Like Common Music and SmOKe, Score’s internal design is backend agnostic. This means that the representation of data is not tied to a single target music system. Users can use mapping functions to convert note lists generated by Score into a format that works with another system. This may be for use with other computer music systems but may also be used for visualisation or other purposes.
The following shows an example use of Score and
Csound. It uses the gen-notes2
function to generate a note
list from time 0 to 5.0 using 5 fields. The first field is a constant
field that will always generate 1. The rest of the p-fields of the
Csound score is generated using the values provided by within the
score.mask
package.
(def notes
(gen-notes2 0 5.0
1
(gauss 0.5 0.1)
(heap [0.1 0.2 0.4])
(rand-range 0.1 0.25)
(rand-item
["8.00" "8.03" "8.02"])))
(def csound-sco
(format-sco notes))
(println notes)
(println csound-sco)
The results of printing the output are shown below:
;; output from (println notes)
[[1 0.0 0.1 0.1455446063675899 8.02]
[1 0.07388877495229043 0.2 0.11487888605849467 8.00]
[1 0.2684591839186033 0.4 0.12170487899979296 8.00]
[1 1.0558572506209922 0.4 0.13304255988624555 8.03]
[1 1.554791683668857 0.2 0.16436113185377213 8.00]
[1 1.9392915161730429 0.1 0.11907587313489418 8.02]
[1 2.3410899943560195 0.2 0.21996317376289015 8.03]
[1 2.787924993057282 0.4 0.2119026696996974 8.00]
[1 3.7580 770774079575 0.1 0.12327608647786711 8.00]
[1 4.199933807980773 0.2 0.23620482696864334 8.00]]
;; output from (println csound-sco)
i1 0.0 0.1 0.1455446063675899 8.02
i1 0.07388877495229043 0.2 0.11487888605849467 8.00
i1 0.2684591839186033 0.4 0.12170487899979296 8.00
i1 1.0558572506209922 0.4 0.13304255988624555 8.03
i1 1.554791683668857 0.2 0.16436113185377213 8.00
i1 1.9392915161730429 0.1 0.11907587313489418 8.02
i1 2.3410899943560195 0.2 0.21996317376289015 8.03
i1 2.787924993057282 0.4 0.2119026696996974 8.00
i1 3.7580770774079575 0.1 0.12327608647786711 8.00
i1 4.199933807980773 0.2 0.23620482696864334 8.00
The first printout shows the results of running gen-notes2
, which produces a
Clojure list of lists. The second printout shows the result of using the
format-sco
function, provided by Score for formatting note lists into Csound
SCO text format. The csound-sco
text may then be further sent to a running
Csound instance for live score performance or written to disk and later read by
Csound as a SCO file.
At this time, Score only provides output mapping for Csound. However, Score’s
generated note lists are usable as-is with Pink, as both systems are written in
Clojure. In
track1.clj,
growing-line
defines a note list using both features from Score and Pink. The
code first uses two note lists generated using the gen-notes
function that
are concatenated together. This is then mapped over and the growl
audio
function is prepended as the first field of each note in the note list. The e
argument given to gen-notes
is itself a Pink audio function – the env
function – that is wrapped using the !*!
operator. The result is that for
each note, the 6th field will be an instance of env
used as the amplitude
argument to the growl
instrument.
;; from music-examples.track1 example file
(def growing-line
(let [e (!*! env [0.0 400 0.11 5000])
starts (range 0 1.8 (/ 1.0 3.0))
amps (range 0.05 5 0.05)
space (range 0.75 -1.0 -0.25)]
(map #(into [growl] %)
(concat
(gen-notes starts 0.1 :G5 amps e 0.75 space)
(gen-notes starts 0.1 :G3 amps e 0.75 space)
))))
From here, the growing-line
note list is then reused as a
part of a larger measured-score. convert-measured-score
is
used to prodcue to the total score, which is then mapped into Pink
events using the sco->events
function provided in the
pink.simple
namespace.
(defn apply-afunc-with-dur
"Applies an afunc to given args within the context of a
given duration. with-duration will bind the value of dur
to the *duration* Pink context variable."
[afunc dur & args]
(with-duration (double dur)
(apply!*! afunc args)))
(defn i
"Csound style note events: audio-func, start, dur, & args."
[afunc start dur & args]
(apply event apply-afunc-with-dur start afunc dur args))
(defn sco->events
"Converts Csound-style note list into a list of
Pink Events."
[notes]
(map #(apply i %) notes))
The above shows the code for
sco->events
. Given a list of notes,
sco->event
maps an anonymous function that applies the
i
function to the values found in each note. The
i
function in turn applies the event
function to each
note, using apply-afunc-with-dur
as the event’s function –
the one that will fired by Pink’s event processor – with the given
arguments. Finally, when apply-afunc-with-dur
is called, it
fires by processing the values found in the original note, applying the
first field – the audio function – to the rest of the fields.
In the full track1.clj example, these Pink events are further passed to
the add-audio-events
function from
pink.simple
. This is a convenience function that wraps
events with another event that uses the add-afunc
function
to attach audio functions to the root node of the engine. At runtime,
when an event is fired, the nested event will generate an audio function
and the top-level event will add it to the engine for processing.
The mapping of note lists is the technique by which the generated data from Score is connected to other systems. Score currently provides a mapping function for Csound and works out of the box with Pink, as shown in the example code. In the future, more mappings could be provided with Score, such as MIDI, OSC, and MusicXML. As the data generated from Score is plain Clojure list data, users can create their own mappings relatively simply.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close