(cmn staff treble c4 q)and outputs traditional music notation as postscript images. The above example would generate a file named "aaa.eps" in your home directory that displayed one staff line with a treble clef and a quarter-note Middle C. Visit the CMN home page for more information.
When the CMN output syntax is current the write command creates either .eps (postscript) or .cmn (cmn input) files. .eps files contain a postscript image of our compositional data in common music notation. .cmn files contain input expressions for the CMN program. These expressions can then be edited to produce a high quality manuscript. There is no backward link from .cmn to .cm files, so its best to delay creating .cmn input files until the composition is finished.
Stella [Top-Level]: new thread foo top-level Stella [Top-Level]: go foo Focus: Foo Type: Thread Status: Normal Elements: 0 Start: unset Stella [Foo]: new midi-note Number of midi-notes to create: (<cr>=*) <cr> Slots and values: note (notes c4 d ef f g) rhythm 1 duration .5 amplitude .5 Container position: (<cr>=Foo) <cr> Stella [Foo]: mix foo Select output syntax: midi Current syntax is MIDI. Start time offset: (<cr>=None) 5 Midi port to open: a Wait for the example to finish playing before continuing. Stella [Foo]: syntax cmn Current syntax is COMMON-MUSIC-NOTATION. Stella [Foo]: open aaa.eps Stella [Foo]: write foo Output file:(<cr>=/user/hkt/aaa.eps) Start time offset: (<cr>=None) <cr> Creating cmn score... Manuscripting /user/hkt/aaa.eps... Done! Display file /user/hkt/aaa.eps? (<cr>=Yes) <cr> [In NeXTStep 3.0, Yap should launch with aaa.eps] Stella [Foo]:
begin-beam variable
(begin-beam) variable in list
(begin-beam (meter 2 4)) variable and a function call in list
((meter 2 4)) function call
A single function call directive must be specified as an element in a list because the function call is itself a list.
The next example adds a cmn object to draw a 2/4 meter and another to draw a double bar. The values for data are quoted because they are meaningful only as CMN directives and not as Lisp expressions to evaluate.
Stella [Foo]: new cmn Number of cmns to create: (<cr>=*) 1 Slots and values: data '((meter 2 4)) Container position: (<cr>=Foo) <cr> Stella [Foo]: new cmn Number of cmns to create: (<cr>=*) 1 Slots and values: data 'double-bar Container position: (<cr>=Foo) <cr> Stella [Foo]: list Foo: 1. #<CMN ((meter 2 4)) 140044131> 2. #<MIDI-NOTE | C4| 1| 0.500| 0.500| 0|> 3. #<MIDI-NOTE | D4| 1| 0.500| 0.500| 0|> 4. #<MIDI-NOTE |DS4| 1| 0.500| 0.500| 0|> 5. #<MIDI-NOTE | F4| 1| 0.500| 0.500| 0|> 6. #<MIDI-NOTE | G4| 1| 0.500| 0.500| 0|> 7. #<CMN double-bar 140070361> Stella [Foo]: write foo Start time offset: (<cr>=None) <cr> Output file:(<cr>=/user/hkt/aaa.eps) <cr> Creating cmn score... Manuscripting /user/hkt/aaa.eps... Done! Display file /user/hkt/aaa.eps? (<cr>=Yes) <cr> Stella [Foo]:When viewing the resulting aaa.eps file, note that CMN has also drawn internal bar lines at the appropriate places. This is because we told CMN that our material was in 2/4 meter. In its normal operating mode, CMN makes a whole host of decisions about rules involving metering and layout. We can control these automatic decisions (and much more) by customizing the CMN output stream, which we will lean about in the next two sections.
Stella [Foo]: list io-streams Io-Streams: 1. #<Port: Midi to A> 2. #<File: "/user/hkt/aaa.eps"> Stella [Foo]: show io-streams[1] Object: #<Port: Midi to A> Type: Midi-Stream Status: Normal Slots: Flags 0 Stream A Syntax #<Syntax: MIDI> Port A Direction :IO Stella [Foo]: edit io-streams[1] Editing #<Port: Midi to A> Type ? for help. Edit: ? ? Show this help. DIRECTION Set value of named slot. FLAGS Set value of named slot. PORT Set value of named slot. QUIT Quit Edit. SHOW Show slots and values. STREAM Set value of named slot. SYNTAX Set value of named slot. Edit: show FLAGS 0 STREAM A SYNTAX #<Syntax: MIDI> PORT A DIRECTION :IO Edit: q Stella [Top-Level]:Edit behaves like the top level loop in Stella because they are really the same program with different command sets. Edit builds its command set "on the fly", from the slot names defined in the object to be edited. To change a slot value simply type the name of the slot and its new value.
To customize the size slot to the overall size of the manuscript. The default value is 24.
To customize the metronome "parsing tempo". The default value is 60. The parsing tempo defines how CMN interprets time values..
In the next example the size and metronome values in "aaa.eps" are changed and the manuscript is regenerated:
[Specify the appropriate index for "aaa.eps" in your Io-Streams container]
Stella [Foo]: edit io-streams[2] Editing #<File: "/user/hkt/aaa.eps"> Type ? for help. Edit: metro 120 The value of METRONOME is 120 Edit: size 40 The value of SIZE is 40 Edit: q Stella [Foo]: write foo Start time offset: (<cr>=None) <cr> Output file:(<cr>=/user/hkt/aaa.eps) <cr> Creating cmn score... Manuscripting /user/hkt/aaa.eps... Done! Display file /user/hkt/aaa.eps? (<cr>=Yes) <cr> Stella [Foo]:The third common customization for CMN output streams is the specification of staff descriptions. By default, every container that outputs data is displayed in its own staff, with its name appearing as the staff label in the CMN manuscript and CMN automatically decides which clefs and how many staves should be used. So we only need staff descriptions to specify a staff label different than a container's name, to specify the clef(s) that CMN should use to display data in a staff, or to specify that a sub container should appear in the same staff as its superior. These situations are all addressed by providing a staff description to the staves command inside edit. In the next example a staff named X draws data from the Foo container using the bass clef:
Stella [Foo]: edit io-streams[2] Editing #<File: "/user/hkt/aaa.eps"> Type ? for help. Edit: staves (staves (foo :name "x" :clef bass)) Edit: q Stella [Foo]: write foo Start time offset: (<cr>=None) Output file:(<cr>=/user/hkt/aaa.eps) Creating cmn score... Manuscripting /user/hkt/aaa.eps... Done! Display file /user/hkt/aaa.eps? (<cr>=Yes) Stella [Foo]:See staves in the Common Music Dictionary for more information.
Stella [Top-Level]: {open aaa.eps size 12 metronome 90 cmn::redundant-accidentals nil}The meter, staffer and marker stream attributes control the manner in which data is passed from Stella to CMN. The simplest of these attributes is meter, which allows the global specification of a parsing meter. For example,
Stella [Top-Level]: open aaa.eps meter (meter 2 4) size 16initialize aaa.eps to parse using 2/4 meter. A global meter may be overridden for a particular staff using the staves macro.
staffer controls the mapping of musical data to CMN staves. The value of staffer must be a function. There are currently two staffing functions supplied by Stella. By default, CMN streams use container-staff to map event data to CMN staves. This staffer function places each event in a CMN staff corresponding to the event's container. The staffer function channel-staff places midi notes in CMN corresponding to midi channel information.
The marker slot holds an function that will be called on each event after it has been sent to CMN. The purpose of a marker function is to implement programmatic addition of marks to a CMN note that has just been placed in its CMN staff.
Here is an example of a marker function that was used to output a large section of a string orchestra piece. The music was composed using midi notes in two generators, with channel information representing violins 1 and 2, viola and cello.
;;; this marker adds a wedge to all notes with amplitude > .5 (defun marker2 (stream object) (when (and (typep object 'midi-note) (> (slot-value object 'amplitude) .5)) (let ((staff (gethash (slot-value object 'channel) *cmn-staves*))) (cmn::add-data-1 stream staff (cmn-eval 'wedge))))) Stella [Top-Level]: {open darkling2.cmn staffer channel-staff metronome 75 size 16 meter (meter 24) marker marker2 staves (staves (0 :clef treble) (1 :clef treble) (2 :clef (alto treble)) (3 :clef tenor))} Stella [Top-Level]: syn cmn Stella [Top-Level]: seq sec2a,sec2b
(defmethod write-event ((object midi-note) (stream cmn-stream)) (cmn::add-note-to-staff stream (container-staff stream (slot-value object 'container)) (slot-value object 'time) (slot-value object 'duration) (cmn-eval (slot-value object 'note))))Musical objects have not explicit notion of "staff". The link between an object in Stella and its CMN staff is properly managed by the cmn output stream, which maintains a "dictionary" of staves indexed by object container. To find the staff of an object, use container-staff, passing it the output stream and the object's container. Cmn-eval evaluates a lisp expression in the context of the CMN program. The value of each midi note's note slot is filtered through cmn-eval because the value may be symbolic "note names" like C4 and DS5, which are treated as variables in CMN. C4 is not a variable in Stella and has no meaning other than as a name of a scale degree in the standard chromatic scale. Cmn-eval insures that the C4 symbol in Stella produces the value of the C4 variable in CMN:
Stella [Top-Level]: ,c4 The symbol C4 has no value. Stella [Top-Level]: (cmn-eval 'c4) #<CMN::WRITE-PROTECTED-NOTE 35514351>Finally, before leaving this section switch back to the MIDI syntax. If we were to try to Listen to material while the CMN syntax was current we would not hear anything because the CMN syntax has output methods defined for notation, not listing.
Stella [Top-Level]: syn midi Current syntax is MIDI. Stella [Top-Level]:
Next Chapter
Previous Chapter
Table of Contents