COMMON MUSIC NOTATION

cmn est un modeste petit programme qui permet de fabriquer et d'afficher des partitions en notation musicale traditionnelle. On peut l'obtenir gratuitement : il suffit de copier en accès anonyme le fichier cmn.tar.gz du site ftp://ccrma-ftp.stanford.edu/pub/Lisp. Il y a toujours encore quelques trous, mais j'espère pouvoir les combler avec le temps. Ce qui manque le plus est une interface graphique intercative.


[Contenu: accidental, appoggiatura, arpeggio, arrow, articulation mark, auxiliary note, bar line, beam, beat subdivision, brace,bracket, chord, clef, clm to cmn, coordinate transformation, crescendo, diminuendo, dynamics, ending, eps file, fingering, glissando, grace note, graphics, horizontal ruler, house (of?) style, justification, key, line mark, matrix, measure number, meter, note, octave transposition, octave transposer, ornamentation, page mark, pattern, pause, portamento, rehearsal mark, rest, section, slur, staff, staff layout, system, text, tie, tremolo, trill, with-cmn]

Introduction

Premier contact : notes personnelles du traducteur (Ndt)

Chaque fois que l'interviens, le texte apparaît en bleu.

Avant de me mettre à la CMN, je n'avais jamais programmé ni du Lisp, ni aucun langage apparenté. Je trouvais ces langages trop difficiles à lire. Mais l'accoutumance c'est faite très vite. Le langage clisp et le paquetage cmn ont été installés le 7 juin 2002 et j'ai rapidement été séduit par la virtuosité qu'on pouvait atteindre. On va de découverte en découverte et très vite on imagine les pires difficultés de la musique contemporaine et on finit par trouver une solution.

En fait j'avais même des antécédents aggravants : j'avais tenté une installation en automne 2001 : l'installation a réussi (c'est très facile) mais l'ordinateur souffrait de pannes matérielles aléatoires dues à des surchauffes, de sorte que je n'ai jamais pu goûter aux joies de CMN et c'est avec l'ordinateur actuel que je n'ai plus ce genre de problème.

Jargon

Il faut prendre l'habitude concevoir que Lisp est constitué d'objets (une note, une portée, une indication dynamique sont des «objets») auxquels on envoie des messages. On peut imaginer un «message» comme un argument qu'on envoie à un programme ou un paramètre qu'on envoie à une fonction. Mais souvent les langages informatiques sont ainsi (bien/mal) faits qu'il faut envoyer tout le temps tous les paramètres aux fonctions (ce qui finit par être lassant). Lisp se contente que des messages indispensables : il n'est pas nécessaire à chaque fois de tout préciser, mais quand le changement est nécessaire, on peut le faire.

CMN est un programme lisp qui fonctionne normalement avec le paquetage cmn. Voici comment procéder : D'abord lancer clisp :

clisp.
Là on se trouve dans clisp avec un prompt qui attend des commandes. On charge le paquetage spécifique de cmn :
(load "cmn-all.lisp").
Puis on déclare vouloir entrer dans cmn :
(in-package :cmn).
Enfin, on peut charger l'un ou l'autre fichier d'exemples fourni avec cmn. Par exemple:
(load "joh.cmn")

Pour les premiers essais, on peut aller dans le répertoire où on a mis les exemples. Mais ce n'est pas nécessaire : on peut avoir le paquetage cmn dans un répertoire "CMN", les textes sources dans un répertoire "partitions" être dans un autre répertoire où CMN va écrire la sortie en PostScript. Comme clisp est normalement installé dans les exécutables, il sera accessible de partout. Les entrées pour une telle situation sont donc à modifier ainsi :

clisp
(load "/le_chemin_complet/CMN/cmn-all.lisp")
(in-package :cmn)
(load "/le_chemin_complet/partitions/sonate.cmn").

L'auteur du logiciel propose une alternative à clisp : Allegro Common Lisp. J'ai tenté de l'installer (pour voir), mais cela n'a pas été concluant et je préfère rester avec clisp. Mais il faut que je prévienne : une première installation n'a pas bien fonctionné ; il y eut des erreurs dont je ne sus détecter l'origine (clisp ou cmn ?). J'ai réinstallé le tout et cela fonctionne à merveille (il est vrai que je ne suis pas du tout "installateur" mais "utilisateur").

Quand le fichier "sonate.cmn" a été chargé, ou bien cmn manifeste sa satisfaction en affichant un T (ce qui veut dire "true") ; dans ce cas, cmn a déjà produit un fichier de sortie en PostScript qui, si rien d'autre n'a été spécifié, s'appelle aaa.eps. Sinon, cmn fait quelques commentaires ce qui permet plus ou moins facilement de trouver l'erreur qui a été faite. A l'attention de ceux qui n'ont jamais travaillé avec un logiciel d'interprétation ou de compilation : le logiciel ne peut signaler que les erreurs contrevenant à la syntaxe et à la morphologie du langage. Il ne peut pas détecter ce qu'on a pensé de travers ; cela demande un effort de compréhension (un logiciel est comme un animal ou un petit bébé : il faut essayer de le comprendre).

Après avoir chargé cmn, écrivez (in-package :cmn) ou (en ACL) :pa :cmn,et toutes les entités seront disponibles. On peut aussi donner le nom du paquetage en préfixe si on travaille dans un autre paquetage, mais à la longue, cela agace.

Voici comment cmn marche en général : l'expression lisp:

(cmn staff treble c4 q) 

produit le fichier "aaa.eps" (la valeur par défaut de *cmn-output-pathname*):

picture

cmn est la fonction principale. Elle lit tous les arguments, répartit les données musicales en systèmes et portées, insère les sauts de ligne et sauts de page, les poutrages, les liaisons, la dynamique etc. Enfin, elle aligne et justifie le résulat et écrit un fichier "encapsulated PostScript" (nommé aaa.eps dans ce cas). Les termes utilisés sont ceux de «Score» ou «Common Music» c4 est le Ut du milieu du piano, q correspond à la noire, etc. En général, la syntaxe de cmn est :

cmn attributs-généraux systèmes

Les attributs généraux concernent les dimensions graphiques, les dimensions de la page, l'épaisseur des poutres etc. Comme la dimension de base est de 40 par défaut, on peut la fixer par exemple à 24 en disant :

(cmn (size 24) staff treble c4 w double-bar)
picture

Les sytèmes contiennent toutes les données musicales. Chaque système est un groupe de portées reliées ensemble par des crochets et séparés verticalement des autres systèmes. Chaque système contient les notes et leurs attributs. Si aucun système n'est indiqué explicitement, il en est créé un automatiquement et de même pour les portées. Voici un exemple d'une partition à deux systèmes dont l'un a deux portées :

(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))))
picture

Tout ce qui est porté sur une partition est un « objet » de la partition : c4 staff tenuto ... Chaque « objet » est à la fois une constante et une fonction - ce que veut dire que staff a des valeurs par défaut (5 lignes, une dimension standard, une direction etc.) mais que ces valeurs peuvent être changés en envoyant des « arguments » supplémentaires à l'objet staff. En tant que fonction, un objet accepte un grand nombre d'arguments.

Le langage Lisp doit en principe respecter une syntaxe conventionnelle nommée CLOS dont les règles disent qu'il faut passer par la fonction setf pour appliquer d'autres arguments. Mais cela implique beacoup de texte à taper en outre il faut documenter chaque accès à l'objet - cela finirait par noyer l'objet dans un déluge de parenthèses. En cmn la manière standard pour changer un attributd'un objet est de demander la modification de l'attribut en passant un argument :

Ainsi

    (c4 q staccato)

crée un objet c4, auquel est attribué une durée d'une noire et un point de staccato. En général, c'est la même chose que :

    c4 q staccato

qu'on voit dans les exemples. La fonction staff enregistre les séquences de notes et leur cortège d'attributs en rétablissant les parenthèses sous-entendues. Il est bon de mettre les parenthèses quand il y a un risque d'ambiguïté. Ainsi on pourrait écrire ainsi le précédent exemples :

(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)

Je trouve que la première forme est plus facile à lire, mais il est vrai que j'ai l'habitude de lire du Lisp parenthésé. Je n'ai pas complètement nettoyé les résidus, il reste donc quelques endroits où les parenthèses sont nécessaires. cmn, system et leur suite sont des fonctions et non pas des macros, ce qui fait que les flots de données sont interprétés sans autre comme arguments d'une fonction. La résolution d'écran est inférieure à celle des imprimantes ; il arrive donc que les images affichées soient crénelées par suite d'erreurs d'arrondi (voir le crochet de l'exemple donné). Dans les exemples suivants, j'omets les arguments, tels que (size 24) qui ne sont pas indispensables pour comprendre.


Réglages d'ensemble

L'argument cmn overall-score-attributes permet de déterminer quelques valeurs qui affecteront la mise en pages de toute la partition ; à l'exception des dimensions concernant l'empreinte imprimable elle-même (largeur de la page : page-width, etc.), toutes les mesures sont exprimées par rapport à la dimension verticale de la portée -- ainsi une portée normale mesure 1.0, et tout autre chose s'y rapporte. Si on veut utiliser des centimètres au lieu de « inches » et des normes européennes au lieu des américaines, il faut fixer la variable *cmn-units* à :cm. La valeur par défaut est :inches. Voici la liste des attributs possibles :

output-file"aaa.eps" (pour numéroter les fichiers, ajouter "-1" au nom)
output-type*cmn-output-type*:postscript, :x, :quickdraw
size40coefficient d'échelle global
automatic-line-breakstcmn coupe les lignes automatiquement
automatic-octave-signstcmn ajoute automatiquement les signes d'octaves
automatic-beamstsi cmn doit calculer le poutrage (see beaming meter message)
automatic-tiest si cmn doit insérer les liaisons
automatic-barst si cmn doit insérer les barres de mesure
automatic-restst si cmn doit insérer les silences
automatic-naturalsnil si cmn doit insérer les bécarres
automatic-beat-subdivision-numberst si cmn doit afficher les valeurs des subdivisions irrégulières
automatic-measure-numbersnil peut être t = 1, un nombre, :by-line, ou :by-page
curvy-flagst drapeaux incurvés ou droits
use-italian-octave-signsnil faut-il ajouter "va" à "8" et "ma" à "15"
add-bassa-to-octave-signsnil faut-il ajouter "bassa"
use-abbreviated-staff-namest s'il faut abréger les noms de portée
always-show-gliss-namet faut-il imprimer "gliss" sur des glissandos qui ne seraient pas marqués
always-show-staff-namest faut-il continuer à nommer les portées après la première
always-show-clefst faut-il mettre la clé à chaque nouvelle ligne
automatic-clef-size1.0 dimension des clés placés sous le drapeau always-show-clefs
all-output-in-one-filenil envoyer les changements de page dans un fichier au lieu de fichier séparés
implicit-accidental-style:new-style plusieurs manières pour traiter les altérations
implicit-accidental-duration1
redundant-accidentalst nil enlève les altérations redondantes
accidental-to-note-head-space0.0625 espace entre altération et tête de note
layoutnil mises en page compliquées -- voir plus loin
page-color nil couleur (rgb) du fond de page
page-height11.0 (29.7)inches (cm) -- cm si *cmn-units* = :cm
page-width8.5 (21.0)inches (cm)
left-margin0.5 (1.0)inches (cm)
right-margin0.5 (1.0)inches (cm)
header-margin1.0 (2.0)inches (cm)
footer-margin1.0 (2.0)inches (cm)
titlenil
metronome60 pour add-note et analogues
line-separation2.0 espace entre les lignes
staff-separation1.5 espace entre portées
system-separation1.5 espace entre systèmes
note-head-size1.0 coefficient général d'échelle des notes (les valeurs par défaut sont un peu trop petites)
grace-note-size.5
glissando-thickness.01 épaisseur des glissando-lines (droites)
tie-thickness.04 épaisseur des liés
tie-curvature.125 courbure des liés
slur-thickness.03 épaisseur des legatos (c'est un petit défaut)
slur-curvature.25 courbure des legatos (this is pretty flat)
maximum-slur-slope.75 pente des arcs de liaison
beam-spacing(* 2.125 .126)distance entre poutres
beam-width(* 1.125 .126)épaisseur des poutres
beam-slope-trigger.5min ambitus for sloped beam (.5=half octave)
maximum-beam-tilt.4how tilted beams are allowed to be
partial-beam-length.4max length of a partial beam
partial-stem-length0set this >0 if you want partial stems
stem-width.025width (fatness) of stem
barline-thickness.02thickness of bar lines
ideal-stem-length.5first stab at basic stem length
staff-line-width.02thickness 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-size8
text-connecting-pattern'(10 0)default is an undashed line
text-connecting-thickness.02
first-measure-numbernil début du numérotage des mesures
initial-onset 0premier temps de la partition (pour éviter des tas de silences initiaux)
full-last-line nil si la dernière ligne prend toute la largeur
page-hooknil utilisé pour des trucs spéciaux (voir cmn-ex.lisp)
line-hooknilused for line related actions
free-expansion-factor1.25 blanc ajouté par la justification
music-fontnil nom de la fonte, si ce n'est pas celle de cmn (e.g. "Sonata")
une ligne par page nilsi t, chaque ligne est placée sur une page separée
title-separationnilespace entre titre et portée
default-font"Times-Roman""Times-Roman" "Times-Italic" "Times-Bold" "Times-BoldItalic"
dynamics-size.8default dynamics mark size
brace-space.125space between brace and staff lines
first-dot-spacing.2space between note and first time augmentation dots
dot-spacing.1space between subsequent time augmentation dots
flag-vertical-spacing.2vertical space between stem flags
maximum-subdivision-bracket-tilt0maximum bracket tilt

Sauf indication contraire, c'est la hauteur d'une portée qui est l'unité de mesure. Une portée normale de 5 lignes mesure 1.0. La fonction in-inches (in-cm) traduit de inches (cm) en unités « cmn ». Ainsi si on veut des poutres plus épaisses :

    (cmn (beam-width .275) (beam-spacing .4) staff treble c4 s d4 s)
picture

Avec les curvy-flags on peut choisir des flammes courbées ou droites :

    (cmn (curvy-flags nil) staff treble a4 s)
picture

Les contenus actuels de la partition sont les prochains arguments pour cmn. Toutes les entités qui décrivent un objet musical ou quelque attribut de cet objet utilisent la même syntaxe et acceptent les mêmes « messages ».

Chaque objet ou groupement d'objets peut être tourné, agrandi ou rapetissé horizontalement ou verticalement et aussi être déplacé en n'importe quel endroit de la partition.

Tout fichier de commandes graphiques (fichiers .eps) peut-être traité comme un objet et comme tout autre objet. cmn peut être appelé récursivement, enchâssant des partitions entières dans d'autres partitions. Enfin, il est facile d'inclure vos propres comanndes dans cmn (voir graphics). Dans ce qui suit, je vais utiliser le terme « message » pour désigner une fonction qui affecte l'objet auquel elle a été passée en argument. Par exemple, dans l'expression :

    (meter 6 8 (meter-size 2))

"(meter-size 2)" est un message adressé à l'objet créé par la function "meter", "6" et "8" sont les arguments normaux et "meter" est une fonction qui crée un objet de la partition. Dans ce cas, l'effet du message est de doubler la taille des chiffres :

   (cmn treble (meter 6 8 (meter-size 2))
picture

Données musicales

La musique est décrite par une liste de systèmes, chaque système contient une liste de portées, chaque portée contenant une liste d'objets tels que notes, silences, etc. et chaque objet contient une collection de listes décrivant les attributs. Systèmes et portées sont créés automatiquement si ce n'est pas spécifié dans les arguments. Cela veut dire que (cmn system staff treble) est la même chose que (cmn treble), mais dans des cas plus compliqués, il vaut mieux (et quelquefois c'est indispensable) d'être explicite. En plus des entités intégrées, toute fonction rencontrée dans la liste des arguments de cmn est évaluée (évidemment) et le résultat (soit un un objet ou une liste d'objets) est assemblée aux données comme s'il s'agissait d'une écriture explicite. On dispose ainsi d'un moyen puissant pour faire appel à toutes les ressources de Lisp. Quelques fonctions sont fournies par cmn et d'autres exemples vont suivre.

Dans tout ce qui suit à propos de ce que cmn contient, il ne faut pas oublier qu'un objet répond non seulement à des messages uniques tels que rotate ou x0 (qui seront passés en revue), mais aussi à une liste d'attributs. Un attribut est un code quelconque que vous souhaitez associé à un autre objet (éventuellement lui-même un attribut) et évalué chaque fois que son propriétaire est évalué (affiché). Un point de staccato par exemple est une marque attachée à une note. Le code associé détermine où est l'axe central de la note, s'il doit être au-dessus ou en-dessous et à quelle distance (pour éviter par exemple une collision avec une ligne de portée). Ce code est appelé quand il faut afficher un objet ou calculer sa grandeur. Les messages standard sont :


 dx dy x0 y0 x1 y1 center justification

En général dx et dy déterminent le placement d'un objet par rapport à l'objet auquel il appartient. Une note, par exemple, appartient à une portée et accompagne cette portée quand lignes et pages sont justifiées. Une marque de staccato peut être liée à une note et l'accompagne jusqu'à trouver sa position verticale sur la portée. Très souvent le point (x0,y0) désigne le coin gauche inférieur et (x1,y1) le coin droit supérieur de la "bounding box" (boîte limite) d'un objet. L'axe central n'est connu que des objets qui servent à aligner les objets le long de la portée. Par exemple, si nous voulons déplacer un marcato vers la droite :

(cmn (staff treble (c4 w (marcato (dx .5)))))
picture

matrix

La matrice d'un objet contrôle son orientation et son placement par rapport au propriétaire de cet objet. Ndt : Pas de panique. Il n'est pas nécessaire d'être un spécialiste du calcul matriciel pour se servir d'une matrice dans cmn. Lisez attentivement les commentaires et faites quelques expériences et cmn montre toute sa puissance. On dispose d'un certain nombre de fonctions pour transformer aisément les coordonnées :

    rotate angle	; effectue une rotation en degrés dans le sens des aiguilles d'une montre.
    scale x y        ; étend ou comprime l'objet en multipliant par x et y 
	; (scale 0 0) ou invisible rend l'objet courant invisible
    mirror (fonction) et mirrored (variable)	; le même effet que (scale -1 1)
    transform matrix	; multiplie la matrice de l'objet courant par la matrice donnée

La matrice la plus externe sert pour déplacer la partition sur la feuille :

(cmn (matrix (list 1 0 0 1 200 0)) staff treble)

Les 4 premiers nombres ("1 0 0 1") produisent une partition de dimensions et orientation inchangée, le 5e est le décalage horizontal et le 6e le décalage vertical (en pixels).


Encrage (pattern)

L'encrage d'un objet détermine comment il va apparaître (son « encre ») :

    gray-scale &optional (val 0)  ; 0 = noir (par défaut), 1 = blanc, val est entre 0 et 1
    détouré &optional (val 0)    ; 0 = extra fin, val est un nombre décimal
    couleur r-g-b     ; 1.0 = couleur, 0.0  absent (e.g (color '(1.0 0.0 0.0)) => rouge)


(cmn staff (treble mirrored (dx .5)) (treble (rotate 180) (dy .75) (color '(0.25 0.5 0.0)) (scale -2 .5)) (bass (gray-scale .5) (dx .75)) (bass (outlined .02) (dx .75)) (quarter-rest (color '(1.0 0.0 0.0)) (rotate 45) (dx .85) (scale 1 2)) (eighth-rest (rotate 90) (dy -.4) (dx .25) (color '(0.0 0.5 0.5)) (scale 2 1)))
picture

Les noms des couleurs de X11 correspondent au rgb.lisp. (cmn (treble aquamarine) c4 q) par exemple. Pour des exemples plus complexes lire le fichier cmn-ex.lisp.


system &rest objects

Chaque partition est organisée en groupes de portées, chaque groupe est appelé un système. La fonction system ressemble à la fonction cmn : elle placer ses arguments sous forme de d'attributs et de portées pleines d'objets musicaux. Les objets principaux d'un système sont des portées et des accolades de système. Il y a deux sortes d'accolades : les courbes et les droites. Si une portée a les deux (cordes divisées par exemple), il faut affecter l'accolade droite au système et la courbe à la portée inférieure :

  (cmn (system (staff)) (system bracket (staff) (staff brace) (staff)))
picturepicture

S'il y a un attribut avant qu'une portée ait été créée, il est affecté au système. Autrement il est affecté à la portée courante.

On m'a signalé que la plupart entendent par « système » le groupe que je désigne par « ligne » et qu'on utilise le mot « section » là où j'écris « système ». Pour moi « section » est une partie d'une pièce (voir la fonction section plus loin) et non pas « partie d'un ensemble ». J'espère que cette terminologie non usuelle ne sera pas cause de trop de confusion.


staff &rest objects
   staff-name staff-size staff-lines tied-to start-line line-separation

Chaque portée traite ses arguments comme le font cmn et system -- elle essaie d'en faire des armatures, des mètres, des clés, des barres de mesure, des notes, des accords etc. Une portée a un nom facultatif (normalement l'instrument qui lui est associé), une dimension (un multiplieur sur l'ordonnée y de chaque objet sur la portée), un nombre de lignes (normalement 5), une liste d'attributs et une liste d'objets.

 (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))
picture

Si un nom de portée comporte un "-flat" (bémol) ou un "-sharp" (dièse) après la première lettre, cmn lui substitue le symbole musical. A moins que vous en décidize autrement (via les options always-show-staff-names et use-abbreviated-staff-names) les lignes suivantes d'une portée produisent une version abrégée du nom de l'instrument. Le message tied-to se superpose aux portées. On fixe la position et la largeur d'une portée par dy, x0 et x1. Par exemple, pour faire une portée vide de 3 inches :

     (cmn (staff (x1 (in-inches 3))))

une partition imprimée verticalement :

     (cmn (transform '(0 1 -1 0 200 200)) (staff (x1 7.5) treble c4 e d4 e))

ou du papier à musique :

     (cmn (header-margin 0) (engorge 
        (loop for i from 0 to 6 collect (staff (x1 (in-inches 7.5))))))

Si le message adressé à la portée est gray-scale, tout est imprimé avec cette couleur. Le message start-line est utile pour les parties de percussion -- il specifie quelle ligne est la ligne initiale (3=mid).

Le message line-separation est utile pour changer la distance entre lignes de la portée indépendamment des valeurs globales size et *staff-line-separation* (par défaut fixé à 0.126).

Dans stf.lisp il y a un exemple changeant les lignes de la portée aux temps impairs.


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
   begin-flanges-repeat-bar
   end-flanges-repeat-bar

(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)
picture

Si une barre est placée au début ou à la fin d'une portée, elle justifiée par rapport à la droite ou la gauche de cette portée. Les barres "pleines" traversent tous les systèmes. Pour qu'une barre générale soit placée au début de chaque nouvelle ligne d'un ensemble, mettre au début de la dernière portée de l'ensemble (pas très clair : voir l'original du texte).

  double terminal justification within-measure 
  dashed dots-left dots-right broken 
  height breathing-space thickness flanges

Voilà une barre épaisse, haute d'une moitié d'une portée placée au milieu de la portée :

  (cmn (barline-thickness .2) treble c4 q (bar (dy .25) (height .5)) c4 q)

bracket &rest objects
brace &rest objects

Le "brace" est une braquette dans le style des accolades de piano. Il faut le placer sur la portée inférieure. L'accolade peut relier n'importe quel nombre de portées si on utilise le message "brace-staves".


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 ...) est la même chose que (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)
picture

Si on a omis de donner une clé à une portée, la clé est mise d'office (pour permettre le placement des notes), mais elle est mise à l'échelle (0 0) pour rester invisible. Les clés ont le message addtionnel " unjustified" (non justifié) et "breathing-space" (espace soufflet). Tenor-treble est une clé de sol avec un "8". À moins que la partition ait l'attribut (score-slot) (always-show-clefs nil), la clé est affichée au début de chaque nouvelle ligne.


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))
picture

Avec les notes, on peut utiliser ou la notation cs/cn/cf ou la fonction sign ; avec les ornements, utiliser ornament-sign.

Le fichier quarter.lisp implémente des symboles pour noter les quarts de ton.


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

Pour annuler une armature (c. à d. mettre des bécarres là où il y avait des altérations), on utilise la commande cancel. Pour des armatures spéciales, on utilise def-key et on fait suivre avec les noms des notes altérées

  (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))
picture

meter numerator denominator &rest objects

"meter" affiche la métrique et impose la métrique de la portée (pour les besoins du poutrage par ex.). Numérateur et dénominateur peuvent être des entiers, des chaînes ou des symboles. Les mètres dénommés sont

  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.)
picture

On change les dimensions des symboles de la métrique avec le message meter-size. Si on souhaite que le poutrage respecte une métrique sans que celle-ci soit indiquée, mettre meter-size à 0. La métrique accepte les messages complémentaires : suppressed-denominator, note-head-denominator, et beaming. Le message beaming se répercute sur le poutrage automatique -- cf. des exemples dans cmn-ex.lisp.


note &rest objects

Les dénominations standard des notes en Score et en Common Music c0..bs8 sont tout à la fois implémentées comme constantes et comme fonctions : c4 est le c médian (Ut3); cf4 abaisse c4 d'un demi-ton et bs4 élève b4 d'un demi-ton. En tant que fonction, toutes acceptent tous les messages usuels. Les durées et les "onset times" sont traités en tant que noires, indépendamment du tempo. Ce qui veut dire que (onset 2.5) fait débuter la note concernée au temps d'une 2.5e de noire -- la durée véritable en secondes ne nous intéresse pas. De même,(duration .5) signifie une croche, quel que soit le tempo ou la métrique. Cela ne peut prêter à confusion que dans les mètres composés (6/8) où on calcule "onsets" et durées en noires et non en 1.5 de noire. Malheureusement, il y a ces quelques cas spéciaux de la musique occidentale (trémolos rythmés etc.) qui sont à traiter séparément. Voici les valeurs rythmiques :

  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 signifie double-croche en triolet. Le point indique une durée pointée : ainsi q. est une noire pointée. En général (rq n) produit un objet rythmique ayant la valeur de n noire : q = (rq 1), tq = (rq 2/3), deux cinquièmes de noire (rq 2/5) etc. Il faut utiliser cette forme pour cmn ait une chance pour comprendre que vous souhaitez un triplet de 17e. Normalement les nombres et les crochets des rythmes irréguliers sont ajoutés automatiquement par cmn.

Quand les notes ne vont pas simplement à la queue leu leu, on peut utiliser les messages "onset" pour indiquer explicitement les décalages de temps (ou bien utiliser les "beat message" qui est relative au décalage de mesure et compte les temps à partir de 1).

Si les notes ne vont pas simplement à la queue leu leu, on peut utiliser les données onset pour indiquer explicitement le point temporel (ou bien indiquer la battue qui se réfère au point temporel dans la mesure qui numérote les battues à partir de 1). Je conseille de s'inventer quelques exercices pour bien maîtriser ces possibilités.

Les messages additionels aux notes sont :

  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
  dots flags head-quarters dashed-stem

La direction de la hampe est donnée soit par :up, :down, :none, ou nil. Si elle est nil, cmn essaie de tracer la hampe à partir du contexte. :none enjoint de ne pas tracer de hampe. stem-up, stem-down, no-stem sont d'autres 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))
picture

dashed-stem trace une hampe en pointillés. Sa valeur est nil, t ou une pattern-list (chaîne servant de modèle). Autres variables : dashed-stem et whisper.

Comme c'est un peu la galère pour ne pas perdre la trace des onsets, ties, (décalages, liaisons, etc.) quand il y a plusieurs voix sur une portée, on peut coder les voix sur des portées différentes et les lier ensemble par la commande tied-to :

(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)))
picture

note-head décrit la tête de note. nil, valeur par défaut, est identique à :normal et trace une tête normale. Autres types : :diamond, :diamond-1 (côtés inclinés), :triangle, :square, :x, :circled-x, :artificial-harmonic, :tremolo, :slash, :none, :airy-head, :breath-out, :breath-in, :arrow-up, :arrow-down. La tête de note peut aussi être n'importe quel signe graphique -- il sera placé à l'endroit de la tête.

(cmn (size 24) staff treble 
  (c4 e (note-head :square)) 
  (e4 e (note-head :x)) 
  (g4 q (note-head :triangle)))
picture

Les attributs supplémentaires sont simplement ajoutés à la liste des arguments et il appartient à cmn de se débrouiller pour les placer. Les points, les drapeaux (flags) et les commandes de têtes (head-quarters) peuvent se mettre à la place des implémentations habituelles de cmn (head-quarters dit s'il faut utiliser des têtes de noire, de blanche ou de ronde) :

(cmn
 (automatic-rests t) (automatic-ties nil) (automatic-beat-subdivision-numbers nil) 
 staff treble (meter 7 8)
 (c4 (rhythm 7/16) (dots 0) (flags 1) (setf sub (beat-subdivision- (subdivision "8:7"))))
 (c4 (rhythm 21/16) (dots 1) (flags 0))
 (c4 (rhythm 7/4) (dots 0) (flags 0) (head-quarters 2) (-beat-subdivision sub))
 (c4 q. (dots 0) (flags 5))
 (c4 (rhythm 3/16) (dots 0) (flags 3) (setf sub (beat-subdivision- (subdivision "4:3"))))
 (c4 (rhythm 9/16) (dots 1) (flags 2))
 (c4 (rhythm 3/4) (dots 4) (flags 0) (-beat-subdivision sub)))

S'il y a un risque de collision, cmn essaie de placer les têtes de telle façon que toutes soient visibles. Si on veut qu'une seule tête n'apparaisse dans un unison, mettre la variable *overlap-noteheads* à t. Pour confirmer à cmn que les valeurs rythmiques sont exactes (donc pour empêcher qu'elle "rationalise" le code), mettre la variable *exact-rhythms* à t.


chord &rest objects

chord note un accord et comporte un argument obligatoire :

  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))
picture

Les messages à l'objet chord (liaisons, dessin des têtes de notes, valeurs rythmiques etc.) affectent chaque note de l'accord. Pour changer les attributs d'une note particuliaire, envoyer le message à cette note.

Des accords sur plusieurs portées utilisent le message tied-to (voir 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))
picture
picture
auxiliary-note &rest objects

auxiliary-note crée un signe qui contient une petite note. Ce signe est utilisé normalement pour noter les harmoniques (hauteur réelle). Les arguments pour auxiliary-note sont les mêmes que pour les notes normales.

(cmn staff treble (c4 q (note-head :diamond) 
    (auxiliary-note c6 no-stem in-parentheses)))
picture
grace-note &rest objects
grace-notes &rest objects
appoggiatura &rest objects

  stem-direction slashed slurred 
  unjustified stem-dy slash-thickness

La valeur de stem-direction est normalement :up. slashed est t pour les petites notes (grace-notes) et nil pour les appoggiatures. slurred est t pour les deux. Il est dur d'obtenir automatiquement les dans tous les cas. Voir ce qu'on en dit sous slur. S'il n'est pas nécessaire de réserver de la place supplémentaire pour les petites notes, on utilise la commande unjustified. Quand il y a plusieurs petites notes, il est d'usage de tracer deux barres sur deux ou trois notes et trois barres s'il y a plus de trois notes. Cela peut être modifié en spécifiant exactement le rythme souhaité :

(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
picture

Les appogiatures sont semblables aux petites notes en ce qu'ils sont représentés par des corps plus petits et qu'il n'en est pas tenu compte en tant que décalage et durée (on place la note principale et les petites suivent). Les appogiatures ne sont pas barrées et par défaut elles sont représentées par des croches. Autrement la syntaxe ne change pas.

Autre problème
Faire une note précédée et suivie de petites notes. Voir Dinicu horastaccato.
(cmn (size 40) 
	(output-file "graceafter.eps")		  
  (staff
	(clef treble)(meter 2 4)
	(d5 h begin-slur begin-tie	   
	   (trill (wavy-line '(0 0 3.5 0))(dy 0.5))
           (grace-note (slashed nil) e5 s)) bar
	(d5 h end-tie begin-tie)
	(d5 h end-tie begin-tie)
	(d5 h end-tie end-slur)
	
	(bar invisible)
	(meter 1 16 invisible)
	(d5 invisible s (grace-note (slashed nil) (cs5 s begin-slur)
	(d5 s end-slur)))
	bar
))
La solution (povisoire ?) consiste à placer des objets invisibles.

picture

rest &rest objects
  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)
picture
Une autre méthode consiste à indiquer simplement (rest (rq <ratio>)).

Sauf indication contraire (via (automatic-rests nil)), cmn complète par des silences chaque fois que les décalages (onsets) et les durée précédentes semblent avoir laissé des trous :

(cmn staff treble (c5 s (onset .75)) (g4 e. (onset 1.25)))
picture

Dans cmn-ex.lisp et rests.lisp se trouvent des abréviations pour les silences les plus usuels et le code pour d'autres sortes de silences (p.ex. des formes inclinées). Si la mesure est plus grande qu'une ronde (p.ex. 3/2 comme dans joh.cmn), le whole-rest correspond à un silence de quatre noires ; pour indiquer une mesure de silence, il faut donc utiliser whole-measure-rest.


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 niente

Si vous souhaitez quelque autre indication, essayez dynamic n &optional spacing-data. Pour placer les soufflets (crescendo, etc), voir crescendo); pour les textes joints tels que poco a poco voir connected-text. Un exemple de la fonction dynamic : (cmn staff treble c4 q (dynamic "fffffff")). Les spacing-data contrôlent l'espacement (interne ?) des glyph -- (cmn treble c4 q (dynamic "fffspz" (list .2 0 .2 0 .15 0 .05 0 0 0 0 0))). Pour une marque (vertical line?) subito mettre ou "I" (un i majuscule) ou "subito" :

(cmn (free-expansion-factor 3.8)
     (c4 h (begin-crescendo (begin-dynamic (dynamic "fIp")) (end-dynamic  (dynamic "Ipp" ))))
     (c5 h (stem-up) (end-crescendo))
     (c4 h (begin-crescendo mf (dynamic "Ip")))
     (c5 h (stem-up) (end-crescendo)))

Articulation

  staccato accent little-swell wedge 
  tenuto marcato down-bow up-bow 
  detache martele thumb natural-harmonic 
  stopped-note open-note pedal pedal-off
  bartok-pizzicato snap-pizzicato left-hand-pizzicato
 swirl mouth-position

L'exemple dans l'introduction utilise la plupart de ces marques ; little-swell prend une marque dynamique optionnelle ; marcato et les pizzicato ont un marque optionnelle d'épaissseur. Dans pedal.lisp on voit comment noter les trois pédales du piano. Voir aussi accent.lisp et percussion.lisp pour certains symboles utilisés au 20e siècle tels que :

picture

Ornements

  mordent inverted-mordent double-mordent turn 
  short-trill trilled-turn  trill tr

Chaque symbole comporte un signe optionnel (ornament-sign). Le trille peut prendre plusieurs messages additionnels - le but est de gérer les détails. Les options sont :

  sign-position other-note wavy-line wavy-time 

"sign-position" peut être ":right" (par défaut), ":up", ou ":in-parentheses". "wavy-line" crée une ligne ondulée à partir de la note. "wavy-time" indique où doit se terminer la ligne ondulée (en valeurs onset-style), la valeur par défaut est la fin de la note. Les arguments possibles pour "wavy-line" sont "t", "nil", ou une liste ; si c'est une liste, les arguments '(dx0 dy0 dx1 dy1) permettent de prolonger la ligne de différentes manières.

(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))))
picture

arpeggio arrow arrow-up arrow-down no-arpeggio 

Ces articulations s'appliquent principalement aux accords. L'arpeggio peut avoir une flèche en haut ou en bas. Non-arpeggio est une braquette sur le côté gauche de l'accord.

  (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))
picture
arrowhead-up arrowhead-down

tracent les flèches.


fingering &rest objects

En plus des arguments habituels, les doigtés "fingering" acceptent des nombres qui sont alors affichés en une pile verticale au-dessous ou en-dessous de l'objet. "fingering-size" et "fingers" existent. Les arguments du doigté ("fingering") peuvent aussi être des chaînes de caractères ou des objets-textes.

(cmn staff treble (e4 q (fingering 3)) 
  (chord (notes c5 g4) q (fingering 7 2)))
picture

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)
picture

text &rest objects

"text" est une sorte de marque tout comme "staccato". Le texte peut utiliser toutes les fontes disponibles. On peut changer l'échelle et faire des rotations. La fonte par défaut est celle donnée par le paramètre "text-font". Les messages concernant les fontes sont :

 font-name font-size font-scaler ; par défaut "font-name"="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))))
picture

La justification par défaut est (:none) ; en outre le texte peut être justifié à gauche : (:left), centré (:center) ou justifié à droite (:right) -- (text "hi" (justification :right)). (non justifié = (justification :none)). Du texte lié est mis en page par "text-" et ses copains ; voir ici. "font-size" donne la vraie dimensions (non scalarisé), tandis que "font-scaler" applique à "font-size" l'échelle de la partition. Le placement d'un texte est normalement attaché à l'objet (le c4 de notre précédent exemple), mais cela peut tourner au cauchemar pour les paroles de chants, etc. Pour les messages spéciaux, il vaut mieux utiliser les messages "x" et "y", qui sont ou bien "nil" (par défaut) ou une forme "lambda" qui remplace toutes les autres données. La forme est appliquée au texte, à l'objet, à la partition et à tous les autres arguments passés à la procédure de mise en page. Voir les exemples des fichiers ".cmn". et le prologue.

Pour les indications de tempo, le nom de l'auteur, etc., une solution pratique est d'attacher ces textes à la clé :

	(clef treble ; la parenthèse reste ouverte
	(text "Pas trop vite" (font-name "Times-Roman")(font-size 12)(dx 1.)(dy 1.5))
	
	(text "Johannes Goehl (1935 - 2002)" (font-name "Times-Roman")(font-size 12)(dx 22.)(dy 2.5))) ; la parenthèse se ferme

Pour placer du texte : (cf. aussi lyrics.lisp ):

  (defun lyrics (&rest args)
    (apply #'text (font-name "Times-Roman") (font-scaler .5) 
      (y #'(lambda (mark note score &optional justifying) (- (staff-y0 note) .9)))
      (x #'(lambda (mark note score &optional justifying) 
        (+ (x0 note) (if (sign note) .2 0))))
      args))

Pour obtenir un glyphe spécial en pointant sur sa situation dans la fonte, utiliser la fonction glyph (voir exemple dans cmn-ex.lisp).

Le message underlined souligne le texte.

Accents, signes diacrituques, umlaute Voilà ce que Bill Schottstaedt a dit :
 
 > Please, is there a way to get diacritics signs in a text with CMN ?

Si vous savez où ils se trouvent dans la fonte, vous pouvez indiquer
l'adresse dans le texte :

   (cmn (prolog #'(lambda (score)
                     (make-ISO-encoded-version score
                       "Times-Roman" "ISO-Times-Roman")))
     staff treble
     (c4 q (text "s\\374\\337"
             (dy 1.5) (dx -.25) (font-name "ISO-Times-Roman")
             (font-scaler .5) (gray-scale .25))))

qui donne "s" "u-umlaut" "double-s". Mon grand-père a écrit son
nom avec a-umlaut.

Multi-note marks

Il y a quantité de marques qui s'appliquent à plus d'une note : ties, slurs, beams, etc. CMN les gère de deux manières. Chaque marque multi-note est doté d'une begin-<marque> et d'une end-<marque> ; formes qui sont à la fois des variables et des fonctions (comme tous les autres objets) qui sont gérés par des piles (dans le sens informatique ;-). Ce qui veut dire que la dernière à débuter est la première à finir - les marques sont enchâssées sans problèmes.

Si les marques doivent se croiser, il clarifier quelle begin-<marque> correspond à quelle end-<marque>. En CMN cela est fait par des identificateurs. Voici un exemple de la forme élémentaire :

(cmn staff treble (c4 q begin-slur) (d4 q) (e4 q end-slur))
picture

Et un exemple avec des identificateurs:

(cmn staff treble (c4 q (setf slur-tag (begin-slur))) (d4 q (end-slur slur-tag)))
picture

L'identificateur est simplement une variable (on peut lui donner n'importe quel nom). Dans l'exemple donné, l'identificateur n'était pas nécessaire, mais voyez cet exemple :

(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)))
picture

Ici la ligne joignant les mots doit être informée où se trouve le mot suivant de la phrase. Sans les identificateurs (

upper-text, 
lower-text
) c'est assez difficile.


Connected text

Pour lier un texte à des notes et des passages, on utilise les commandes

  text- -text- -text    text_  _text_  _text

Elles acceptent un nombre quelconque d'arguments, l'un d'entre eux devant être une chaîne ou un objet texte. text- démarre un texte et continue soit avec -text- ou avec -text. -text- est relié à la séquence courante ou à celle indiquée par une étiquette et permet de la continuer. -tex- est relié de même à une séquence (courante ou étiquetée) et la termine. Graphiquement, la jointure est faite par la liste text-connecting-pattern qui par défaut est une simple ligne entre les fragments de texte (soit '(10 0)). Pour obtenir une ligne pointillée :

(cmn (text-connecting-pattern '(5 10)) staff treble
  (c4 h (text- "hi")) (d4 q) (d4 q (-text- "ho")) 
  (e4 q) (e4 h (-text "away!")))
picture

La position verticale du motif peut être commandée par connecting-pattern-level. D'autres motifs sont : :dash (centré entre les mots) et :arrow (un flèche à droite). L'initialiseur connecting-pattern-thickness ou le message thickness précise l'épaisseur de la ligne de jonction. text- retourne une étiquette qui peut être utilisée pour distinguer des séquences de texte simulténées. Si text- rencontre un message, la forme lambda associée est appliquée à l'ensemble du texte (voir joh.cmn). Pour changer localement un motif de connexion, il faut appliquer le message connecting-pattern à text- -text- ou -text. text_ et ses collègues agissent comme text-, mais placent le motif de connexion à la ligne de base (au niveau du point) et non pas à mi-hauteur. Voir les commentaires dans le fichier cmn3.lisp traitant de plusieurs fonctions lyriques, qui augmentent les moyens de contrôler le placement des textes et leur connexion.


glissando and portamento

  glissando-to &rest objects   
  portamento-to &rest objects

  begin-glissando end-glissando begin-portamento end-portamento 
  glissando- -glissando portamento- -portamento

Ceci trace la ligne reliant deux notes avec, le cas échéant, un texte sur la ligne inclinée. La ligne est normalement droite ; pour obtenir une ligne ondulée, utiliser le message wavy-line. Avec le message thickness ou avec le score slot : glissando-thickness on ajuste l'épaisseur de la ligne (droite).

(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)
picture

S'il y a de la place, cmn ajoute « gliss » ou « port » ou autre chose à la ligne.

(cmn staff treble
  (c4 h (begin-glissando 
          (text "up up up" (font-name "Times-Roman") (font-scaler .6))))
  (c5 h end-glissando))
picture

crescendo and diminuendo

  begin-crescendo begin-diminuendo end-crescendo end-diminuendo 
  crescendo- -crescendo diminuendo- -diminuendo

Ceci crée les soufflets utilisés pour noter les crescendos et diminuendos. Un soufflet va de la note courante et va ou bien jusqu'à la note à laquelle correspond le message end-crescendo ou bien jusqu'à la fin de la durée. Le souffler peut démarrer n'importe où : le début est différé par onset-offset. Le message width détermine l'ouverture du soufflet. On peut spécifier les valeurs dynamiques à placer au début et/ou à la fin d'un soufflet, soit en passant la valeur à la fonction begin-crescendo soit avec les messages begin-dynamic et end-dynamic. La macro always-dyn-up place soufflets et valeurs au-dessus de la portée. Si on utilise la fonction begin-crescendo (ou begin-diminuendo), end it with the function end-crescendo (end-diminuendo), not the variable form.

(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)))
picture

Si on souhaite mettre l'indication cresc., il faut utiliser la fonction text attachée à une note

(cmn staff treble 
  (c4 q (text "cresc." (dy -2.0)(font-name "Times-Italic")
    (font-scaler 0.5)))
  

Ties

  begin-tie end-tie tie-direction tie-curvature 
  dashed dx0 dy0 dx1 dy1 breathing-space

Les liaisons sont gérés comme les glissandos. tie-direction indique le sens de la courbure :up ou :down. tie-curvature indique le degré de courbure ; la valeur par défaut figure dans le "slot" initial. L'argument pour dashed est une liste : longueur_du_trait longueur_de_l'espace.

(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))
picture

Si des accords sont liés, cela s'applique automatiquement à toutes les notes de l'accord.

(cmn staff treble (chord (notes c4 e4 g4 c5) q begin-tie) 
  (chord (notes c4 e4 g4 c5) q end-tie))
picture

On peut aussi lier des notes une par une :

(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))
picture

Sauf indication contraire ((automatic-ties nil)), CMN trace les liaisons chaque où c'est nécessaire. Voir ring.lisp pour l'usage de ring- et consorts (ties off into space).

(cmn staff treble (meter 2 4) f4 e. f4 q. f4 h.)
picture
(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))
picture

Liaisons (Slurs)

  begin-slur end-slur 
  slur- -slur- -slur

Les liaisons sont comme les prolongations, mais ne sont pas limitées à deux notes. La cmn cherche à faire de jolies liaisons, mais souvent se trouve coincée. Dans ce cas, il faut intervenir et ce n'est pas facile. Il faut éditer une liste de deux listes, chacune comprenant 6 points. Ce sont les points de contrôle de deux courbes de Bézier qui tracent la liaison. '((x1 y1 x2 y2 x3 y3) (x2 y2 x1 y1 x0 y0)) donnent l'allure générale. $$$ with the slur thickness subtracted from y1 and y2 on the return run. $$$ Le begin-slur est doté de nombreux messages pour qu'on puisse décrire les liaisons :

  dx dy dx0 dy0  dx1 dy1 dx2 dy2 dx3 dy3 
  slur-direction slur-thickness slur-curvature dashed

dx et dy sont appliqués à tous les points, les autres ne concernent que les points indiqués. (begin-slur (dy -.25)) descend la liaison entière de 0.25, mais (begin-slur (dy0 -.25)) ne descend que les 4 premiers points qui décrivent la liaison. "dashed" a le même sens que pour les prolongations.

(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)
picture

tremolo &rest objects

Il y a deux sortes de tremolos : "unmeasured" (hors mesure) et "measured" (en mesure). En outre, il faut choisir le style impliquant poutres, barrés, liaisons et tête de notes sans que cela soit toujours cohérent. Par exemple, un manuel de notation prescrit que les trémolos de blanches doivent avoir une poutre et deux barrés, les trémolos de noire pas de poutre et trois barrés, les croches une poutre et deux barrés, mais les têtes pleines pour qu'on puisse les distinguer des blanches. Ce serait logique de ne pas mettre de poutres mais trois barrés aux trémolos de blanches ou de noires. Grumble! Essayons d'y voir clair. Il y a d'abord :

  begin-tremolo end-tremolo begin-measured-tremolo end-measured-tremolo
  unmeasured-tremolo tremolo paranoid-tremolo measured-tremolo

"begin-tremolo" et "end-tremolo" sont des trémolos "unmeasured". Le début et la fin conviennent aux cas où il y a deux notes par trémolo. Les autres ("unmeasured-tremolo", etc) conviennent aux tremolos de notes seules. Aux trémolos paranos on ajoute le mot "trem.". Ces cas ont les messages supplémentaires :

  tremolo-position	:on-stem ou :between-stems
  measured		t ou nil
  paranoid		t ou nil
  tremolo-slashes	nil (=3) ou un entier
  tremolo-beams		nil ou le nombre de poutres
  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))
picture

Poutres

Les poutres sont mises automatiquement ou à la main. Si l'option automatic-beams est t (par défaut), le poutrage automatique s'adapte à la métrique s'il peut. Un poutrage explicite prévaut à l'automatique. Les commandes pour un poutrage explicite sont :

  begin-beam end-beam no-beam no-beam-break
  beam- -beam- -beam
  beam-direction explicit-beams dx dy dx0..dy1    ;voir exemples dans cmn-ex.lisp

Les deux premiers sont sont comme begin-slur et end-slur et s'appliquent à toutes les notes de la portée entre begin-beam et end-beam. Beam- et ses semblables sont comme text- et ses semblables. Voici un exemple des trois possibilités :

(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)))
picture

Les nombres complétant les division rythmiques dites "irrationnelles" sont aussi simples que possible -- cmn ajoute les braquettes aux groupement seulement s'il est indispensable. Pour en permettre l'usage explicite :

  beat-subdivision- -beat-subdivision- -beat-subdivision no-beat-subdivision

Ils acceptent des messages supplémentaires (un nombre, une chaîne ou un objet texte) and braquetté (bracketted). Ce dernier peut être t (par défaut), nil, :up ou :down. Les détails peuvent être changés par dx, dy, dx0, dy0, dx1, dy1 et le "bracket-type" (voir 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)))
picture

Si les notes poutrées appartiennent à différentes portées, commencer la poutre sur la portée la plus élevée même si les notes de cette portée ne s'accrochent que plus loin :

(let ((tag nil))
  (cmn
   (staff bass
	  (c3 e (setf tag (beam-)))
	  (quarter-rest invisible) ; not strictly necessary, but improves spacing
	  (eighth-rest invisible))
   (staff bass
	  (eighth-rest invisible)
	  (d3 e (-beam- tag))
	  (ef3 e (-beam- tag))
	  (g3 e  (-beam tag))
	  bar)))

Si les "onsets" sont données explicitement, les notes à poutrer sont triées automatiquement. Des poutre en éventail (utilisées par Bartok et d'autres) sont implémentées dans le fichier "wedge.lisp" (voir aussi des exemples explicites dans cmn-ex.lisp). La fonction rqq dans rqq.lisp étend cette notion à des rythmes bien plus extravagants. Voir les commentaires et les exemples dans ce fichier. Voici un exemple de rqq:

  (cmn treble (rqq '(2 ((1 (1 1 1 2)) (1 (1 2)) (1 (1 2 4))))
                g4 fs4 sixteenth-rest en4 (chord c4 ef4) eighth-rest af4 bf4 gf4))
picture
* Cet exemple est vraiment convainquant et montre ce qu'il est possible de faire avec CMN le plus simplement du monde
picture

* Remarquer :
- deux voix sur une portée avec des rythmes pas toujours concordants
- le passage de la poutre d'une portée à l'autre

Poutres sur deux portées

Au point de départ, écrire
(setf _identifiant_ (beam-))
et au point d'arrivée, écrire
(-beam _identifiant_)
. Pour accrocher les notes entre ces deux points, écrire
( ... la note ...(-beam- _identifiant_))
Pour les cas complexes, voir l'exemple franz.cmn et ccarh93.cmn (pages 13 - 19)


endings
*****************************

Voilà les indicateurs de première et de seconde reprise.

  begin-first-ending begin-second-ending
  end-first-ending end-second-ending

Begin-first-ending et begin-second-ending acceptent des messages additionnels :

  max-line	;le numéro de la ligne avec la plus haute (plus basse)
note sous le signe d'octave
  terminal	;t si la terminaison est aussi
la fin de la pièces

(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)
picture

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))
picture

change-beat mm 

On indique ainsi le tempo et (comme montré ci-dessus) le changement de tempo. Le changement de battue a deux arguments : l'ancienne et la nouvelle. mm prend deux arguments : la valeur métronomique et si nécessaire la valeur rythmique concernée (par défaut une noire). Normalement la valeur métronomique vient en plus de l'indication du tempo $$$???$$$[ is a parenthetical addition to the tempo indication]. mm also responds to in-parentheses and the various justification messages.

repeat-measure 

Le symbole repeat-measure est centré entre deux barres de mesure et vaut une mesure. En tant que fonction, il accepte un nombre en option qui sera affiché au-dessus du symbole.

(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)
picture

octave transposition

Les transpositions d'octaves sont mises automatiquement pour les notes très hautes ou très basses, sauf si on initialise (automatic-octave-signs nil).

(cmn staff bass c5 e d5 e f5 e g5 e c5 q g4 q c4 q)
picture

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  

Ils agissent comme les ligatures et les liaisons. 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)
picture

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)))
picture

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

Dans une partition cmn on peut insérer des fichiers .eps et avec changements d'échelle, rotations etc. La commande graphics a besoin d'un paramètre additionnel : file dont l'argument est le nom du fichier à insérer.

(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))))
picture

The contents of the .eps file are copied into the output file of cmn.


NDT : Quelques difficultés :

La Bounding Box peut avoir un comportement capricieux : pour s'en rendre compte, regarder le résultat sur une feuille très grande (A3 ou plus) ; des fois ce qu'on a inséré se retrouve sur le bord.

Comment ménager de la place pour ce qu'on vient d'insérer ? Dans l'état actuel (de mes connaissances) on obtient des superpositions.

.
with-cmn &rest objects

On peut transformer une partition en marque et l'appliquer par with-cmn. with-cmn agit comme cmn sauf qu'elle n'ouvre aucun fichier.

picture

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)...)

De la même veine que engorge il y a staff-engorge, system-engorge et score-engorge, cette dernière fonction impliquant la fonction score. Chacune de ces fonctions prend une liste de portées, systèmes ou partitions et retourne le nouvel objet (portées, systèmes, etc) contenant toutes les données. Par exemple,

  (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)))

Les arguments pour system-engorge et score-engorge doivent être compatibles, ce qui veut dire que les listes des systèmes et des portées doivent se correspondre. 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.


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:

   (funall (sundry-mark sundry) sundry object score justifying).

The staccato function, for example, is essentially:

(defun staccato (&rest objects)
  (make-instance 'sundry :name :staccato 
    :mark #'(lambda (mark note score &optional justifying)
              (circle score 
                      (+ (x0 note) (center note)) 
                      (+ (y0 note) .25)
                      .05 0 360))))

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		;add a line to (x,y)
  rlineto score dx dy		;add a line from the current point to (current-point+dx,current-point+dy)
  moveto score x y		;add a jump to (x,y) 
  rmoveto score dx dy		;add a jump from the current-point to (current-point+dx,current-point+dy)
  curveto score x0 y0 x1 y1 x2 y2
	;add a Bezier curve from the current-point using these three points as guides
  show score mark		;display a mark of some sort
  draw score			;cause the current lines to be drawn
  fill-in score			;cause the current lines to be filled in
  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, cmn-glyphs.lisp for the standard music symbols, and percussion.lisp for a variety of simple examples. 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 &optional size)
  (let* ((y-off (+ (y0 mark) (dy mark) (staff-y0 note) 
		   (* (max 11 (+ 4 (head-line note))) *staff-line-separation*)))
	 (r (/ 10 40))
	 (x-off (+ (x0 note) -.05 (dx mark) (center note) (x0 mark))))
    (with-thickness score mark .025
      (circle score x-off y-off r)
      (circle score x-off y-off (* r .6) 190 350)
      (circle score (- x-off (* .33 r)) (+ y-off (* .25 r)) (* r .1))
      (circle score (+ x-off (* .33 r)) (+ y-off (* .25 r)) (* r .1)))))

Using head-line, 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 (.025), draw the outer circle, the mouth circle, and the two eyes. Now, to make this a normal CMN 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))

et maintenant nous pouvons utiliser notre nouvelle marque :

(cmn staff treble c4 q smiley-face)
picture

Voici un exemple traçant un ensemble arbitraire de lignes connectées :


(defun a-line (line-data &rest objects)
  ;; line-data is assumed to be a list of x y breakpoints
  (apply #'mark
	 (lambda (mark note score &optional size)
	   (let* ((y-off (+ (y0 mark) (dy mark) (staff-y0 note)))
		  (x-off (+ (x0 note) (dx mark) (x0 mark))))
	     (with-thickness score mark 0
	       (moveto score (+ x-off (first line-data)) (+ y-off (second line-data)))
	       (loop for x in (cddr line-data) by #'cddr and y in (cdddr line-data) by #'cddr do
		 (lineto score (+ x-off x) (+ y-off y)))
	       (draw score))))
	 :a-line
	 objects))

(cmn staff treble c4 q (a-line '(0 0 1.0 .5 2.0 0)))


  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 (text "s\\374\\337"
            (dy 1.5) (dx -.25) (font-name "ISO-Times-Roman")
            (font-scaler .5) (gray-scale .25))))

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

picture

Changing Global Justification Decisions

Il faut indiquer aux procédures de justification quels objets ne doivent pas être écrasées et quel est l'espacement dont ils ont besoin autour d'eux. Les quatre boîtes entourant un tel objet sont la bounding box (x0 y0 to x1 y1 -- c'est là que l'objet sera tracé), ses "murs" ou "walls" (le minimum d'espace blanc que l'objet $$$can get by with$$$), "fences" (the amount of white space that makes the object look uncrowded), et des expandeurs ou "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. You can uses the messages fences, walls, and expanders to make local changes to the spacing decisions. For example, in an extract from the Mozart Clarinet Quintet, the repeat bar was not giving itself enough white space, so I used:

(begin-and-end-repeat-bar (fences '(.2 .3)))

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.

On peut localement changer l'emplacement des "walls" (murs) en passant un autre x et y en paramètre à la fonction walls :

    (c4 q
         (graphics (file "xx.eps") (dx 0.0) (dy -2.20))
         (walls '(0 2.0)))

Autre exemple pour mettre un peu d'espace entre l'armature et une altération en début de ligne:

   	bar line-mark
	(fs5 te (walls '(0.5 0.)) )(f5 te)(f5 te)


Hooks

  editor-hook
  filter-hook page-hook line-hook
  spacing-hook 

Ces astuces indiquent comment éditer les listes de données en cmn avant que la traduction se fasse. Line-hook, page-hook et spacing-hook sont aussi des score slots. Voir les exemples dans cmn-ex.lisp. editor-hook est appliqué au flux brut des données et peut servir à extraire ou transposer des parties, par exemple. filter-hook est appliqué au résultat final du processus de justification et peut être utilisé pour extraire une page d'une partition ou pour appliquer une fonction d'édition de finition. La fonction extract-part effectue l'extraction de parties en utilisant editor-hook. Elle prend le nom de la partie à extraire ou une fonction qui prend en compte le nom de la portée et retourne t si c'est la partie souhaitée :

  (cmn (extract-part "hi")
    (staff (staff-name "hi") treble c4 q)
    (staff (staff-name "ho") bass c4 q))

Pour transposer une partition, en tout ou en partie, voir /home/rbastian/CMN/cmn/transpose.lisp.


Examples

Il y a quelques exemples inclus dans le répertoire cmn : fux.cmn, moz.cmn, gus.cmn, carl.cmn, etc. cmn-ex.lisp contient quelques exemples. Les exemples de ce manuel sont dans cmnt.lisp. La variable *cmn-version* contient le numéro de version actuel (une date). Il y a un visualiseur pour le Mac : mettre "output-type" à :quickdraw comme cela

    (cmn (output-type :quickdraw) staff treble c4 q)

Sur SGI ou Linux, il y a un visualiseur nommé xcmnw -- il faut utiliser Motif pour le compiler et le charger; quand ceci est fait, la sortie à utiliser est :x.


Bogues connues et lacunes

Les sujets suivants sont sur ma liste de ceux qu'il faut traiter : cadences, aides de lecture, améliorer l'extraction des paties instrumentales, glyphes pour la musique ancienne, glyphes remplissables pour X et Quickdraw, une interface graphique complète.

NDT : pouvoir ménager de l'espace vide, petites notes sans appuis tie sur la dernière tête de note et non pas sur la première en cas de subdivision.

Bill Schottstaedt
bil@ccrma.stanford.edu

Glossaire

picture
picture

Index

a-majordetacheholdrmoveto
a-minordf-majorHorizontal rulerrotate
accentdiminuendoHouse stylerqq
accidentaldisplay-notesideal-stem-lengthscale
add-bassa-to-octave-signsdot-spacingimplicit-accidental-durationsection
add-notedots-leftimplicit-accidental-stylesegno
af-majordots-rightin-inchessf
af-minordotted-eighth-restin-parenthesessff
all-output-in-one-filedotted-half-restinitial-onsetsforzando
alla-brevedotted-quarter-restinterior-double-barsforzato
altodotted-sixteenth-restinverted-mordentsfp
always-show-clefsdotted-whole-restjustificationsfz
always-show-gliss-namedoubleJustificationsharp
always-show-staff-namesdouble-barkeyshort-trill
appoggiaturadouble-basslayoutshow
arpeggiodouble-flatleft-hand-pizzicatosign
arrowdouble-mordentleft-marginsign-position
arrowhead-updouble-sharplinesixteenth
articulationdouble-wholeline Layoutsixteenth-rest
as-minordouble-whole-restline-hooksixty-fourth
automatic-barsdown-bowline-marksixty-fourth-rest
automatic-beamsdrawline-separationsize
automatic-beat-subdivision-numbersds-minorline-widthslash-thickness
automatic-clef-sizedxlinetoslashed
automatic-line-breaksdx0little-swellslur-curvature
automatic-measure-numbersdx1marcatoslur-direction
automatic-naturalsdymarteleslur-thickness
automatic-octave-signsdy0matrixslurred
automatic-restsdy1maximum-beam-tiltslurs
automatic-tiesdynamicsmaximum-slur-slopesmall-flat
auxiliary-notedynamics-sizemaximum-subdivision-bracket-tiltsmall-natural
b-majore-majormeasure numberssmall-sharp
b-minore-minormeasure-restsnap-pizzicato
bareditor-hookmeasured-tremolosoprano
bar-expandersef-majormeterspacing-hook
bar-fencesef-minormetronomespp
bar-wallseighthmezzo-sopranostaccato
baritoneeighth-restmezzofortestaff
baritone-Cend-beammezzopianostaff-line-width
baritone-Fend-crescendomfstaff-lines
barline-thicknessend-diminuendomirrorstaff-name
bartok-pizzicatoend-first-endingmirroredstaff-name-font
bassend-glissandommstaff-name-font-minimum-size
beam-directionend-measured-tremolomordentstaff-name-font-scaler
beam-slope-triggerend-no-octave-signmovetostaff-separation
beam-spacingend-octave-downmpstaff-size
beam-widthend-octave-upmusic-fontstart-line
beamingend-portamentonaturalstem-direction
beamsend-repeat-barnatural-harmonicstem-down
Beat subdivisionend-second-endingno-beamstem-dy
begin-and-end-repeat-barend-slurno-beam-breakstem-up
begin-beamend-tieno-beat-subdivisionstem-width
begin-crescendoend-tremolono-octave-signstopped-note
begin-diminuendoend-two-octaves-downno-stemsub-bass
begin-first-endingend-two-octaves-upnotesundry
begin-glissandoendingsnote-headsundry-mark
begin-measured-tremoloeps filesnote-head-sizesystem
begin-no-octave-signexplicit-beamsnotessystem-separation
begin-octave-downfoctavetenor
begin-octave-upf-majoroctave transpositiontenor-treble
begin-portamentof-minoroctave-downtenuto
begin-repeat-barfermataoctave-sign-patternterminal
begin-second-endingffoctave-uptext
begin-slurfffone-line-per-pagetext-connecting-pattern
begin-tieffffone-twenty-eighthtext-connecting-thickness
begin-tremolofill-inone-twenty-eighth-restthickness
begin-two-octaves-downfilter-hookopen-notethirty-second
begin-two-octaves-upfingeringornamentsthirty-second-rest
bf-majorfirst-measure-numberother-notethumb
bf-minorflag-vertical-spacingoutlinedtie-curvature
braceflangesoutput-filetie-direction
brace-spaceflatoutput-typetie-thickness
bracketfooter-marginptied-to
breath-markfortepage-heightties
breathing-spacefortissimopage-hooktitle
brokenfortississimopage-marktitle-separation
c-majorforzandopage-widthtr
c-minorfpparanoid-tremolotransform
caesurafree-expansion-factorpartial-beam-lengthtreble
cclassfrench-violinpartial-stem-lengthtremolo
centerfs-majorpatterntrill
cf-majorfs-minorpausetrilled-turn
change-beatfull-barpedalturn
chordfull-double-barpedal-offtwo-octaves-down
circlefull-interior-double-barpercussiontwo-octaves-up
cleffull-last-linepianissimounjustified
CLM to CMNfzpianississimounmeasured-tremolo
cmng-majorpianounmetered
*cmn-output-pathname*g-minorpitchup-bow
*cmn-units*g.p.portamentoupside-down-fermata
codageneral-pauseportamento-touse-abbreviated-staff-names
colorgf-majorppuse-italian-octave-signs
common-timeglissandopppvertical-separation
connected textglissando-thicknessppppwavy-line
Coordinate Transformationsglissando-toprologwavy-time
crescendograce-notequarterwedge
cs-majorgrace-note-sizequarter-restwhole
cs-minorgrace-notesredundant-accidentalswhole-rest
curvetogrand-pauserehearsal markswith-cmn
curvy-flagsgraphicsrehearsal-letterwith-pattern
cut-timegray-scalerehearsal-numberwith-scaling
cyclegs-minorrepeat-measurewith-transformation
d-majorhalfrestwithin-measure
d-minorhalf-restrfzx0
dashedhead-quartersright-marginx1
dashed-barheader-marginrinforzandoy0
default-fontheightrlinetoy1