This is cmn.txt in view mode; [Download] [Up]
This version of the cmn documentation omits all the graphics and font-related
stuff of the original (cmn.wn, cmn.rtfd).
COMMON MUSIC NOTATION
cmn is a simple little hack that can create and display traditional
western music scores on the NeXT. It does not hope to replace
existing music publishing programs -- Score and Finale have a 20 year
head start; instead, cmn provides a way to translate a clm note list
into a traditional score, and a way to turn out editable cmn
PostScript files for cut and paste operations within the NeXT software
world. cmn is free, available via anonymous ftp from ccrma-ftp as
pub/Lisp/cmn.tar.Z. It is built on top of Common Lisp and CLOS
(available free as pcl -- pub/Lisp/pcl.tar.Z), and currently uses the
Sonata font. It still has a few glaring omissions, but I hope to
bring it closer to completion as time goes by. In any case, the
sources are free, so don't hesitate to hack away at them. As an
example of how cmn works in general, the lisp expression:
(cmn staff treble c4 q)
produces the file "aaa.eps" (the default value of
*cmn-output-pathname*). If the variable *cmn-preview* is "open" (on
the NeXT) or t (on the Mac), the results are displayed automatically.
cmn is our main function. It reads in all its arguments, organizes
the musical data into systems and staves, adds line and page breaks,
beams, ties, slurs, dynamics, and so on, aligns and justifies the
result, and produces an "encapsulated PostScript" file (aaa.eps in
this case). The basic nomenclature is that of Score or Common Music.
c4 is middle c, q means quarter note, and so on. In its most general
use, cmn has the following form:
cmn overall-score-attributes systems
The overall-score-attributes control global graphics decisions such as
overall size, page width, beam thickness, and so on. Say we want to
produce a smaller version of our previous example. The default size
is 40; we'll set it to 24:
(cmn (size 24) staff treble c4 w double-bar)
The systems contain all our musical data. Each system is a group of
related staves, normally bracketed together and separated vertically
from other systems. Each staff contains the actual notes and whatnot.
If no system is given explicitly, one is created automatically.
Similarly, if no staff is given, one is provided automatically.
Here's an example of a score with two systems, one of which has two
staves:
(cmn (size 24)
(system brace
(staff treble (meter 6 8)
(c4 e. tenuto) (d4 s) (ef4 e sf)
(c4 e) (d4 s) (en4 s) (fs4 e (fingering 3)))
(staff treble (meter 3 4)
(c5 e. marcato) (d5 s bartok-pizzicato) (ef5 e)
(c5 e staccato tenuto) (d5 s down-bow) (en5 s) (fs5 e)))
(system bracket
(staff bar bass (meter 6 16)
(c4 e. wedge) (d4 s staccato) (ef4 e left-hand-pizzicato)
(c4 e tenuto accent rfz) (d4 s mordent) (en4 s pp) (fs4 e fermata))))
Each score object (c4, or staff, for example) is both a constant and a
function. In its existence as a constant, it provides access to all
the defaults that surround that object. As a function, it accepts any
number of arguments adding or changing attributes. In normal CLOS
syntax, we would call setf on the slots of the associated instance
variable, but that's a lot of typing, requires that I document the
accessors, and makes it hard to see the musical data for all the
parentheses and local bindings. So, the standard way in cmn to modify
an object is to pass the modification as an argument to the object.
That is,
(c4 q staccato)
creates a middle-c object, sets its duration fields to reflect the
value of a quarter note, and adds a dot for staccato. In simple
cases, this is exactly the same as
c4 q staccato
encountered in the staff data list. The staff function notices
sequences of notes and associated data and packages them up for you,
just as if you had put in the parentheses by hand. You do have to use
parentheses when ambiguities might otherwise develop. We could have
written our previous example as:
(cmn (size 24)
system brace
staff treble (meter 6 8) c4 e. tenuto d4 s ef4 e sf
c4 e d4 s en4 s fs4 e (fingering 3)
staff treble (meter 3 4) c5 e. marcato d5 s bartok-pizzicato ef5 e
c5 e staccato tenuto d5 s down-bow en5 s fs5 e
system bracket
staff bar bass (meter 6 16) c4 e. wedge d4 s staccato
ef4 e left-hand-pizzicato c4 e tenuto accent rfz
d4 s mordent en4 s pp fs4 e fermata)
I find the first form easier to read, but I'm used to Lisp's
parentheses. I haven't completely cleaned up all the left over cases,
so there are still a few places where parentheses are needed. cmn,
system, and friends are functions, not macros, so the streams of data
are interpreted as straightforward Lisp arguments to a function. The
screen resolution is less than most printer resolutions, so sometimes
the image displayed on the screen is slightly ragged due to round off
errors and so on (the bracket in the example just given is a case in
point). In the code examples that follow, I'll omit the arguments,
like (size 24), that aren't completely germane to the discussion.
cmn overall-score-attributes systems
overall-score-attributes set various decisions that affect the layout
of the entire score. Except for the page-layout related variables
(page-width, et al), all distances are in terms of staff heights --
normal staff is 1.0 high, and everything else is keyed to that. If
you want to use centimeters rather than inches, and European paper
sizes rather than American, set the variable *cmn-units* to :cm. It
defaults to :inches. The attributes can be any of the following:
output-file "aaa.eps" (if name ends in "-1", subsequent files count up from there)
output-type :postscript :quickdraw is the other possibility
size 40 overall size scaler
automatic-line-breaks t should line breaks be added by cmn
automatic-octave-signs t should octave signs be added by cmn
automatic-beams t should beams be added by cmn (see beaming meter message)
automatic-ties t should ties be inserted by cmn
automatic-bars t should bars be inserted by cmn
automatic-rests t should rests be inserted by cmn
automatic-naturals nil should naturals be inserted by cmn
automatic-beat-subdivision-numbers t should irregular subdivisions be numbered by cmn
automatic-measure-numbers nil can be t = 1, a number, :by-line, or :by-page
curvy-flags t curved or straight flags (see below)
use-italian-octave-signs nil do we add "va" to "8" and "ma" to "15"
add-bassa-to-octave-signs nil do we add "bassa" as well
use-abbreviated-staff-names t after first use, is name abbreviated?
always-show-staff-names t should staves continue to be named after 1st
all-output-in-one-file nil put page breaks in output file (rather than separate files)
implicit-accidental-style :new-style various ways to handle implicit accidentals
implicit-accidental-duration 1
redundant-accidentals t if nil, cancel redundant accidentals
layout nil for complicated staff layouts -- see page 34
page-height 11.0 (29.7) inches (cm) -- cm if *cmn-units* = :cm
page-width 8.5 (21.0) inches (cm)
left-margin 0.5 (1.0) inches (cm)
right-margin 0.5 (1.0) inches (cm)
header-margin 1.0 (2.0) inches (cm)
footer-margin 1.0 (2.0) inches (cm)
title nil
metronome 60 for add-note and friends
line-separation 2.0 white space between lines of music
staff-separation 1.5 white space between staves
system-separation 1.5 white space between systems
note-head-size 1.0 overall scaler on size of note heads (default is a bit small)
grace-note-size .5
tie-thickness .04 fatness of ties
tie-curvature .125 how curved ties try to be
slur-thickness .03 how fat slurs get (this is a skinny default)
slur-curvature .25 how curvy slurs try to be (this is pretty flat)
maximum-slur-slope .75 how steep slurs can get
beam-spacing (* 2.125 .126) distance between beams
beam-width (* 1.125 .126) fatness of beams
beam-slope-trigger .5 min ambitus for sloped beam (.5=half octave)
maximum-beam-tilt .4 how tilted beams are allowed to be
partial-beam-length .4 max length of a partial beam
partial-stem-length 0 set this >0 if you want partial stems
stem-width .025 width (fatness) of stem
ideal-stem-length .5 first stab at basic stem length
staff-line-width .02 thickness of staff lines (most use thicker lines than this)
staff-name-font "Times-Roman" instrument names prepended to staves
staff-name-font-scaler .4
staff-name-font-minimum-size 8
text-connecting-pattern '(10 0) default is an undashed line
first-measure-number nil where to start the automatic measure numbering
initial-onset 0 score start time (to avoid lots of initial rests)
full-last-line nil should last line be full length no matter what
page-hook nil used for page related actions (see cmn-ex.lisp)
line-hook nil used for line related actions
free-expansion-factor 1.25 white space added during justification
Unless otherwise stated, all of the numbers are in units of
staff-heights. That is, a normal five line staff is 1.0 high. The
function in-inches (in-cm) translates from inches (cm) to cmn units.
Say, for argument, that you want fatter beams:
(cmn (beam-width .275) (beam-spacing .4) staff treble c4 s d4 s)
The curvy-flags attribute controls whether flags are curved or straight:
(cmn (curvy-flags nil) staff treble a4 s)
The actual contents of the score are the next arguments to cmn. All
the entities that specify either a musical object or some attribute of
that object use the same syntax, and can accept the same "messages".
Any object or group of objects can be rotated, scaled (that is
stretched in the horizontal and/or vertical direction), and moved to
any location in the score. Any arbitrary file of graphics commands (a
.eps file) can be treated as an object just like any other object, and
cmn can be called recursively, packaging up entire scores within other
scores. Finally, it is relatively easy to integrate your own graphics
hacks into cmn (see page 29). In what follows, I will use the name
"message" for a function that affects the thing it is an argument to.
That is, in the expression
(meter 6 8 (meter-size 2))
the expression "(meter-size 2)" is hereby designated a "message" to
the object created by the meter function. "6" and "8" are ordinary
arguments, "meter" is a function that creates a score object. In this
case, the effect of the message is to double the size of the meter
numbers:
(cmn treble (meter 6 8 (meter-size 2))
All the musical data is organized into a list of systems, each system
containing a list of staves, each staff containing a list of objects
like notes, rests, and so on, and each object containing a variety of
lists describing its attributes. Systems and staves are created
automatically if not specified in the arguments to cmn. That is, (cmn
system staff treble) is the same as (cmn treble) but in more
complicated cases, it is better (and sometimes necessary) to be
explicit about groupings. In addition to the built-in entities, any
function encountered in the list of cmn arguments is (of course)
evaluated and the result (either one object, or a list of objects) is
spliced into the data as though it had been written explicitly,
providing a simple and extremely powerful way to call on the full
resources of lisp. A few such functions are provided by cmn, and
examples of others will be given below.
In the following discussion of the various things cmn knows about, it
should be kept in mind that any object not only reponds to the
standard messages like rotate or x0 (all of which are listed below),
but can also have attached to it a list of "marks". A "mark" is any
arbitrary code you want associated with some other object (itself a
"mark" in some cases), and evaluated whenever its owner is evaluated
(displayed). A staccato dot, for example, is a mark attached to a
note. Its associated code figures out where the center of the note
is, which side (up or down) the dot belongs on, and how far away it
should be (to avoid collision with staff lines, for example). This
code gets called when we want to display an object or find out how big
it is. The standard messages are:
dx dy x0 y0 x1 y1 center justification
dx and dy normally affect the placement of the object relative to
whoever owns it. A note, for example, is owned by the staff it is on,
and travels around with that staff as lines and pages are justified.
The note may itself own a staccato mark, which travels around with the
note as it finds its vertical position on the staff. Very often the
point (x0,y0) is the lower left corner of the object, and (x1,y1)
marks the upper right corner of the "bounding box" of the object. Not
all objects know about center, but those that do return the musical
center point of the object (the point used to align things across
staves and so on). For example, say we want to push a marcato mark
over to the right:
(cmn (staff treble (c4 w (marcato (dx .5)))))
matrix
An object's matrix controls its orientation and placement relative to
whoever owns it. There are a variety of functions provided to make it
easier to deal with coordinate transformations:
rotate angle ; rotates the current object counterclockwise by angle degrees.
scale x y ; stretches or compresses the object by x and y (as multipliers)
; (scale 0 0) or invisible makes the current object invisible
mirror (function) and mirrored (variable) ; the same as (scale -1 1)
transform matrix ; multiplies the current object's matrix by matrix
pattern
An object's pattern controls how it is drawn (its "ink") -- on NeXT
3.0 you have access to the full pattern facility of Postscript. Two
built-in functions provide gray scales and outlines:
gray-scale val ; 0 = black (the default), 1 = white, val is between 0 and 1
outlined val ; 0 = thinnest outline, val is an integer
(cmn staff (treble mirrored (dx .5))
(treble (rotate 180) (dy .75) (scale -2 .5))
(bass (gray-scale .5) (dx .75))
(bass (outlined 2) (dx .75))
(quarter-rest (rotate 45) (dx .5) (scale 1 2))
(eighth-rest (rotate 90) (dy -.4) (scale 2 1)))
system &rest objects
Each score is organized into groups of related staves, each such group
called a system. The system function is much like the cmn function --
it tries to organize its arguments into system-wide marks and staves
full of musical objects. The main objects that a system notices are
staff objects and system-wide brackets. The two kinds of brackets are
bracket and brace. If a staff has both a bracket and a brace (divided
strings in an orchestral score, for example), put the bracket on the
system, and the brace on the lower of the staves:
(cmn (system (staff)) (system bracket (staff) (staff brace) (staff)))
If a mark occurs before any staff has been created, it is attached to
the system as a whole. Anything else is assumed to belong to the
current staff.
staff &rest objects
staff-name staff-size staff-lines tied-to start-line
Each staff treats its arguments much as cmn and system do -- it tries
to collect everything into key signatures, meters, clefs, bar lines,
notes, chords, and so on. A staff has an optional name (normally the
instrument associated with that staff), a size (a multiplier on the
y-extent of everything on that staff), a number of lines (normally 5),
a list of marks, and a list of objects.
(cmn (staff (staff-name "E-sharp Bazooka") (staff-lines 2) (e4 w fff))
(staff (staff-name "c-flat Clavicle") (staff-lines 0) treble d4 q c5 h.)
(staff (staff-name "Violin") (staff-size .5) sub-bass g2 h c2 h))
If the staff name has "-flat" or "-sharp" after the first letter, the
musical symbol is used instead. Unless you say otherwise (via the
score slots always-show-staff-names and use-abbreviated-staff- names),
subsequent lines of a staff try to use an abbreviated version of the
instrument name. The tied-to message overlays staves (see page 12).
You can set the staff position and extent using dy, x0 and x1. For
example, to get an empty staff 3 inches long:
(cmn (staff (x1 (in-inches 3))))
to get a score printed vertically:
(cmn (transform '(0 1 -1 0 200 200)) (staff (x1 7.5) treble c4 e d4 e))
or to make a piece of blank music paper:
(cmn (header-margin 0) (engorge
(loop for i from 0 to 6 collect (staff (x1 (in-inches 7.5))))))
If a staff is passed the gray-scale message, everything on the staff
is printed with that color. The message start-line is useful with
percussion parts -- it specifies which line to start with (3=mid).
bar &rest objects
bar double-bar interior-double-bar
dashed-bar full-double-bar full-bar
begin-repeat-bar end-repeat-bar
begin-and-end-repeat-bar full-interior-double-bar
begin-and-end-repeat-bar-without-thin-lines
begin-and-end-repeat-bar-with-one-thick-line
(cmn (size 24) bar c4 q begin-and-end-repeat-bar c4 q interior-double-bar
c4 q dashed-bar c4 q begin-repeat-bar
c4 q end-repeat-bar c4 q double-bar)
If a bar occurs as the first or last thing on a staff, it is left or
right justified to the beginning or end of that staff. The "full"
bars continue across system breaks. These take the additional
messages
double terminal justification within-measure
dashed dots-left dots-right broken
thickness breathing-space
justification can be nil, :right, or :left.
within-measure is t if the bar (normally a repeat bar) has no metrical significance.
broken determines whether the bar continues across system breaks.
thickness and breathing-space apply to the double-bar
bracket &rest objects
brace &rest objects
The brace is a piano-style curly-bracket. It should be placed on the
lower of the two staves. Bracket can cover any number of staves; to
get a brace over many staves use the brace-staves message.
clef &rest objects
french-violin treble tenor-treble
soprano mezzo-soprano alto tenor baritone baritone-C
baritone-F bass sub-bass double-bass
percussion
(clef treble ...) is the same as (treble ...).
(cmn staff french-violin c4 q treble c4 q soprano c4 q mezzo-soprano c4 q
alto c4 q tenor c4 q baritone c4 q bass c4 q sub-bass c4 q)
If a staff has no clef, it is given one (for note placement
decisions), but it is scaled (by 0 0) to be invisible. Clefs take the
additional messages unjustified and breathing-space. (Tenor-treble is
a treble clef with an "8").
accidental &rest objects
sharp flat natural double-sharp double-flat
small-sharp small-flat small-natural
(cmn staff treble g4 q gs4 q gf4 q gn4 q (g4 q double-sharp)
(g4 q double-flat) (g4 q natural-sharp) (g4 q natural-flat))
When used with notes, use either the cs/cn/cf notation or the sign
function; when used with ornaments, use ornament-sign; in text it is
probably simplest to switch for one character to the Sonata font and
use # for sharp, b for flat, n for natural, \272 for double-flat and
\334 for double- sharp. The file quarter.lisp implements one form of
quarter-tone accidentals.
key &rest objects
c-major a-minor cs-major as-minor df-major bf-minor
d-major b-minor ef-major c-minor e-major cs-minor
f-major d-minor fs-major ds-minor gf-major ef-minor
g-major e-minor af-major f-minor a-major fs-minor
bf-major g-minor b-major gs-minor cf-major af-minor
To cancel a key signature (i.e. put naturals where the accidentals
would normally be), use cancel key. For funny key signatures, use
def-key. Here the name of the key is followed by the note names
corresponding to the accidentals as displayed in the treble clef.
(def-key foo-major bf4 ef5 fs5)
(cmn staff tenor b-major c4 q
bar (cancel b-major) ef-major c4 q bar bass foo-major c4 q))
meter numerator denominator &rest objects
meter displays a meter and sets the staff's current meter (for beaming
decisions and so on). Numerator and denominator can be integers,
strings, or symbols. The named meters are
alla-breve common-time cut-time unmetered
(cmn staff treble (meter 6 8) c4 h. bar (meter '5+7 8) c4 w
bar cut-time c4 w bar (meter 2 2 in-parentheses (dx .1)) c4 h
bar (meter 9 8) (meter '4+5 8 (dx .1) in-parentheses) c4 w
bar (meter 3 2 note-head-denominator) c4 h
bar (meter 3 4 suppressed-denominator (meter-size 2)) c4 q.)
The size of the meter numerals can be changed with the message
meter-size. If you want beaming decisions to follow a meter without
any meter being displayed, set the meter-size to 0. Meter takes the
additional messages: suppressed-denominator, note-head-denominator,
and beaming. The beaming message affects the automatic beaming
decisions -- see cmn-ex.lisp for examples.
note &rest objects
The standard Score or Common Music note names c0..bs8 are all built-in
both as constants and as functions. c4 is middle-c; cf4 is a semitone
from c4, and bs4 is a semitone from b4. As a function, each takes all
the usual messages. Onset times and durations are handled in terms of
quarter notes, independent of the actual tempo. That is, the message
(onset 2.5) means the note in question starts at the time of the
2.5-th quarter note -- the true time in seconds is of no interest to
us. Similarly, (duration .5) means an eighth-note, no matter what the
tempo or meter are. The only place this might cause confusion is in
compound meters (6/8) where we are still calculating onsets and
durations in quarter notes, not 1.5 quarter notes. Unfortunately
western music notation has some peculiar special cases involving
measured tremolos and so on -- these will be treated as we get to
them. The rhythmic values can be:
double-whole whole half quarter eighth sixteenth
thirty-second sixty-fourth one-twenty-eighth
64th 64th. 32nd 32nd. 16th 16th. 8th 8th.
q q. q.. h h. h.. w w. dw e e. e..
s s. s.. ts te tq th te. tq. ts. q... h...
ts stands for triplet-sixteenth. The periods indicate dotted rhythmic
values. That is, q. is a dotted quarter. In general, (rq n) produces
a rhythm object with a rhythmic value of n quarter notes. q = (rq 1),
tq = (rq 2/3), a quintuplet eight is (rq 2/5) and so on. Use the
ratio form of the value so that cmn has some chance of telling that
you really mean a triplet 17-th. The numbers and brackets marking
irregular beat divisions are normally added automatically by cmn.
When notes are not simply marching along one after the other, you can
use the onset message to set the onset times explicitly (or use the
beat message which is relative to the measure onset and numbers the
beats starting at 1). Additional messages to note are:
line note-head sign cclass pitch octave
head-quarters tie-direction stem-dy
stem-direction stem-up stem-down no-stem
in-parentheses slur-direction note-head-size
Stem direction is either :up, :down, :none, or nil. If the latter,
cmn tries to decide from the context which direction to draw the stem.
:none means "don't draw a stem". stem-up, stem- down, and no-stem are
also variables.
(cmn staff treble (c4 h (onset 0) stem-down) (c5 e (onset 0) stem-up)
(b4 e (onset .5) stem-up) (a4 q (onset 1.0) stem-up))
It is a bother to keep track of onsets, ties, and so on when there are
several voices on a staff. For this case, put the voices on separate
staves, then tie them together using the tied-to message:
(cmn (setf s1 (staff treble (meter 6 8) a4 e a4 e a4 e a4 q.))
(staff (tied-to s1) (d4 q. stem-down) (d4 q. stem-down)))
Note-head describes what kind of note head you want. Nil, the
default, is the same as :normal and produces a normal note head.
Other types are :diamond, :triangle, :square, :x,
:artificial-harmonic, :tremolo, :slash, :none. The note-head can also
be any arbitrary mark (graphics code) you want -- it will be placed
where the note head would otherwise have gone.
(cmn (size 24) staff treble
(c4 e (note-head :square))
(e4 e (note-head :x))
(g4 q (note-head :triangle)))
Additional attributes of a given note are simply added to the list of
arguments, and it is normally up to the individual marks and cmn to
sort out who goes where.
chord &rest objects
Chord produces a chord. One of the arguments to chord should be
notes &rest ns
(cmn staff treble
(chord (notes e4 g4 f4 a4 c5 b4 d5) s stem-down)
(chord (notes e5 g5 f5 a4 c5 b4 d5) s)
(chord (notes cn4 ef4 gn4 bf4 ds5 fn5) e stem-down))
Messages to the chord object (ties, note-head shapes, rhythmic values,
and so on) affect every note in that chord. To set some attribute of
just one note in a chord, pass it as a message to that note within the
notes list. Chords across staves use the tied-to message (see
cmn-ex.lisp).
(cmn staff treble
(chord (notes c4 e4 g4) q (note-head :diamond))
(chord (notes (c4 (note-head :diamond))
(e4 (note-head :triangle))
(g4 (note-head :x))) q))
auxiliary-note &rest objects
auxiliary-note creates a mark that contains a (small) note. It is
normally used in situations like harmonics where we sometimes want to
display a little note where the true pitch is. The arguments to
auxiliary-note are exactly the same as those to note.
(cmn staff treble (c4 q (note-head :diamond)
(auxiliary-note c6 no-stem in-parentheses)))
grace-note &rest objects
grace-notes &rest objects
appoggiatura &rest objects
stem-direction slashed slurred
unjustified stem-dy slash-thickness
Stem-direction is normally :up. Slashed is t for grace-notes and nil
for appoggiaturas. Slurred is t for both. Slurs are very hard to get
right automatically in all cases. See more discussion under slur
below. If you don't want extra room provided for the grace note or
appoggiatura, use the message unjustified. For multiple grace notes,
the default is to place two beams on two and three such notes, and
three beams on more than three. This can be over-ridden simply by
specifying explicitly the rhythm you want:
(cmn staff treble
(g4 q (grace-note fs4))
(g4 q (grace-note (slurred nil) (stem-direction :down) b4
(note-head :diamond) staccato tenuto wedge fermata))
;; omit the slur and use a diamond head on the grace note
;; and get very confused about articulation
(g4 q (grace-note e4 fs4)) (g4 q (grace-note gf4 ef4))
(g4 q (grace-note (slashed nil) b4 a4)) ;; omit the slash
(b4 q (grace-note d4 e4 fs4 g4 a4))
(g4 q (grace-note ef5 e bf4 e ef4 e))) ;; just one beam on the grace notes
Appoggiaturas are similar to grace notes in that they are normally
displayed in a smaller size than the normal notes, and are not
explicitly lined up in terms of onset and duration (the main note is
aligned and the little notes tag along behind). Appoggiaturas in cmn
assume that you don't want a slash through the beam or flag, and that
the default rhythmic value is eighth note. The syntax is otherwise
the same as that for grace notes.
Rests
rest &rest objects ;rest-1 used to be the name of this function
double-whole-rest whole-rest measure-rest dotted-whole-rest
half-rest dotted-half-rest quarter-rest dotted-quarter-rest
eighth-rest dotted-eighth-rest sixteenth-rest dotted-sixteenth-rest
thirty-second-rest sixty-fourth-rest one-twenty-eighth-rest
(cmn staff treble bar whole-rest bar half-rest
quarter-rest eighth-rest sixteenth-rest
thirty-second-rest sixty-fourth-rest
one-twenty-eighth-rest bar (measure-rest 23) bar)
Unless you indicate otherwise (via (automatic-rests nil)), cmn adds
rests wherever note onsets and previous durations seem to have left a
gap:
(cmn staff treble (c5 s (onset .75)) (g4 e. (onset 1.25)))
cmn-ex.lisp and rests.lisp contain abbreviations for common rest names
and code for other kinds of rests, such as slanted measure rests.
dynamics &rest objects
ppp pianississimo pp pianissimo p piano
mp mezzopiano pppp ffff
fff fortississimo ff fortissimo f forte
mf mezzoforte sff spp
sf sforzato sforzando forzando fz fp
rfz rinforzando sfp sfz
If you want some other indication, try dynamic n. Crescendo wedges
are handled separately (see crescendo below), and connected text like
poco a poco is handled as connected-text. An example of the dynamic
function is (cmn staff treble c4 q (dynamic "fffffff")).
Articulation
staccato accent little-swell wedge
tenuto marcato down-bow up-bow
detache martele thumb natural-harmonic
stopped-note open-note pedal
bartok-pizzicato (snap-pizzicato) left-hand-pizzicato
The long example given on page 2 uses most of these marks.
Little-swell takes an optional dynamic mark. Marcato and the
pizzicatoes take the optional message thickness. Pedal.lisp provides
support for the three piano pedals and explicit pedalling. See also
accent.lisp and percussion.lisp for 20-th century markings such as:
Ornaments
mordent inverted-mordent double-mordent turn
short-trill trilled-turn trill
Each of these has an optional sign (ornament-sign). Trill takes
several addditional messages -- the main issue here is how to
display the details of the trill. The options are:
sign-position other-note wavy-line wavy-time
sign-position can be :right (the default), :up, or :in-parentheses.
wavy-line creates a wavy line to the next note. wavy-time sets the
end point (in onset-style values) of the wavy line (the default is the
note's end time). Wavy-line's argument can be t, nil, or a list; if
the latter, the arguments are considered '(dx0 dy0 dx1 dy1) to make it
easier to extend the line in various ways.
(cmn staff treble c5 q mordent c5 q turn c5 q short-trill
c5 q trilled-turn c5 q trill c5 q (mordent (ornament-sign small-flat))
(c5 q (trill (sign-position :up) (ornament-sign small-natural)))
(cs5 q (trill (ornament-sign small-sharp) (sign-position :in-parentheses)))
(c5 q (trill (wavy-line t))) (c5 q (trill (ornament-sign flat))))
arpeggio arrow arrow-up arrow-down no-arpeggio
These articulation marks apply primarily to chords. The arpeggio mark
can have an arrow at the top or bottom. No-arpeggio is a bracket on
the left side of the chord.
(cmn staff treble
(chord (notes c4 e4 g4) h (arpeggio arrow-down))
(chord (notes c4 e4 g4) h arrow-up)
(chord (notes d4 g4 e5) h no-arpeggio))
fingering &rest objects
Fingering takes, in addition to the usual arguments, any number of
numbers which are then displayed in a vertical stack above or below
the object. fingering-size and fingers exist. The arguments to
fingering can also be strings or text objects.
(cmn staff treble (e4 q (fingering 3))
(chord (notes c5 g4) q (fingering 7 2)))
pause &rest objects
breath-mark general-pause g.p. grand-pause
fermata upside-down-fermata hold
caesura pause
(cmn staff treble (meter 2 4)
(c4 q fermata) (quarter-rest g.p.) (c4 q breath-mark)
(c4 q upside-down-fermata) double-bar)
text &rest objects
Text is a form of mark like staccato. The text can be in any
available font, and, as usual, scaled, rotated, etc. The default font
is given by the slot text-font. The font-related messages are:
font-name font-size font-scaler ;font-name default is "Times-Roman"
(cmn staff treble
(c4 q (text "middle-c" (dx 1.0) (dy 2.0) (rotate 180)
(font-name "Times-Roman") (font-size 12))))
In addition to the default justification (:left), the text can be
unjustified, centered (:center) or right justified (:right) -- (text
"hi" (justification :right)). (Unjustified = (justification :none)).
Connected text is handled by text- and friends discussed below.
font-size is the true size (unscaled), whereas font-scaler scales the
font-size by the overall score size. The message unjustified tells
cmn not to try to make plenty of room for the text. Text placement
normally is anchored to the owning object (the c4 in our previous
example), but this can cause endless positioning headaches for lyrics
and whatnot. For special cases, use the messages x and y. These are
either nil (the default) or a lambda form that completely over-rides
normal positioning decisions. The form is apply'd to the text mark,
the owning object, the current score, and whatever other arguments
were passed to the display procedure. Examples can be found in the
various .cmn files included with cmn. (See also the prolog discussion
on page 32). To position lyrics, one possibility is the following
(see also lyrics.lisp):
(defun lyrics (&rest args)
(apply #'text unjustified (font-name "Times-Roman") (font-scaler .5)
(y #'(lambda (mark note score &rest rest) (- (staff-y0 note) .9)))
(x #'(lambda (mark note score &rest rest)
(+ (x0 note) (if (sign note) .2 0))))
args))
Multi-note marks
There are a number of marks that apply to more than one note -- ties,
slurs, beams, and so on. cmn handles these in two ways. Each
multi-note mark has a begin-<mark> and end-<mark> form that is both a
variable and a function (as with all the other objects), and these
follow a stack discipline. That is, the last one to begin is the
first one to end -- marks can be nested without problem. If the marks
need to cross one another, a mechanism is needed to make it obvious
which begin-<mark> belongs to which end-<mark>. In cmn, this is done
with tags. Here is an example of the simple form:
(cmn staff treble (c4 q begin-slur) (d4 q) (e4 q end-slur))
And an example of tags:
(cmn staff treble (c4 q (setf slur-tag (begin-slur))) (d4 q (end-slur slur-tag)))
The tag is simply a variable (give it any name you like). In the
example given above the tag was unnecessary, but consider this
example:
(cmn staff treble
(c4 h (setf lower-text (text- "hi"))
(setf upper-text (text- "sil" (y0 2.0))))
(d4 q (-text- "ver" upper-text (y0 2.0)))
(d4 q (-text- "ho" lower-text))
(e4 q (-text "!" upper-text (y0 2.0)))
(e4 h (-text "away!" lower-text)))
Here the line connecting the words has to know where the next word in
its sentence is, and without the tags (upper-text, lower-text), that
task could be relatively difficult.
Connected text
Text that needs to be connected across notes or passages is handled by
text- -text- -text
These take any number of arguments, one of which should be either a
string or a text object. text- starts a new connected text sequence
and connects to either -text- or -text. -text- connects to a current
sequence (either the last one started or the one indicated by a tag
passed to -text-) and continues it forward. -text connects to a
current sequence and finishes it. The connecting pattern is the list
text-connecting-pattern which defaults to a simple line between the
pieces of text (that is '(10 0)). To get a dashed line,
(cmn (text-connecting-pattern '(5 10)) staff treble
(c4 h (text- "hi")) (d4 q) (d4 q (-text- "ho"))
(e4 q) (e4 h (-text "away!")))
text- returns a tag that can be used to distinguish between
simultaneous text sequences (see the example given above). If the
text- call encounters the x or y message, the associated lambda form
is applied across the entire connected text sequence (see joh.cmn for
an example). For a purely local change of connecting pattern, use the
message (to text- et al) connecting-pattern.
glissando and portamento
glissando-to &rest objects portamento-to &rest objects
begin-glissando end-glissando begin-portamento end-portamento
glissando- -glissando portamento- -portamento
These create the line connecting two notes with optional text sitting
on the slanted line. The line is normally straight; use the message
wavy-line to get a curvy connecting line.
(cmn staff treble (e4 h (glissando-to a3)) quarter-rest
(c4 h begin-glissando) (g4 h end-glissando))
;; set free-expansion-factor to 2 to get room for the word "gliss"
;; or use the message minimum-length: (minimum-length 2.0)
If there's room, cmn adds the word "gliss" or "port" or whatever you
want to the line.
(cmn staff treble
(c4 h (begin-glissando
(text "up up up" (font-name "Times-Roman") (font-scaler .6))))
(c5 h end-glissando))
crescendo and diminuendo
begin-crescendo begin-diminuendo end-crescendo end-diminuendo
crescendo- -crescendo diminuendo- -diminuendo
These create the wedges sometimes used to mark crescendos and
diminuendos. The wedge starts at the current note and ends either at
the note that contains the end-crescendo or wherever its duration
falls. The wedge can start anywhere -- the message to delay the
wedge beginning is onset-offset. The message width controls how wide
the wedge gets. You can specify the dynamics mark to be placed at the
beginning or end of the wedge either by passing the mark to the
begin-crescendo function, or by using begin-dynamic and end-dynamic.
(cmn staff treble
(c4 q (crescendo (duration 2.0))) (d4 q)
(c4 q (begin-diminuendo (end-dynamic f) (width .75))) (d4 q)
(e4 q end-diminuendo)
(c4 q (begin-crescendo ppp f)) d4 q e4 q f4 q (g4 q (end-crescendo)))
Ties
begin-tie end-tie tie-direction tie-curvature
dashed dx0 dy0 dx1 dy1 breathing-space
Ties are handled like glissandos. Tie-direction sets which way the
tie curves, either :up or :down. Tie-curvature controls how much the
tie curves; the default is the score slot tie- curvature. The
argument to dashed is a list (length-of-pattern
length-of-white-space).
(cmn staff treble (c4 q begin-tie) (c4 q end-tie)
(c4 q (begin-tie (tie-direction :up) (tie-curvature .5))) (c4 q end-tie))
When entire chords are tied, all notes within the chord are tied
automatically.
(cmn staff treble (chord (notes c4 e4 g4 c5) q begin-tie)
(chord (notes c4 e4 g4 c5) q end-tie))
To tie just selected notes of a chord, put the ties on those
individual notes:
(cmn staff treble (chord (notes (c4 (setf tie-c4 (begin-tie))) e4 g4 c5) q)
(chord (notes (c4 (end-tie tie-c4)) e4 g4 c5) q))
Unless you indicate otherwise (by setting automatic-ties to nil), cmn
puts in ties wherever it deems necessary. See also ring.lisp for
ring- and friends (ties off into space).
(cmn staff treble (meter 2 4) f4 e. f4 q. f4 h.)
(cmn staff treble (meter 2 4)
(chord (notes f5 af4 df5) (rq 5/4))
(chord (notes f5 ef5 df5 a4) (rq 3/2))
(chord (notes f4 gf4 af4 d5) (rq 5/4) stem-down))
Slurs
begin-slur end-slur
slur- -slur- -slur
Slurs are like ties, but can cover any number of notes. cmn makes a
real effort to make a pretty slur, but it often screws up. When that
happens, you will have to edit the slur-data by hand, and that's not
easy. The data is a list of two lists, each a set of 6 points. These
are the controlling points of the two Bezier curves that outline the
slur. '((x1 y1 x2 y2 x3 y3) (x2 y2 x1 y1 x0 y0)) is the general idea,
with the slur thickness subtracted from y1 and y2 on the return run.
There are a variety of messages to begin-slur to help edit slurs:
dx dy dx0 dy0 dx1 dy1 dx2 dy2 dx3 dy3
slur-direction slur-thickness slur-curvature dashed
dx and dy are applied to all points whereas the others apply only to
the indicated point. (begin- slur (dy -.25)) moves the entire slur
down .25, but (begin-slur (dy0 -.25)) moves only the first of the 4
points that describe the slur. Dashed for slurs is the same as for
ties.
(cmn staff treble
g4 q begin-slur ef4 q c4 q end-slur
g4 q begin-slur b4 q a4 q end-slur
b4 q begin-slur e5 q d5 q cs5 q end-slur
a4 q begin-slur e4 q f4 q g4 q a4 q end-slur
g4 q begin-slur ef5 q bf4 q ef4 q end-slur)
Tremolo &rest objects
There are two kinds of tremolo: unmeasured and measured. In addition,
there are a number of stylistic choices involving beams, slashes,
slurs, and note heads, not all of them entirely logical. For example,
one book on music notation says half note tremolos should have one
beam and two slashes, quarter note tremolos should have no beams and
three slashes, and eighth note tremolos should have one beam and two
slashes, but filled in note heads, since otherwise there would be no
way to tell them from half note tremolos. The logical way would be to
put no beams and three slashes on both half note and quarter note
tremolos. Grumble! To try to sort out the various possibilities,
there are first:
begin-tremolo end-tremolo begin-measured-tremolo end-measured-tremolo
unmeasured-tremolo tremolo paranoid-tremolo measured-tremolo
begin-tremolo and end-tremolo are unmeasured tremolos. The begin and
end forms apply to those cases where there are two notes in the
tremolo. The others (unmeasured-tremolo, etc) are for single note
tremolos. Paranoid-tremolo includes the word "trem.". These take the
additional messages:
tremolo-position :on-stem or :between-stems
measured t or nil
paranoid t or nil
tremolo-slashes nil (=3) or an integer
tremolo-beams nil or the number of beams
slant .1
width .3
thickness .08
font-name "Times-Roman"
font-scaler .4
maximum-length .85
(cmn staff treble
(c4 q tremolo) (c4 w paranoid-tremolo)
(c5 q (tremolo (tremolo-slashes 1)))
(c4 h begin-measured-tremolo) (d4 h end-measured-tremolo)
(c4 e begin-tremolo) (d4 e end-tremolo))
Beams
Beams can be handled automatically or by hand. If the score slot
automatic-beams is t (the default), automatic beaming follows the
current meter if it can (see the example on page 2). Any explicit
beams over-ride automatic beaming. Explicit beams are handled by:
begin-beam end-beam no-beam no-beam-break
beam- -beam- -beam
beam-direction explicit-beams dx dy dx0..dy1 ;see cmn-ex.lisp for examples
The first two are like begin-slur and end-slur and apply to all notes
on the staff between the begin- beam and end-beam. Beam- and friends
are like text- and friends. Here's an example of all three
possibilities:
(cmn staff treble c4 e d4 e (c4 e begin-beam) (d4 s) (e4 s end-beam)
(c4 e (setf beam (beam-))) (d4 e (-beam- beam)) (e4 e (-beam beam)))
The numbers marking irregular beat subdivisions are kept as simple as
possible Ð cmn adds the bracket only if there is something peculiar
in the grouping. To deal with these explicitly use:
beat-subdivision- -beat-subdivision- -beat-subdivision no-beat-subdivision
These take the additional messages subdivision (a number, string, or
text object) and bracketed. The latter can be t (the default), nil,
:up, or :down. The details of the bracket can be changed with the
messages dx, dy, dx0, dy0, dx1, dy1, and bracket-type (see
cmn-ex.lisp).
(cmn staff treble c4 te c4 te c4 te
(d4 (rq 1/5)) (d4 (rq 1/5)) (d4 (rq 1/5)) (d4 (rq 1/5)) (d4 (rq 1/5))
(c5 (rq 2/3)) (c5 (rq 1/3))
(c4 te (setf hi (beat-subdivision- (subdivision 7) (dy0 -.5) (dy .5))))
(c4 te (-beat-subdivision- hi)) (c4 te (-beat-subdivision hi)))
If the beamed notes fall on different staves, start the beam on the
higher staff even if the notes on that staff come later in the beam;
if the onsets are given explicitly, the notes being beamed are sorted
out automatically. Wedged ("feathered") beams (as used by Bartok and
others) are implemented in wedge.lisp, included with cmn (see also
cmn-ex.lisp for explicit beam choices).
endings
These are the first and second ending marks.
begin-first-ending begin-second-ending
end-first-ending end-second-ending
Begin-first-ending and begin-second-ending take the additional messages:
max-line ;the line number of the highest (lowest) note under the octave sign
terminal ;t if the ending is also the ending of the piece
(cmn staff treble (meter 2 4)
(c4 q) (c4 q) (bar begin-first-ending)
(c4 q) (c4 q) (end-repeat-bar end-first-ending begin-second-ending)
(c4 q) (c4 q) (bar end-second-ending)
c4 q c4 q double-bar)
segno coda
(cmn staff (bar (mm 96 e) treble c4 w (bar segno) (c4 w) (bar coda)
(c4 w) (bar (change-beat q. e)) (c4 w))
change-beat mm
These two set the current metronome marking and (as shown above) a
change of beat. Change-beat takes two arguments, the old beat and the
new beat. mm takes two arguments, the metronome marking, and
optionally the rhythmic value that marking applies to (it defaults to
a quarter note). Normally the metronome marking is a parenthetical
addition to the tempo indication. mm also responds to in-parentheses
and the various justification messages.
repeat-measure
The repeat-measure mark is centered between bar lines and has a
metrical value equal to a measure. As a function it accepts an
optional number to be displayed over the mark.
(cmn staff treble (meter 2 4) c4 q c4 q bar repeat-measure bar
c4 q g4 q bar (repeat-measure 440) c4 q c4 q double-bar)
octave transposition
Octave transposition signs are added automatically to very high (or
low) passages unless you set the score slot automatic-octave-signs to
nil.
(cmn staff bass c5 e d5 e f5 e g5 e c5 q g4 q c4 q)
If you like the Italian persiflage of "va" and "ma" (or, God forbid,
"bassa"), set the appropriate score structure slot
(use-italian-octave-signs, add-bassa-to-octave-signs). Explicit
octave signs are handled with:
begin-octave-up octave-up end-octave-up
begin-octave-down octave-down end-octave-down
begin-two-octaves-up two-octaves-up end-two-octaves-up
begin-two-octaves-down two-octaves-down end-two-octaves-down
begin-no-octave-sign no-octave-sign end-no-octave-sign
These act like the tie and slur messages. Octave-up and friends apply
only to one note; no-octave- sign and friends turn off the automatic
octave signs for short passages. The note pitch values within the
octave signs are the displayed values, not the true values:
(cmn staff treble c4 q begin-two-octaves-up d4 q e4 q f4 q end-two-octaves-up)
These take the messages vertical-separation, font-name, font-scaler,
and octave-sign-pattern. Rehearsal marks and measure numbers
Rehearsal marks are either numbers or letters, optionally boxed or
circled, and normally attached to a bar line. The cmn entities are:
rehearsal-number rehearsal-letter
each of which take the additional message frame to set the type of the
surrounding frame. The frame can be nil (the default), :none, :box,
or :circle. It need be set only on the first rehearsal mark. Each
mark after the first normally increments the mark letter or number
("Z" goes to "AA", and "I" is skipped), but you can reset the mark to
be anything by passing it as an argument to rehearsal-number or
whatever. measure-number is similar -- it displays a number. Other
messages are: rehearsal-frame-width and rehearsal-frame-white-space.
page-mark and line-mark
Page-mark is an explicit end-of-page mark. Line-mark is an explicit
end-of-line mark. Line-mark takes the additional messages dx and dy.
In this context, these refer to the positioning and justification of
the upcoming line. Normally staff positioning within a line is set by
the dy message to the staff, and the staff/system-separation
variables. There are cases where one line, or a staff within a line
needs to be moved vertically to avoid collisions. Similarly, the
justification decisions within a line are sometimes suboptimal. In a
sense, the dx and dy messages provide you with a horizontal and
vertical ruler to guide the positioning process to whatever level of
detail you like. The argument to dx (in this case) is a list of
lists, each inner list a pair of numbers: '(beat dx-position) where
the beats (actually quarter-notes, not beats) are numbered from 1, and
the dx-position is in the normal staff-based units (use in-inches, if
you like). If more than one line-mark applies to a given line (via
multiple staves, all being explicit about line breaks), all the dx
(and dy) messages are merged before being applied to the justification
of that line. Vertical (staff) positioning is handled by dy. Its
argument can be a number, or a list of lists. If a number, it is like
a local dy message to the staff it occurs in. If a list of lists,
each inner list is a pair of numbers '(staff-number dy) where the dy
number is in the usual units, and the staves are numbered from 1 at
the top of the line. To see the current rulers, set the show-rulers
field of the score. In the glorious (but distant) future, we will
figure out how to tie this into the window system and use a mouse to
push tab stops around, as in WriteNow. Line-break and page-break are
the same as line-mark and page-mark.
Note list display (add-note, display-notes)
add-note score name begin-time duration frequency &rest rest
Add-note is the main interface between clm note lists and cmn. name
is the instrument name, begin- time and duration are in seconds,
frequency is in Hz. cmn assumes 12 tone equal tempered 5-line staff
output, and uses the score slot metronome to choose the closest simple
rhythmic values for begin-time and duration. To save the result as a
call on cmn, use cmn-store. The easiest way to read in a note list is
to wrap it up in a list and call display-notes:
display-notes score-attributes notes
(display-notes nil
'((vln 0 .5 440 .1) (vln 0 .5 660 .1) (vln .5 .5 880 .1)))
We can now write this out as a call on cmn with cmn-store. The
latter's two optional arguments are the score structure to be stored
(it defaults to the last score created -- *cmn-score*), and the output
file name (it defaults to "hi.cmn").
If the score slot automatic-naturals is t, cmn adds natural signs
wherever they seem to be needed. The two slots,
implicit-accidental-style and implicit-accidental-duration, give you
some control over how these decisions are made. The style can
currently be :new-style, :old-style, :only-chords, or :paranoid. The
duration (perhaps "persistence" is a better word) is the number of
notes an accidental mark hangs over -- it only applies to :new-style
(the default) where it defaults to 1. :old-style is the 19th century
way -- an accidental is cancelled only by a bar line. :paranoid
doesn't let anything cancel an accidental. cmn tries to be smart
about key signatures as well, but there are some weird ambiguous cases
here.
graphics &rest objects
Any .eps file can be imported into the cmn score, rotated, scaled, and
so on. Graphics takes one additional message to the usual ones: file.
The argument to file is the name of the .eps file to be inserted.
(cmn (output-file "2.eps") staff treble c5 s)
(cmn staff treble
(c4 q (graphics (file "2.eps") (scale .6 .6)
(dx 2.0) (dy 1.0) (rotate 90))))
The contents of the .eps file are copied into the output file of cmn.
with-cmn &rest objects
It is possible to package up an entire score as a mark by calling
with-cmn. with-cmn is just like cmn except that it doesn't open any
files.
Extensions to the input functions
cmn is just a normal Lisp function of any number of arguments. If an
argument evaluates to nil, it is ignored (this is useful for functions
called only for their side effects); if an argument is a score-
object-list, the entire associated list is spliced into the argument
list as though it had occurred that way from the start. To take
advantage of this, use disgorge and engorge. Engorge returns a score-
object-list instance containing the objects passed as its arguments;
the various functions that take data lists (cmn, system, staff, etc)
notice these objects and "flatten" them, treating the list of objects
just as if they had come in the normal argument list. For example,
say we want a bunch of quarter notes all staccato, stem down, and we
are lazy typists:
(defun qsd (&rest notes)
(engorge
(loop for note-name in notes
collect (note note-name q staccato (stem-direction :down)))))
and now in cmn we can say: (cmn staff treble (qsd a4 c4 b4 g5 d5 d4))
This process can be carried as far as you like -- everything is
straight-forward lisp, and all of lisp is at your disposal. The
opposite of engorge (which wraps up the list of objects into a
score-object-list instance) is disgorge. When passed a
score-object-list instance, it returns the list you originally wrapped
up. A slightly more complicated example of engorge is the function:
cycle &rest objects
The objects passed to cycle are sequences of cmn objects. Each is
treated as a circular list, and the result of cycle is a list whose
length is the length of the longest sequence passed. Each object in
the resultant list reflects the combination of the corresponding
objects from the lists of sequences. That is,
(cmn staff treble (cycle (list c4 e4 g4 c4 e4 g4) (list e. s) staccato))
produces the same result as
(cmn staff treble (c4 e. staccato) (e4 s staccato) (g4 e. staccato)...)
In the same vein as engorge are the functions staff-engorge,
system-engorge, and score-engorge, the latter involving the function
score. Each of the engorging functions takes a list of staves,
systems, or scores, and returns the new staff or whatever that
contains all the data of its arguments. For example,
(setf v1 (staff treble (meter 3 4) c4 q c4 h))
(setf v2 (staff treble (meter 3 4) d4 h d4 q))
(cmn (staff-engorge (list v1 v2)))
(setf s1 (system (staff treble (meter 3 4) c4 q c4 h)
(staff bass (meter 3 4) c3 h c3 q)))
(setf s2 (system (staff treble (meter 3 4) d4 q d4 h)
(staff bass (meter 3 4) d3 h d3 q)))
(cmn (system-engorge (list s1 s2)))
(setf sc1 (score staff treble c4 h c4 q))
(setf sc2 (score (initial-onset 3) staff treble
(d4 q (onset 3)) (d4 h (onset 4))))
(cmn (score-engorge (list sc1 sc2)))
The arguments to system-engorge and score-engorge must be compatible
in the sense that the list of systems and staves must match. Score
looks like the overall cmn call, but it only packages up the score
data ready for a "real" cmn call.
These functions provide the underlying support for sections. In the
cmn function call described earlier, there is actually yet another
outer layer above systems, called sections. These provide a way to
package up portions of a piece, apply local score decisions to those
portions, and then glue them all together at the end. Each section
looks like a cmn or score call:
(cmn (section (redundant-accidentals nil)
(staff treble (meter 4 4) cs4 q cs4 q cs4 q cs4 q))
(section (staff treble cs4 q cs4 q cs4 q cs4 q)))
The successive sections either are abutted (as in the example above),
or use the score slot section- onset to specify the starting time, or
use the score-slot initial-onset with correct onsets within the
section data.
glyphs &rest glyphs
returns a list of glyphs -- this is primarily an optimization to avoid
endless font changes. The glyphs can be characters, integers, or
actual glyphs. The integers should be the octal digits corresponding
to the character. See the example on page 34 under prolog.
Extensions to the display functions
The easiest way to add your own graphics code is to package it up in a
sundry instance and pass that to the object you want to own the code.
The sundry class has two slots, sundry-name (a debugging convenience)
and sundry-mark. Sundry-mark is a function that is called as follows
(apply (sundry-mark sundry) sundry object score rest).
The staccato function, for example, is essentially:
(defun staccato (&rest objects)
(make-instance 'sundry :name :staccato
:mark #'(lambda (mark note score &rest rest)
(moveto score (+ (x0 note) (center note)) (+ (y0 note) .25))
(show score %dot))))
It finds the center of the note it belongs to, then tries to put a dot
over it. Of course, the actual code is a bit more complicated because
sometimes the dot goes under the note, we have to try to avoid
colliding with staff lines, and we have to do something reasonable
with the objects that might be passed as arguments to staccato. The
basic graphics operations are:
lineto score x y ;draw a line to (x,y)
rlineto score dx dy ;draw a line from the current point to (current-point+dx,current-point+dy)
moveto score x y ;go to (x,y) without drawing anything
rmoveto score dx dy ;go from the current-point to (current-point+dx,current-point+dy)
curveto score x0 y0 x1 y1 x2 y2
;draw a Bezier curve from the current-point using these three points as guides
show score glyph ;display a font character (a "glyph")
draw score ;cause the current lines to be drawn (stroke in PostScript nomenclature)
fill-in score ;cause the current lines to be filled in (rectfill and others in PostScript)
circle score x y r &optional (ang1 0) (ang2 360) filled
;draw a circle, center (x,y), radius r starting at ang1 and going to ang2
line-width score ;the thickness of the line drawn by draw (a slot that can be setf'd)
The easiest way to mix text and music is to position the music using
the margin slots, then attach the text as a series of marks on a
staff. See cmnt.lisp for several examples used in this manual. The
field staff-y0 gives the bottom of the staff containing the current
object.
A complete example
Say we want to add a mark called smiley-face that will always appear
above the staff centered over whatever object it is attached to. We
want smiley-face to take all the usual messages. First, we write the
display function that positions the face and draws it:
(defun display-smiley-face (mark note score &rest rest)
(let* ((y-off (+ (y0 mark) (dy mark) (staff-y0 note)
(* (max 11 (+ 4 (maximum-line note)))
(staff-line-separation score))))
(r (/ 10 40))
(x-off (+ (x0 note) (dx mark) (center note) (x0 mark))))
(setf (line-width score) .025)
(circle score x-off y-off r)
(draw score)
(circle score x-off y-off (* r .6) 190 350)
(draw score)
(circle score (- x-off (* .33 r)) (+ y-off (* .25 r)) (* r .1) 0 360 t)
(circle score (+ x-off (* .33 r)) (+ y-off (* .25 r)) (* r .1) 0 360 t)
(setf (line-width score) 0)))
maximum-line is a message that returns the line number of the highest
note in the object (it might be a chord). We either display the face
above the staff (line 11) or above the note if it is above the staff.
We center it over the note taking dx messages into account. Next we
set the line width to be a little thicker than the minimum, draw the
outer circle, the mouth circle, and the two eyes. At the end we reset
the line width to 0. Now, to make this a normal mark, we need to
define the variable and function smiley-face.
(defvar smiley-face
(make-instance 'write-protected-sundry
:name :smiley-face
:mark #'display-smiley-face))
(defun smiley-face (&rest objects)
(apply #'mark #'display-smiley-face :smiley-face objects))
and now we can use our new mark:
(cmn staff treble c4 q smiley-face)
with-scaling score size x0 y0 &body body
with-transformation score matrix x0 y0 &body body
with-pattern score pattern &body body
These macros take some arbitrary graphics code and then apply some
transformation to the result. With-scaling evaluates body, scales the
result by size in both the x and y directions and puts the result at
the location (x0, y0) in the outer score. With-transformation is
similar but lets you apply an arbitrary transformation to the result
of evaluating body. Matrix is used to transform the result of body,
and the result is placed at (x0, y0). In both cases, the (x0, y0)
coordinates should be scaled by the overall score size. With-pattern
evaluates body using the pattern pattern.
More complex graphics additions can follow the example of trill (for
simple one-note marks), or ties (for multi-note marks). Each new
class should include methods for descry (to produce a printed
representation of the instance), copy (to copy an instance), and
display (the graphics code associated with the object). For
multi-note marks that need to know the position of the later marks,
specialize backpatch to the new class. If your new class is a
sub-class of the sundry class, there should be no special cases to
worry about. If your object has metrical significance that the
justification routines need to handle, add a house method (see any
example in the source). If you want to add your own graphics
procedures to the header or "prolog" portion of the graphics output,
use the message prolog (passed to the score in the
overall-score-attributes section). Prolog's argument is a function of
one argument, the overall score. It should send whatever graphics
code it wants to (output score). For example, say we want to use the
"ISO encoding" for the Times-Roman font (to get at umlauts and so on).
In this case, we can use the built-in function
make-ISO-encoded-version (which can also serve as an example of a
Prolog function):
(cmn (prolog #'(lambda (score)
(make-ISO-encoded-version score
"Times-Roman" "ISO-Times-Roman")))
staff treble
(c4 q (glyphs #\s 374 337 ; 374 = u-umlaut, 337 = double-S
(dy 1.5) (dx -.25) (font-name "ISO-Times-Roman")
(font-scaler .5) (gray-scale .25))))
; or (text "s\\374\\337" ...) and 366 373 in Times-Roman
There can be any number of prolog calls -- the associated procedures
are called in the order given in the argument list. Similarly, the
code executed by the sundry object can send graphics commands directly
to the output graphics file -- (output score) is the output stream.
Line Layout
Unless told otherwise, cmn includes every staff on every line, even if
the staff has nothing but rests for line after line. There are a
number of layout options to affect this decision. The layout message
can be passed to the score (as one of the "attributes"), any system,
or any staff, affecting everything "beneath" it that doesn't have some
explicit layout directive. The default layout is nil; the other
options are t, :old-style, :new-style, :locked, and a list of lists.
:old-style layout includes a staff on a given line only if it has
notes on that line. The layout t is the same as :old- style except
that the first line of the score includes every staff (this is the
norm for orchestra scores). :locked is used to explicitly override a
higher-level layout setting, equivalent to an explicit (layout nil).
:new-style layout omits the staff lines where the staff has no notes.
Here's an example of :new-style
Changing Global Justification Decisions
The justification routines need to know which objects cannot be
overwritten and how much white space they need or want around them.
The four boxes surrounding each such object are its bounding box (x0
y0 to x1 y1 -- this is where the object is actually drawn), its
"walls" (the absolute minimum white space the object can get by with),
"fences" (the amount of white space that makes the object look
uncrowded), and "expanders" (how to expand white space around the
object when there's more space than we'd like). The walls, fences,
and expanders are kept in variables with names such as:
bar-walls bar-fences bar-expanders
Each is a list of two numbers: left side, right side. Walls and
fences are in the staff relative coordinates. Expanders are usually
just integers -- the bigger the integer the more white space will be
placed on that side of the object if needed to fill out the line. The
bar data, for example, is:
(defparameter bar-walls '(.1 .1))
(defparameter bar-fences '(.1 .05))
(defparameter bar-expanders '(0 1))
These cause there to be .1 space on each side of the bar, no matter
what. If bar-walls were '(.1 0) an object could stick right to it on
the right side.
When a line is being justified and the line does not fill the page
width, the score slot free-expansion- factor determines how much
expansion takes place over the absolute minimum needed to display the
objects. It defaults to 1.25, which may be a little stuffy, but 1.5
often looks spaced out. A free- expansion-factor less than 1.0 will
force the objects to smash into each other. The score slot regularize
(normally nil) can be used to instruct cmn to make a greater effort to
attain a regular spacing.
editor-hook filter-hook page-hook line-hook spacing-hook
These "hooks" provide ways to edit the cmn data lists before the
output is produced. line-hook, page-hook, and spacing-hook are also
score slots. See cmn-ex.lisp for examples. editor-hook is applied to
the raw input data stream, and can be used to extract or transpose
parts, for example. filter-hook is applied to the end result of the
justification process, and can be used to extract a page from a large
score, or apply some last minute editing function. The function
extract-part provides part extraction using editor-hook. It takes the
name of the part to be extracted, or a function that takes the staff
name and returns t if it wants that part:
(cmn (extract-part "hi")
(staff (staff-name "hi") treble c4 q)
(staff (staff-name "ho") bass c4 q))
To transpose a score or any portion thereof, see transpose.lisp.
Examples
There are a few longer examples included on the cmn directory:
fux.cmn, moz.cmn, gus.cmn, carl.cmn, and so on. cmn-ex.lisp has some
examples of programming in cmn. The examples in this manual are in
cmnt.lisp. The variable *cmn-version* contains the current version
number (a date). There is a previewer for the Mac: set the
output-type to :quickdraw as in
(cmn (output-type :quickdraw) staff treble c4 q)
Known bugs and lacunae
The following are on my list of things to add or fix -- if you find a
bug or omission that's not on this list, send me a note: cadenzas,
cues, second alignment on virtual staves, part-extraction could be
made much smarter.
Bill Schottstaedt
bil@ccrma.stanford.edu
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.