Design

Score uses a functional programming approach to model musical scores using data and functions separately, rather than using objects which combine state and behavior. Notes (i.e. events) are represented using standard Clojure list data structures filled with values. The meaning of each value field of a note is entirely determined by the user. Scores (i.e., note or event lists) are lists of lists (i.e., notes) and they may be hierarchically organised by embedding one within another. Score provides functions for generating and transforming flat note lists as well as organising functions to transform hierarchical lists into a flattened total score. Once a total score is produced, users can use Score’s mapping functions to map the data into a format suitable for a target music system. Score also provides a set of music value functions for generating values and transforming values from one format to another. Score’s concepts map closely to those found in SmOKe (i.e., Music Magnitudes, Events, EventLists, EventGenerators, EventProcessors, and Voices).

Score is designed for use within Clojure code. Users may explicitly write out each note and organise them into lists, use code to generate and process note lists, or use a combination of the two together. By offering both hand-written notation and score generation, Score allows users to work with both the “score as data” approach found in Music-N systems as well as the “score as program” approach found in Canon.

The model of notes as a list of values, and scores as a list of notes, is very flexible. Users can use standard Clojure functions such map, filter, reduce to process the notes. They can further use functions like concat and mapcat to join together smaller blocks of notes into larger blocks. This allows a bottom-up composing of scores that has similarities to Western Music concepts of notes, phrases, sections, and movements.

Score’s design is backend agnostic, meaning the internal representation is not designed for any specific target music system. The user can take a full list that represents a total score for a work, then do a final processing step to map the notes to a target format. This approach is exemplified in Common Music and SmOKE, where one develops their work with an internal score model and generates output as MIDI, Csound SCO, or other format.

Beyond the internal design, Score, like Pink, is designed as a library and not a system. Users can create works that depend upon a specific version of Score, and their work will continue to function even if newer versions of Score are produced. Also, Score has no other dependencies outside of Clojure itself, which simplifies the introduction of Score into a project. Finally, Score is designed to interoperate well with Pink, and vice versa.