Score Organization
With a bottom-up approach to music making, one might first start with building up small units of music. This could be a drum pattern, a melodic line, a granular cloud, a processed sample of sound, or more. Once smaller units are created, it is natural to build up larger units of music, which in turn may be used to build up even larger units of music. This framework or approach to music making has been used long before computers, and numerous approaches have been taken within computer music. (The music system HMSL has been very inspiring for this work.)
Score offers two primary functions for higher level organisation of music: convert-timed-score
and convert-measured-score
. The two functions take in list data structures written in timed- or measured-score formats. They will process the score formats and yield a single, flattened note list. The two functions operate similarly with the exception of how they work with time specifications. They are described with examples below.
convert-timed-score
convert-timed-score
allows the user to organise smaller blocks of score into a larger score. The user specifies a list of values that can either be numbers or note lists. If a number is encountered, it sets the current time for note list start time translation. If a note list is encountered, it will be translated in time by the current time. For note lists, convert-timed-score
requires that the second field of each note be a value for a start time.
The following shows an example usage of convert-timed-score
. First, a score fragment is explicitly written out by hand and assigned to the pattern variable. Second, the score
variable is defined in the timed-score format. It reads as “at time 0.0, play pattern, and at time 4.0, play the pattern again”.
(def pattern
[['bass-drum 0.0 0.5]
['bass-drum 1.0 0.5]
['bass-drum 2.0 0.5]
['bass-drum 3.0 0.5]])
(def score
[0.0 pattern
4.0 pattern])
(println (convert-timed-score score))
The following shows the note list generated by calling convert-timed-score
with the score
variable.
([bass-drum 0.0 0.5]
[bass-drum 1.0 0.5]
[bass-drum 2.0 0.5]
[bass-drum 3.0 0.5]
[bass-drum 4.0 0.5]
[bass-drum 5.0 0.5]
[bass-drum 6.0 0.5]
[bass-drum 7.0 0.5])
convert-timed-score
also allows for multiple note lists to be used for a given time. The following shows an example where two note lists, bd-pattern
and snare-pattern
, are used together in the timed-score.
(def bd-pattern
[['bass-drum 0.0 0.5]
['bass-drum 1.0 0.5]
['bass-drum 2.0 0.5]
['bass-drum 3.0 0.5]])
(def snare-pattern
[['snare-drum 1.0 0.5]
['snare-drum 3.0 0.5]])
(def score
[0.0 bd-pattern
4.0 bd-pattern snare-pattern])
(println (convert-timed-score score))
The resulting processed score would be:
([bass-drum 0.0 0.5]
[bass-drum 1.0 0.5]
[bass-drum 2.0 0.5]
[bass-drum 3.0 0.5]
[bass-drum 4.0 0.5]
[bass-drum 5.0 0.5]
[bass-drum 6.0 0.5]
[bass-drum 7.0 0.5]
[snare-drum 5.0 0.5]
[snare-drum 7.0 0.5])
Since the notes lists are just lists, users can hand-write blocks of notes, use note-processing functions, and use note-generating functions within a timed score. For example:
(def score
[0.0 bd-pattern
4.0 (process-notes bd-pattern 2 #(* % 0.5))
snare-pattern
[['single-shot-sample 2.0 2.0]]])
(println (convert-timed-score score))
shows an example of using inline hand-written note lists and function calls within a time-score. In the example, the second use of bd-pattern
has been processed with the process-notes
function, such that the 3rd field of each note has its value multiplied by 0.5. Also, a single-shot-sample note has been introduced to the score, written in by hand. Results of processing are shown below.
([bass-drum 0.0 0.5]
[bass-drum 1.0 0.5]
[bass-drum 2.0 0.5]
[bass-drum 3.0 0.5]
[bass-drum 4.0 0.25]
[bass-drum 5.0 0.25]
[bass-drum 6.0 0.25]
[bass-drum 7.0 0.25]
[snare-drum 5.0 0.5]
[snare-drum 7.0 0.5]
[single-shot-sample 6.0 2.0])
convert-timed-score
provides users a way to organise score fragments in time. The results from calling this function is a flattened note list. This note list may in turn be assigned to a variable and used within other calls to convert-timed-score
.
convert-measured-score
convert-measured-score
operates similarly to convert-timed-score
, but uses the measure as a unit of time rather than a time value. The measured-score is also a list, but begins with a :meter definition. Following the meter, values may be either numbers or lists, just as in timed-scores, but the numbers are interpreted as measure numbers. The following:
(def score
[:meter 4 4
0 bd-pattern
1 bd-pattern snare-pattern])
(println (convert-measured-score score))
shows an example usage of convert-measured-score
. The score reads as “with a 4/4 meter, at measure 0, play bd-pattern, and at measure 1, play bd-pattern and snare-pattern”. Start time values for notes are interpreted as beats, and beats map to quarter note values of the meter. The results are shown below.
([bass-drum 0.0 0.5]
[bass-drum 1.0 0.5]
[bass-drum 2.0 0.5]
[bass-drum 3.0 0.5]
[bass-drum 4.0 0.5]
[bass-drum 5.0 0.5]
[bass-drum 6.0 0.5]
[bass-drum 7.0 0.5]
[snare-drum 5.0 0.5]
[snare-drum 7.0 0.5])
convert-measured-score
allows for multiple note lists to be used per measure. Also, users may use in-lined, hand-written note lists and function calls embedded within measure-scores just as they would with timed-scores. For musical genres that use a regular, measured framework of time, using convert-measured-score
may be more convenient to use and think with than using convert-timed-score
. Choosing between one or the other system of time will be dependent upon the user’s own musical goals.
convert-measured-score
and convert-timed-score
simply process score lists and generate a note list. The results of these functions may themselves be further processed. This allows the user to mix usage of each time system. For example, if one was working on a film score, one could use measured-score to write the main music track and use a timed-score to add sound effects according to clock time. The user could then use concat
to merge the two scores together.