![]()
© 2002 Bruno Lartillot
Au démarrage de compo, vous obtenez une fenêtre de type console avec une invite (le caractère ? ou > ou autres) suivi d'un curseur affichant en écho chaque caractère tapé au clavier. Toutes les syntaxes décrites ci-dessous peuvent être saisies à ce niveau. L'expression est évaluée par compo dès que la touche entrée est frappée, avec l'effet de bord escompté (généralement la création d'un fichier midi ou postscript). Ceci est un moyen simple d'essayer Compo et de tester des expressions simples du langage. Mais ce mode de travail a deux limitations : Il ne permet pas de saisir des expressions volumineuses et il ne permet pas de conserver la saisie pour des sessions ultérieures.
L'utilisation normale consiste à créer un fichier texte pour chaque travail, en utilisant tout type d'éditeur de texte, et de charger de tels fichiers dans l'environnement de compo en saisissant :
(load nomdefichier)
Le format de nomdefichierdépend de votre système. Ce peut-être
quelque chose comme "/usr/dir/file" (Unix), "Principal:folder:file"
(Mac OS) ou "C:\dir\file" (Windows). De plus, selon votre
environnement Lisp, la fonction load peut être accessible
comme élément d'un menu, avec une boîte de dialogue permettant
de sélectionner de manière interactive le fichier à charger.
Compo est insensible à la casse. Par conséquent, chaque syntaxe ou exemple décrit ci-dessous peut être saisi aussi bien en majuscule qu'un minuscule. En d'autres termes :
(note :hei :d) <=>
(NOTE :HEI :D) <=>
(nOtE :HeI :d)
Au sein d'un fichier texte, des séparateurs (retours à la ligne, tabulations ou espaces) peuvent être insérés n'importe où, à condition qu'ils ne coupent pas un nom, un mot-clé ni un nombre. Ceci permet de structurer et d'indenter le texte d'une manière lisible. Par exemple :
(note :sync
(:soprano
(:c)(:d)(:e))
(:bass
(:c3)(:g2)(:c3)))
Il est possible de placer des commentaires au sein d'une oeuvre conséquente. Un commentaire est tout texte commençant par un point-virgule, jusqu'à la fin de la ligne courante. Par exemple :
; Cette nuit, j'ai rêvé que le destin frappait à
ma porte...
(note
(:8th
(:rest)(:g)(:g)(:g) (fermata :ef :h)) ; ...une
première fois...
(:8th
(:rest)(:f)(:f)(:f) (fermata :d :h))) ; ...puis
une seconde, avec insistance!
Notez que les commentaires ne sont visibles que depuis le fichier source, pour une meilleure compréhension, mais n'ont aucun effet sur le jeu midi ou l'impression de la partition.
Le terme note est compris dans compo dans un sens plus général que dans le langage musical courant. La musique peut généralement être décrite sous la forme de notes élémentaires ou atomes, et de structures hiérarchiques combinant de tels atomes. Dans compo, aussi bien les atomes que les structures sont appelés "notes" dans la mesure où, comme décrit plus loin, ils partagent un même ensemble de propriétés. La définition générale et récursive de la note est donc :
Une note est soit un atome (note élémentaire) ou toute structure de note (note conteneur).
La forme générale du constructeur de note est :
(type [nom] propriété* subspec*)
Les crochets indiquent que le nom est optionnel, et l'étoile indique que les propriétés ou les subspecs sont présents en nombre quelconque, y compris zéro.
Le type est un nom parmi une liste prédéfinie, déterminant
le comportement particulier de la note qu'il définit. Le type permet
de définir les paroles, armures, changements de mesure ou de clé,
groupes de notes... Chaque type disponible est décrit plus loin dans
la présente documentation de référence. Pour le moment,
notez simplement que le type le plus générique est note.
Un nom est une chaîne quelconque (comme "intro"). Selon le type de la note, le nom peut avoir divers usages décrits plus loin, lors de la description des types de notes. Par défaut, les noms définis au niveau élémentaire permettent de placer des annotations au-dessus de la portée :
(realize (score ("This is an annotation" :c)(:d)(:e)(:f)(:g)))

Et un nom placé à la racine définit le titre de l'oeuvre :
(realize (score "This is the title" (:c)(:d)(:e)(:f)(:g)))

Un nombre, ou une liste de nombres ou de chaînes de caractères permet d'indiquer doigtés et chiffrages d'accords :
(realize (score (:name 1 :c)(:name
2 :d)(:name 3 :e)))
=> 
(realize (score :chord (:name ("b7"
5 "#") :c)(:e)(:g)(:bf)))
=> 
Un subspec peut être une sous-note, une sous-note répétitive, une déclaration ou une référence comme décrits ci-après :
Une sous-note revêt la même forme que le constructeur de note, excepté que le type n'est pas requis :
([type] [name] property* subspec*)Si le type n'est pas indiqué, c'est le type note qui est utilisé par défaut.
Une expression de la forme n
*subnote signifiant que la sous-note spécifiée est répétée n fois. Par exemple :2*((:c)(:d)(:e)(:c))
Une expression de la forme name
=subnote qui lie simplement le nom spécifié à la sous-note définie. Un nom valide ne doit pas être un mot-clé (commençant par:), doit contenir au moins une lettre et ne doit contenir aucune occurence du caractère=.La liaison du nom à la sous-note reste valide jusqu'à la fin de la portée où apparaît la déclaration, les portées étant matérialisées dans compo par les paires de parenthèses. Dans l'exemple suivant, la validité du nom x est la section représentée par
...:
(note (:c) ((:d) x=((:c)(:d)(:e)) ...))
Un nom figurant seul. Chaque nom rencontré comme référence, est remplacé par la sous-note couramment associée à ce nom :
(note x=((:c)(:d)(:e)) x))<=>(note x=((:c)(:d)(:e)) ((:c)(:d)(:e))))Selon la règle précédente, les deux exemples suivants sont des expressions valides :
(note a=((:c)(:d)(:e)) a)
(note a=((:c)(:d)(:e)) (:f a))mais les deux exemples suivants ne le sont pas :
(note (a=((:c)(:d)(:e))) a)
(note (a=(:c a)))La définition de
ane figurant pas dans l'une des portées incluant la référence àadans le premier cas, et an'étant pas entièrement défini lorsque sa référence apparaît dans le second.Les références incluses à l'intérieur d'une déclaration ne sont pas résolues au moment du traitement de la déclaration, mais lorsque cette déclaration est elle-même référencée. Ceci permet les références en avant, comme ci-après :
(note x=(:f y) y=((:c)(:d)(:e)) x)<=>(note (:f ((:c)(:d)(:e)))Un nom déclaré doit être référencé au moins une fois pour avoir une incidence sur la réalisation. Par conséquent,
xn'a absolument aucun effet dans cette expression :
(note x=((:c)(:d)(:e)) (:f))Un nom peut être localement redéfini, ainsi dans l'expression :
(note a=((:c)(:d)(:e)) (a=((:f)(:g)(:a)) a) a)la première référence
ase réfère à((:f)(:g)(:a))tandis que la seconde se réfère à((:c)(:d)(:e)).
Une note gère cinq propriétés dites propriétés numériques : elles sont respectivement la hauteur, la durée, la position, la voix et la dynamique. Dans le cas d'une note élémentaire, les propriétés numériques servent à calculer les valeurs finales (paramètres midi ou de partition). Dans le cas d'un conteneur, les propriétés numériques jouent le rôle de modificateurs pour les propriétés numériques de ses sous-notes.
Ce processus de modification des notes par leurs conteneurs est récursif. La note racine modifie ses sous-notes, qui ensuite modifient leurs propres sous-notes etc. Notez que les objets notes ne sont pas effectivement modifiés. La portée de la modification est seulement le calcul de la séquence résultante (ce processus est appelé la réalisation dans la terminologie de compo).
La manière dont les propriétés numériques sont
modifiées est expliquée ci-dessous pour chaque propriété
numérique. Par convention, un terme super-nom-de-propriété
se réfère ˆ la valeur de la propriété nom-de-propriété
dans le conteneur immédiat d'une note. Considérons cet exemple
:
(note :d (:e))
Si nous considérons la note élémentaire (:e)
dans l'exemple ci-dessus, super-HEI représente la
valeur de hauteur de son conteneur direct, c'est à dire :d.
Partout où un mot-clé est autorisé comme valeur de propriété,
il peut figurer seul (c'est à dire non précédé par
le mot-clé d'un nom de propriété). Par example :REST
peut figurer seul dans une définition de note, et est une abréviation
de :HEI :REST.
(note :HEI value)
La propriété de hauteur d'une note est spécifiée
par le keyword :HEI suivi d'une valeur représentant la hauteur
en cents, C4 étant égal à 0.
En plus des nombres, certains mot-clés sont autorisés comme valeurs de hauteur. Le format est :
Par exemple : 400, :g, :e5 or :fff2
sont des valeurs de hauteur valides.
nil ou :rest comme valeur de hauteur définit
un silence.
La syntaxe anglo-saxonne est la syntaxe par défaut. Il est possible de changer la syntaxe au niveau général en saisissant :
(setf *default-syntax* :latin)
Et l'expression suivante a pour effet de revenir à la syntaxe anglo-saxonne :
(setf *default-syntax* :english)
Si un mot-clé est fourni comme valeur il est converti en cents selon un tempérament non égal par dŽfaut. Si vous souhaitez passer en tempérament égal, entrez simplement l'expression Lisp :
(setf *default-temperament* *equal-temperament*)
Et entrez cette expression pour revenir au tempérament non égal par défaut :
(setf *default-temperament* *compo-temperament*)
La raison pour laquelle compo utilise un tempérament spécifique
plutôt que de travailler en tempérament égal, est que cela
permet de conserver le différence entre ré# et mib par exemple,
distinction souvent utile, en particulier en musique tonale classique. A ce
niveau, cette utilisation des tempéraments musicaux n'influe que sur
la représentation interne des hauteurs de note, et non sur la restitution
audio. Il existe un autre moyen de spécifier le tempérament au
niveau de la restitution audio qui est décrit dans le cadre du type de
note midi.
HEI est modifié par la valeur de l'expression : (+
HEI super-HEI):
(note :d (:e)) <=> (note (:f))
HEI vaut 0 par défaut :
(note
:HEI :c4) <=> (note)
(note :DUR value)
La propriété de durée d'une note est spécifiée
par le mot-clé :DUR suivi par une représentation
proportionnelle de la durée, où 1 correspond à la noire,
1/2 à la croche, 4 à la ronde...
En plus des nombres, les mot-clés :DW (double ronde) :W
(ronde), :H (blanche), :Q (noire), :8th
(croche), :16th (double-croche), :32th (triple croche),
:64th (quadruple croche) (en syntaxe anglo-saxonne), :DR
(double ronde), :R (ronde), :B (blanche), :N
(noire), :C (croche), :DC (double-croche), :TC
(triple croche) and :QC (quadruple croche) (en syntaxe latine),
éventuellement avec un ou deux points sont autorisés comme durées.
DUR est modifié par la valeur de l'expression : (*
DUR super-DUR):
(note :h (:q.)) <=>
(note (:h.))
DUR vaut 1 par défaut :
(note
:DUR :q) <=> (note)
La conversion finale d'une durée en durée midi est obtenue en multipliant la valeur par 1000 et en arrondissant le résultat à l'entier le plus proche. Ainsi tout nombre correspond à une durée midi valide (exprimée en millisecondes).
(note :POS value)
La propriété de position d'une note est spécifiée
par le mot-clé :POS suivie par une représentation
proportionnelle de la position, homogène avec celle utilisée pour
les durées. La position est un décalage en réalité.
Son effet sur le positionnement de la note dépend de la propriété
form (cf. form).
La propriété de position n'accepte pas de mot-clés particuliers comme valeur.
POS est modifié par la valeur de l'expression : (*
POS super-DUR):
(note :h (:POS 3)) <=>
(note (:POS 6))
POS vaut 0 par défaut :
(note
:POS 0) <=> (note)
La conversion finale d'une position en durée midi est obtenue en multipliant la valeur par 1000 et en arrondissant le résultat à l'entier le plus proche. Ainsi tout nombre correspond à une position midi valide (exprimée en millisecondes).
La propriété form d'une note est spécifiée
par un mot-clé parmi :juxt, :chord or :sync.
Lorsque la valeur est :juxt, la position horizontale de chaque
sous-note est calculée de telle sorte que la sous-note est positionnée,
selon la valeur de POS, relativement à la fin de la sous-note
qui la précéde dans la liste des sous-notes :
(realize (score :juxt (:pos 1 :c4)(:pos
0 :e4)))

Lorsque la valeur est :chord, la position horizontale de chaque
sous-note élémentaire est affectée à la position
du conteneur, indépendamment de toute valeur de position au niveau des
sous-notes :
(realize (score :chord :pos 1 (:c4)(:e4)))

Lorsque la valeur est :sync, la position horizontale de chaque
sous-note directe est calculée de telle sorte que la sous-note est positionnée,
selon la valeur de POS, relativement à la position du conteneur.
La différence entre :sync et :chord et que
seules les sous-notes directes sont synchronisées dans le cas de :sync,
tandis que toutes les sous-notes à quelque niveau de profondeur, sont
synchronisées dans le cas de :chord. Concrètement,
:sync est adapté à la synchronisation de plusieurs
voix, tandis que :chord est adapté à la définition
d'accords ou agrégations au sein d'une voix. :sync doit
toujours être utilisé avec des sous-notes ayant des valeurs de
voix séparées (cf. voice) :
(realize (score :sync
(:treble
(:c)(:chord (:b3)(:d))(:chord (:c)(:e)))
(:bass
(:c3)(:g2)(:c3))))

form vaut :juxt par défaut :
(note :juxt) <=> (note)
(note :VOI value)
(note :VOICE-CLASS value)
Une note peut être reliée à une voix ou une classe de voix.
Généralement, on s'intéresse à la classe de voix,
qui est spécifiée par le mot-clé :VOICE-CLASS
suivi par un entier positif ou négatif.
En plus des entiers, les mot-clés :french-violin, :treble,
:soprano, :mezzo-soprano, :alto, :tenor,
:baritone, :bass, :sub-bass, :double-bass
et :percussion sont des classes de voix valide. Ces mot-clés
correspondent aux valeurs entières comprises entre -1 et 9, :treble
correspondant à la valeur neutre 0.
En réalité, les classes de voix représentent des ensembles
de 256 voix chacun. Les sous-notes d'une super note à laquelle une classe
de voix est attribuée, peuvent être affectées à une
voix, sous la forme d'un entier entre 0 et 255 précédé
du mot-clé :VOI. Cette hiérarchie à deux niveaux
est utile pour gérer des groupes de voix partageant un comportement commun
:
0 ou :treble correspond
au canal 1, 1 ou :soprano au canal 2... et 15
ou :french-violin au canal 16. Notons que :percussion
correspond au canal 10, ce qui est généralement conforme à
l'attente des synthétiseurs midi.score pour plus de
précision.L'exemple suivant illustre le but pratique de la classification des voix :
(realize
(score :sync :tied-voices (:treble :bass)
(:treble :sync
(:voi 0 (:c)(:d)(:e))
(:voi 1 (:c)(:b3)(:c)))
(:bass :sync
(:voi 0 :g3 :h.)
(:voi 1 (:c3)(:g2)(:c3)))))

VOICE-CLASS vaut 0 par défaut :
(note :treble) <=> (note)
(note :DYN value)
La propriété de dynamique, ou nuance, d'une note est spécifiée
par le mot-clé :DYN suivi de tout nombre entier représentant
la valeur de dynamique.En plus des entiers, les mot-clés :dynmp,
:dynp, :dynpp, :dynppp, :dynpppp,
:dynmf, :dynf, :dynff, :dynfff
et :dynffff sont des valeurs de dynamique valides. Les entiers
correspondant sont des multiples de 12, de -60 à 48, :dynmf
correspondant à 0. Les mot-clés :dynfz, :dynsf,
:dynsfz, :dynsff, :dynrfz et :dynfp
sont également des valeurs de dynamique valides. Ils correspondent respectivement
aux valeurs entières 2, 4, 6, 8 et 10.
:DYN est modifié par la valeur de l'expression : (+
DYN super-DYN):
(note :dynf (:dynff)) <=> (note
(:dynfff))
:DYN vaut 0 par défaut :
(note :dynmf) <=> (note)
La conversion finale d'une dynamique en une vélocité midi est obtenue en arrondissant la valeur en entier, puis en lui ajoutant 60, en sélectionnant le minimum entre ce résultat et 127 et enfin en sélectionnant le maximum entre ce résultat et 0. Ainsi, tout nombre correspond à une vélocité midi valide (entier entre 0 et 127).
La valeur donnée à toute propriété numérique
n'est pas nécessairement un nombre littéral ou un mot-clé
comme 20 ou :8th, ce peut etre un calcul de la forme
:
(operator operand1
operand2...operandn)
Où operator peut être tout opérateur arithmétique
comme +, -, * or /, et chaque
opérande peut lui-même et récursivement être une valeur.
La valeur finalement attribuée à la propriété est
le résultat de ce calcul. Par exemple, les deux valeurs (+ 20 (*
10 4)) et 60 sont équivalentes. Un exemple concret
de cette facilité est la représentation d'une note dont la durée
est la somme de deux durées élémentaires, comme :

Au lieu d'écrire quelque chose d'abscons du style (note :dur 9/2),
il est plus élégant d'écrire (note :dur (+ :w :8th)).
Pour une propriété donnée, les mot-clés autorisés comme opérande d'une valeur calculée sont les mêmes que ceux autorisés pour une valeur littérale.
(setf name note)
Cette facilité standard de Common Lisp d'affectation globale de variable
est utilisée par compo pour permettre des déclarations globales.
Les noms définis de cette manière peuvent être référencés.
(setf *a* (note (:c)(:d)(:e)))
(note *a*)
Le but est d'autoriser quasiment la même richesse que cmn, l'excellent imprimeur de partition de Bill Schottstaedt qui est utilisé de manière sous-jacente.
Les types de notes sont divisés en trois catégories :
Dans cette catégorie, on trouve les points d'orgue, les petites notes, les notes avec des signes d'articulation comme les staccatos ou les tenutos, ou des signes d'ornementation comme les trilles, mordants ou autres trémolos.
(fermata :suspens value)
Le type fermata accepte une propriété supplémentaire
:suspens qui est une durée, valant 0 par défaut.
Cette durée est additionnée à la durée normale de
la note, et donc retarde d'autant la note suivante, lors d'une réalisation
midi. Il n'a pas d'effet sur l'impression de partition :
(realize (score (:c)(:b3)(:c)(fermata :suspens :h :d)(:d)(:e)(:c)(fermata
:suspens :h :d)))
Le type grace-note permet de spécifier une ou plusieurs
petite notes précédant la note normale. Les petites notes doivent
être synchronisées avec la note réelle correspondante, en
utilisant la forme :chord :
(realize (score (:c)(:chord (grace-note :16th (:b3)(:c)(:d))(:c))(:e)(:c)))

Le type unslashed se comporte comme une petite note, si ce n'est
qu'il sonne comme une appogiature, c'est à dire qu'il commence au moment
prévu pour la note correspondante, la retardant d'autant. Il a la même
représentation qu'une petite note, sans la barre oblique :
(realize (score (:c)(:chord (unslashed :16th (:b3)(:c)(:d))(:c))(:e)(:c)))

Les types de notes d'articulation sont résumés ci-dessous :
(realize (score (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)))

Un type de note d'articulation peut être spécifié sur une note élémentaire, auquel cas, il s'applique seulement à cette note :
(realize (score (:c)(staccato :d)(:e))

Ou il peut être spécifié au niveau d'un conteneur, auquel cas, il est hérité par chaque note élémentaire du groupe :
(realize (score (:c)(staccato (:d)(:e)(:f))(:g)))

Les types d'ornements sont résumés ci-dessous :
(realize (score (mordent)(inverted-mordent)(double-mordent)(turn)
(short-trill)(trill)))

Toute ornement accepte une propriété supplémentaire :SIGN
pouvant être :flat, :natural, :sharp,
:small-flat, :small-natural et :small-sharp.
Par exemple :
(realize (score (turn :sign :small-flat)))

Un Trill accepte les deux propriétés :SIGN-POSITION
valant :right (par défaut) , :up ou :in-parentheses
et :WAVY-LINE valant nil (par défaut) ou t.
Par exemple :
(realize (score :free-expansion-factor 2 (trill :sign :small-flat
:sign-position :in-parentheses :wavy-line t :w)(:d)(:e)(:f)(:g)))

Les ornements représentent des notes élémentaires sur la partition, bien que pouvant être des conteneurs, auquel cas, les sous-notes sont prises en compte uniquement lors des réalisations midi. Ainsi, on peut spécifier chaque note d'un trille par exemple, tout en gardant la partition lisible :
(realize (score (trill (:32th (:d)(:c)(:d)(:c)(:d)(:c)(:b3
:h)))(:c)))

Sonne :

Dans le cas où aucune sous-note n'est spécifiée pour un ornement, un schéma par défaut est fourni pour chaque type. Voici les correspondances :
(realize (midi (mordent))) sonne comme :

(realize (midi (inverted-mordent))) sonne comme :

(realize (midi (double-mordent))) sonne comme :

(realize (midi (turn))) sonne comme :

(realize (midi (trill))) ou (realize (midi (short-trill)))
sonne comme :

(tremolo :density value :attenuation
value subnote1 subnote2)
Un trémolo doit comporter exactement deux sous-notes, chacune étant
soit une note élémentaire, ou un accord. La propriété
de densité détermine le nombre de répétitions du
couple de deux sous-notes. Plus grande est la densité, plus rapide est
chaque répétition, de telle sorte que la durée globale
d'un trémolo reste constante. La densité vaut 4 par défaut.
La propriété d'atténuation prend comme valeur un mot-clé
de dynamique permettant d'atténuer la vélocité midi lors
de l'exécution de trémolos denses. La valeur attribuée
au nom (:name) d'un trémolo est utilisée comme une
indication textuelle du trémolo sur la partition. Il vaut "trem."
par défaut :
(realize (score (tremolo "trem. 8" :density 8 :attenuation
:dynp
(:chord
(:c)(:e))
(:d))))

Un champ s'applique exclusivement pour l'étendue où il est défini, c'est à dire la paire de parenthèses qui l'englobe. Cette étendue peut recouvrir plusieurs portées de la partition. Si un champ b masque un autre champ a du même type, en apparaissant à l'intérieur de l'étendue de a, a est restauré à la fin de l'étendue de b. L'exemple suivant montre la correspondance entre l'étendue d'un changement de tonalité dans la définition compo, et ce qui en résulte dans la partition. Notons que le Sol Majeur initial est automatiquement réhabilité après la modulation en Fa Majeur, sans qu'il soit nécessaire d'expliciter cette réhabilitation :
(realize (score :key :g
(:sync
(:treble (:c)(:d)(:e))(:bass (:c)(:a3)(:g3)))
(key-change
:key :f :sync (:treble (:f)(:g)(:a))(:bass (:f3)(:bf3)(:a3)))
(:sync
(:treble (:b)(:c5))(:bass (:g3)(:c3)))))

(clef-change :clef value ...)
La propriété :clef accepte comme valeur :french-violin,
:treble, :tenor-treble, :soprano, :mezzo-soprano,
:alto, :tenor, :baritone, :baritone-F,
:bass, :sub-bass, :double-bass ou :percussion,
produisant le résultat suivant, dans le même ordre :

:clef vaut :treble par défaut.
(key-change :key value ...)
La propriété :key accepte comme valeur :C,
:CS, :DF, :D, :EF, :E,
:F, :FS, :GF, :G, :AF,
:A, :BF, :B ou :CF.
:key vaut :C par défaut.
Voir l'introduction sur les champs ci-dessus pour un exemple de changement d'armure.
(measure :time value ...)
La propriété :time détermine la mesure. Elle
accepte comme valeur :
:common-time (C) ou :cut-time
(C barré) ;(3 8) pour une mesure
à 3/8 ;nil, auquel cas le champ n'est pas mesuré.:time vaut :common-time par défaut.
(realize (score
(measure
:time 3 (:c5 :h.)(:b :h.))
(measure
:time :cut-time :h (:c5)(:g)(:a)(:g))
(measure
:time (3 8) :8th (:c5)(:b)(:c5)(:a)(:b)(:c5))))

(realize (score (measure :time nil (:c)(:d)(:e)(:f)(:g)(:a)(:b)(:c5))))

Normalement, compo détermine automatiquement où placer les barres de mesure, selon la mesure. Cependant, il est possible de placer explicitement des barres de mesure. Ceci est utile particulièrement dans le cas de partitions non mesurées, où les barres peuvent être utilisées comme des repères. Le fait de placer manuellement des barres n'affecte pas le décompte automatique des temps par compo.
(realize (score :time nil (:c)(:d)(:e)(:f)(:g)(bar)(:a)(:b)(:c5)))

(beam ...)
Un grupetto (beam) groupe, voix par voix, chaque sous-note de
durée inférieure à une noire. Dans la mesure où
cmn groupe automatiquement les notes selon les temps, il est rarement nécessaire
d'expliciter les grupettos. Cependant, le grupetto peut être utilisé
pour modifier le comportement par défaut. Par exemple, le regroupement
par défaut pour cette définition :
(realize (score :8th (:c)(:d)(:e)(:f)))
Est :

Si pour telle raison, on préfère avoir le regroupement de ré et mi, la solution est :
(realize (score :8th (:c)(beam (:d)(:e))(:f)))

(tie ...)
Les notes liées sont automatiquement gérées par compo. Normalement, il n'est pas nécessaire de les spécifier. Cependant, des notes liées peuvent être spécifiées manuellement dans certains cas limites.
(slur ...)
Une liaison dessine, voix par voix, une courbe reliant la première à la dernière de ses sous-notes :
(realize (score (slur :sync (:treble (:c)(:d)(:e))(:bass
(:c)(:g3)(:c)))))

Relevons la distribution automatique des liaisons entre chaque voix définie à l'intérieur de l'étendue de la liaison.
(arrow :direction value
...)
(arpeggio :direction value
...)
(no-arpeggio ...)
Une flèche est un signe graphique indiquant si un accord doit être
joué de bas en haut ou l'inverse. Les flèches ne s'appliquant
qu'aux accords, la forme par défaut est :chord dans ce cas.
La direction peut être :up or :down. arpeggio
et no-arpeggio sont des flèches spécialisées.
La direction n'a pas de sens dans le cas de no-arpeggio, l'objectif
étant de jouer toutes les notes simultanément.
(realize (score (arrow :direction :up (:c)(:e)(:g))
(arpeggio
:direction :down (:c)(:e)(:g))
(no-arpeggio
(:c)(:e)(:g))))

(glissando ...)
(portamento ...)
Voici un exemple simple et explicite :
(realize (score :free-expansion-factor 2 (glissando (:c)(:c5))(portamento
(:c)(:c5))))

(octave :8ves value ...)
La propriété :8ves détermine le nombre d'octaves
de transposition visuelle des notes. Il peut être 1, 2,
-1, -2 ou 0 et vaut 1 par défaut.
(realize (score
(octave :8ves
1 :c5 (:c)(:d)(:e)(:f))
(octave
:8ves 2 :c5 (:g)(:a)(:b)(:c5))
(octave
:8ves -1 :c3 (:c5)(:b)(:a)(:g))
(octave
:8ves -2 :c3 (:f)(:e)(:d)(:c))))

Lorsque des notes éloignées de la portée sont rencontrées, cmn gère automatiquement les transpositions d'octaves, ce qui est généralement très pratique :
(realize (score :c7 (:c)(:d)(:e)(:f)(:g)))

Mais si dans certains cas l'on souhaite obliger cmn à ne pas faire
de transposition d'octave, le type octave avec :8ves
à 0 doit être utilisé :
(realize (score (octave :8ves 0 :c7 (:c)(:d)(:e)(:f)(:g))))

(repeat ...)
Un champ repeat définit une section devant être reprise
une deuxième fois. Sur la partition, le champ est délimité
par un signe de début de répétition et un signe de fin
de répétition, et il est exécuté deux fois dans
le cas d'une exécution midi. Si le début de la section de reprise
est le début de la partition, le signe de début de répétition
n'est pas représenté.
(realize (score (repeat (:c)(:d)(:e)(:c))(repeat
(:e)(:f)(:g :h))))

(crescendo :amp
value ...)
(diminuendo :amp
value ...)
La propriété :amp représente l'amplitude
sous la forme d'un valeur de dynamique.
Comportement Midi :
Selon la valeur de dynamique effective au début du crescendo ou du diminuendo, et selon l'amplitude spécifiée, la valeur de dynamique de chaque note élémentaire incluse dans le champs est recalculée de manière à refléter une progression linéaire ascendante ou descendante.
Représentation sur la partition :
Un soufflet ouvert ou fermé, de même durée que le champ, est dessiné sous chaque portée incluse dans la définition.
(realize (score (crescendo (:c)(:d)(:e)(:f)(:g))))

(rehearsal-letter :frame
value)
(rehearsal-number :frame
value :reset value)
Les repaires littéraux ou numériques sont des évènements
élémentaires (sans sous-note), pouvant être placés
le long de la partition, et sont représentés au-dessus de celle-ci.
Le système incrémente automatiquement le numéro ou la lettre
pour le prochain repère. La propriété :frame
spécifie si l'indication doit être entourée ou non, et si
l'encadrement est un carré ou un cercle. Les valeurs sont :none,
:box ou :circle. La propriété :reset
détermine à quelle valeur le compteur doit être réinitialisé
le cas échéant.
(realize (score (rehearsal-number :frame
:box :reset 10)(:c)(:d)(:e)(:f)(:g)(:a)(:b)(:c5)(rehearsal-number)(:d5)))

(page-mark)
(line-mark)
line-mark force un saut de ligne, tandis que page-mark
force un saut de page. Les deux types sont des événements élémentaires,
pouvant être placé le long de la partition.
(realize (score (:c)(:d)(:e)(:f)(line-mark)(:g)(:a)(:b)(:c5)))

(controler :id
value :channel
value :neutral
value :min
value :max
value ...)
(level-controler ...)
(tone-controler ...)
(pitch-controler ...)
(pan-controler ...)
(fx-controler ...)
(fx2-controler ...)
Les contrôleurs permettent de définir des champs à l'intérieur
desquels chaque variation de dynamique contrôle le niveau d'un contrôleur
midi. :id et :channel sont respectivement le numéro
de contrôleur et le canal midi. Attention au fait que les canaux midi
ont des valeurs entre 0 et 15 dans compo, et non entre 1 et 16. Si :chan
vaut nil (valeur par défaut), le message de contrôle midi est dirigé
vers le même canal que les notes associées, ceci est le comportement
généralement attendu. Le cas de figure typique où le message
de contrôle midi devrait être envoyé à un autre canal,
est celui où l'on souhaite contrôler une table de mixage à
laquelle le synthétiseur est connecté. :min et :max
devraient être positionnés respectivement aux valeur minimum et
maximum pour ce contrôleur midi. :neutral est la valeur à
laquelle le contrôleur doit être rétabli lorsque le champ
de contrôleur se termine. Il correspond généralement à
la valeur initiale de ce contrôleur midi.
Six contrôleurs spécialisés sont prédéfinis.
Ils correspondent aux six manières courantes de contrôler le son
: level-controler contrôle le niveau d'amplitude, tone-controler
contrôle les paramètres de timbre comme la fréquence des
filtres, leur résonnance, l'amplitude où la fréquence d'un
LFO..., pitch-controler contrôle la molette d'ajustement
microtonal, pan-controler la diffusion panoramique, fx-controler
et fx2-controler peuvent être affectés à des
commandes auxiliaires contrôlant le niveau d'effets tels que réverbération
ou égalisation.
A l'exception du contrôle microtonal qui correspond au message midi
standard de pitch bend, chaque contrôleur spécialisé
doit être adapté selon la charte midi de votre synthétiseur.
Par exemple, si votre séquenceur attribue le numéro de contrôleur
7 au contrôle de gain, vous devriez avoir les réglages suivants
dans votre fichier cminit.lisp :
(setf *level-controler-id* 7)
(setf *level-controler-chan* nil)
(setf *level-controler-neutral* 77)
(setf *level-controler-min* 0)
(setf *level-controler-max* 127)
Le même principe s'applique pour chaque contrôleur spécialisé.
(time-var :name
value :dur value
...)
Une variation de tempo permet d'utiliser la propriété numérique
de durée (:dur) pour contrôler une accélération
ou un ralentissement du tempo, sans affecter la représentation des durées
dans la partition. En pratique, la valeur de durée spécifiée
au niveau du champ time-var modifie, au sens défini plus
haut (cf. durée), les durées des sous-notes
dans le cas d'une exécution midi, mais non dans le cas d'une impression
de partition. Toute valeur donnée à la propriété
:name d'un champ time-var est rapportée au-dessus
de chaque portée. En plus de chaînes de caractères simples,
une liste constituée d'un mot-clé de durée et d'un nombre
permet de spécifier une valeur de tempo, et une liste de deux mot-clés
de durée spécifie un changement de tempo par équivalence
d'unités de durée.
(realize (score (time-var :name (:q 120) (:c)(:d)(:e)(:f))
(time-var
:name (:h :q) :8th (:h (:g)(:a)(:b)(:c5)))))
(legato ...)
Un champ de legato est destiné à être utilisé avec un synthétiseur midi monophonique. Avec ce type d'instrument, si une note débute tandis que la précédente n'est pas terminée, la seconde prolonge la première au sein de la même enveloppe d'amplitude. Selon ce principe, tout grupetto, liaison, glissando ou portamento défini à l'intérieur de la portée d'un legato est "midi-réalisé" de manière particulière : la durée de chaque note interne au grupetto, liaison, glissando ou portamento est augmentée afin de recouvrir partiellement la note suivante. Bien-sûr, cette augmentation n'est pas appliquée dans le cas d'une impression de partition.
(realize (midi (legato (:c)(beam (:d)(:e))))) => entendre
(beam-begin :sym value ...)(beam-end :sym
value ...)
(slur-begin :sym
value ...)(slur-end :sym
value ...)
La description des structures musicales dans compo est normalement hiérarchique. Mais dans certains cas, on est amené à déclarer les structures de manière non hiérarchique. Considérons l'exemple suivant :

Le problème est que ni le groupe de liaison, ni le grupetto n'est hiérarchiquement inclus à l'intérieur de l'autre. Par conséquent, il ne peuvent être décrits hiérarchiquement. La solution consiste à utiliser des évènements indiquant le début et la fin de chaque groupe, avec un symbole rendant possible la correspondance entre un début et sa fin correspondante. Voici la définition compo de l'exemple ci-dessus :
(realize
(score :8th
(slur-begin :sym a)(:c :h)(beam-begin :sym b)(:d)(:e)
(slur-end :sym a)(:f)(:g)(beam-end :sym b)(:a)))
(lyrics ...)
Une note de type lyrics représente une section où
les notes élémentaires définissent des paroles devant être
inscrites sous les portées, et non des notes dessinées sur les
portées. Le texte à inscrire est la chaîne fournie comme
nom à chaque note élémentaire. Ce texte figure sous la
portée correspondant à la même voix que la voix où
est définie la note "lyrics", et à la même
position que cette note, à condition qu'il existe une note réelle
à la même voix et à la même position. Par exemple,
dans :
(note :sync
(lyrics :sync
(:soprano ("Oooh")("Aaah"))
(:tenor ("Iiih")))
(:soprano (:d)))
"Oooh" est inscrit sous le ré au soprano, mais "Aaah", figurant à une position où aucune note réelle n'est présente au soprano, est ignoré, tandis que "Iiih" est ignoré pour motif qu'il n'y a pas de note réelle à la voix de ténor.
Il est possible de superposer deux strophes (au maximum) sous une même
portée, en utilisant la propriété :line, affectée
du numéro de ligne. :line vaut 1 par défault.
(realize (score :free-expansion-factor 2 :sync
(lyrics
("Au")("clair")("de")("la")("lu-"
:h)("-ne" :h))
(lyrics
:line 2 ("Pre-")("-te")("moi")("ta")("plu-"
:h)("-me" :h))
((:c)(:c)(:c)(:d)(:e
:h)(:d :h))))

Conformément au style de compo, il est possible d'inscrire les mêmes paroles sous deux voix distinctes, tout en n'écrivant ces paroles qu'une seule fois.
(realize (score :free-expansion-factor 2 :sync
stanza=(("Au")("clair")("de")("la")("lu-"
:h)("-ne" :h))
(lyrics
:soprano stanza)
(:soprano
(:c)(:c)(:c)(:d)(:e :h)(:d :h))
(lyrics
:bass stanza)
(:bass
(:c)(:g3)(:e3)(:f3)(:g3 :h)(:g2 :h))))

(mute ...)
Toutes les notes définies dans la portée d'un champ mute
ne sont pas exécutées au cours d'une "midi-réalisation".
Cependant, tout événement de contrôle midi dû à
des variations de dynamiques, au sein d'un champ de contrôleur (cf. contrôleur)
est effectivement généré. En pratique, le champ mute
est utile pour définir des voix particulières, servant uniquement
à la modulation de contrôleurs midi, sans jouer de notes réelles.
Par exemple, un moyen simple de défnir une progression panoramique de
gauche à droite peut être (les valeurs d'id et de canal de l'objet
pan-controler correspondant à mon synthétiseur) :
(realize (midi (pan-controler :id 28
:channel 15 (crescendo :dyn -64 :amp 128 (:c)(:d)(:e)))))
Le problème est que chaque variation de dynamique (le crescendo dans
ce cas) s'applique toujours aux vélocités midi. Par conséquent,
la progression panoramique est parasitée par un crescendo de dynamique
non souhaité. La solution est de d'inclure le champ pan-controler
et son crescendo au sein d'une voix muette, synchronisée avec notre voix
réelle :
(realize (midi :sync
((:c)(:d)(:e))
(mute (pan-controler
:voi 1 :id 28 :channel 15 (crescendo :dyn -64 :amp 128 (:h.))))))
=> entendre
Généralement, il est préférable de séparer les sections de contrôleurs en les intégrant dans de telles voix muettes, plutôt que de les mélanger avec des notes, de manière à éviter qu'ils n'interfèrent sur les vélocités de notes.
(score :key value
:time
value
:anacrusis
value
:voice-order
value
:tied-voices
value
:system-disp
value
:output-type
value
:output-file
value
:size
value
:transposers
value
:automatic-line-breaks
value
:automatic-beat-subdivision-numbers
value
:automatic-measure-numbers
value
:curvy-flags
value
:always-show-staff-names
value
:all-output-in-one-file
value
:page-height
value
:page-width
value
:left-margin
value
:right-margin
value
:header-margin
value
:footer-margin
value
:line-separation
value
:staff-separation value
:system-separation
value
:free-expansion-factor
value ...)
Une expression score doit nécessairement figurer à
la racine. En d'autres termes, l'expression (note (score)) est
illégale.
De même que pour les changements d'armure, la propriété
:key peut valoir :C, :CS, :DF,
:D, :EF, :E, :F, :FS,
:GF, :G, :G, :AF, :A,:BF,
:B et :CF. Elle vaut :C par défaut.
De même que pour measure, la propriété :time
détermine la mesure. Elle peut être :
:common-time (C) ou :cut-time
(C barré) ;(3 8) pour une mesure
à 3/8 ;nil, auquel cas le champ n'est pas mesuré.:time vaut :common-time par défaut.
La propriété :anacrusis détermine la position
à laquelle débute la partition. Elle permet de faire débuter
une oeuvre avec une mesure incomplète. Par exemple : (score :anacrusis
3 (:c)(:d)(:e)) imprime une partition commençant avec une première
mesure ne comportant qu'un seul temps. :anacrusis vaut 0 par défaut.
La propriété :voice-order permet de changer l'ordre
par défaut de la présentation des voix, de haut en bas (cf. VOIce).
(realize (score :voice-order (:bass :treble) :sync
(:treble (:c)(:d)(:e))
(:bass (:c)(:g3)(:c))))

La propriété :tied-voices gère la liste des
classes de voix pour lesquelles toutes les voix doivent être imprimées
sur la même portée. Dans l'exemple suivant, conformément
à la valeur donnée à :tied-voices, seules
les voix :treble sont regroupées sur la même portée,
tandis que les voix de basse ne le sont pas :
(realize
(score :sync :tied-voices (:treble)
(:treble :sync
(:voi 0 (:c)(:d)(:e))
(:voi 1 (:c)(:b3)(:c)))
(:bass :sync
(:voi 0 :g3 :h.)
(:voi 1 (:c3)(:g2)(:c3)))))

Par défault, aucune classe de voix n'est regroupée.
La propriété :system-disp détermine la dispostion
globale du système. Elle accepte un élément ou une liste
:
:brace ou :bracket,
auquel cas, le système global est regroupé par une accolade
ou un crochet respectivement ;() (la liste vide), compo détermine lui-même
s'il doit représenter une accolade, un crochet ou rien. Un système
ne comportant qu'une portée n'aura pas de signe de regroupement. Un
système ayant exactement deux portées aura une accolade, sinon
il aura un crochet ;() si aucun nom de portée n'est requis ; :brace or :bracket, et suivie d'une
liste de chaînes de caractères, ou de listes vides.
(realize (score :voice-order (:baritone :treble :bass)
:system-disp ((:bracket "Me" "You" "Him") (:brace ()()))
:w :sync
(:baritone :sync (:bf3)(:voi 1 :g3)(:voi 2 :c3))
(:treble
:e)
(:bass
:c3)))

La propriété :output-type détermine le type
de formatage. Elle accepte :postscript, :quickdraw
(pour Macintosh, nécessite MCL), or :x (pour Unix, nécessite
xcmnw and motif). Avec :postscript, la partition est générée
sous la forme d'un fichier postscript. Avec :quickdraw ou :x,
la partition est pré-visualisée. :output-type prend
par défaut la valeur courante de la variable cmn::*cmn-output-type*.
La propriété :output-file permet de changer l'emplacement
et le nom du fichier postscript produit. Elle prend par défaut la valeur
de la variable *default-output-file*. Elle accepte tout pathname
Lisp.
La propriété :size fixe la taille proportionnelle
de la partition. Elle prend par défaut la valeur courante de la variable
*default-size*.
La propriété :transposers permet de spécifier
les classes de voix correspondant à des instruments transpositeurs. Ceci
est utile pour les instruments comme la trompette par exemple, qui transpose
en ré, c'est à dire pour laquelle un ré est écrit
do sur la partition. La valeur doit être une liste de transpositeurs,
chacun étant un couple de la forme (voice-class
. height).
(realize (score :transposers ((:treble . :D)) (:c)(:d)(:e)))

Les propriétés suivantes correspondent aux options disponibles dans cmn. La description est tirée de la documentation de référence de cmn (les valeurs entre parenthèse correspondent aux valeurs par défaut) :
:automatic-line-breaks (t) les sauts de ligne doivent-ils être
inclus par cmn
:automatic-beat-subdivision-numbers (t) les sous-divisions irrégulières
doivent-elles être signalées par cmn
:automatic-measure-numbers (nil) peut être t = 1, un nombre,
:by-line, ou :by-page
:curvy-flags (t) Bannières courbes ou droites
:always-show-staff-names (t) Les portées doivent-elles
être nommées au-delà dela première
:all-output-in-one-file (nil) insère les sauts de page
dans le fichier en sortie (plutôt que de générer des fichiers
séparés)
:page-height (11.0 inches) (29.7 cm) -- cm si cmn::*cmn-units*
= :cm
:page-width (8.5 inches) (21.0 cm)
:left-margin (0.5 inches) (1.0 cm)
:right-margin (0.5 inches) (1.0 cm)
:header-margin (1.0 inches) (2.0 cm)
:footer-margin (1.0 inches) (2.0 cm)
:line-separation (2.0 inches) espace blanc entre deux lignes de
musique
:staff-separation (1.5 inches) espace blanc entre deux portées
:system-separation (1.5 inches) espace blanc entre deux systèmes
:free-expansion-factor (1.25 inches) espace blanc ajouté
pour la justification
(cleaves ((voice-class1 . value1)(voice-class2
. value2) ...))
Change les clés associées à la liste de classe de voix
spécifiées.
Chaque classe de voix peut être toute valeur de classe de voix telle que défini dans VOIx et classe de voix.
Chaque classe de voix qui n'est pas présente dans la liste, est associée par défaut à la clé du même nom.
Un tel assignement global de clé remplace tout assignement de clé précédent aux mêmes voix et reste valide jusqu'au prochain assignement de clé.
Exemple:
(cleaves ((:treble . :soprano)))
(realize (score ((:c)(:d)(:e))))

(midi :midi-file
value :tempo value
...)
Une expression midi doit nécessairement figurer à
la racine. En d'autres termes, l'expression (note (midi)) est illégale.
La propriété :midi-file permet de changer l'emplacement
et le nom du fichier midi produit. Elle prend par défaut la valeur de
la variable *default-midi-file*. Elle accepte tout pathname
Lisp.
La propriété :tempo définit le nombre de
noires par minute. Elle vaut 60 par défaut.
(program-change voice-class
[program])
Change le programme midi (instrument de musique) associé à la classe de voix spécifiée.
La classe de voix est tout nombre entier ou mot-clé autorisé
comme valeur pour la propriété :voice-class.
Le programme doit être l'un des mot-clés ci-dessous (correspondant à la liste normalisée General Sound) :
:acoustic-grand-piano :bright-acoustic-piano
:electric-grand-piano :honky-tonk :electric-piano-1 :electric-piano-2 :harpsichord
:clavicord
:celesta :glockenspiel :music-box
:vibraphone :marimba :xylophone :tubular-bells :dulcimmer
:drawbar-organ :percussive-organ :rock-organ
:church-organ :reel-organ :accordian :harmonica :tango-accordian
:nylon-acoustic-guitar :steel-acoustic-guitar
:jazz-electric-guitar :clean-electric-guitar :muted-electric-guitar :overdriven-guitar
:distortion-guitar :guitar-harmonics
:acoustic-bass :finger-electric-bass
:pick-electric-bass :fretless-bass :slap-bass-1 :slap-bass-2 :synth-bass-1 :synth-bass-2
:violin :viola :cello :contrabass
:tremolo-strings :pizzicato-strings :orchestral-strings :timpani
:string-ensemble-1 :string-ensemble-2
:synth-strings-1 :synth-strings-2 :choir-aahs :voice-oohs :synth-voice :orchestra-hit
:trumpet :trombone :tuba :muted-trompet
:french-horn :brass-section :synth-brass-1 :synth-brass-2
:soprano-sax :alto-sax :tenor-sax
:baritone-sax :oboe :english-horn :bassoon :clarinet
:piccolo :flute :recorder :pan-flute
:blown-bottle :shakuhachi :whistle :ocarina
:square-lead :sawtooth-lead :calliope-lead
:chiff-lead :charang-lead :voice-lead :fifths-lead :bass+lead
:new-age-pad :warm-pad :polysynth-pad
:choir-pad :bowed-pad :metallic-pad :halo-pad :sweep-pad
:rain :soundtrack :crystal :atmosphere
:brightness :goblins :echoes :sci-fi
:sitar :banjo :shamisen :koto :kalimba
:bagpipe :fiddle :shanai
:tingle-bell :agogo :steel-drums :woodblock
:taiko-drum :melodic-tom :synth-drum :reverse-cymbal
:guitar-fret-noise :breath-noise :seashore
:bird-tweet :telephone-ring :helicopter :applause :gunshot
Si program n'est pas spécifié, l'utilisateur est
invité à choisir de manière interactive une valeur dans
cette liste.
(init-programs)
Réinitialise tous les canaux midi à 0 (acoustic grand piano).
(test-programs)
Envoie une note midi à chaque canal afin d'activer les changements de programme.
(note :COERCER value)
L'interface de coercition de compo est un outil très puissant, dont la compréhension n'est pas absolument nécessaire pour démarrer avec compo. L'utilisation de cette interface nécessite une connaissance des spécificateurs de type de Common Lisp. Veuillez vous référer à toute documentation sur Common Lisp (comme Common Lisp, the Language - Steele) si vous n'êtes pas déjà familier avec les spécificateurs de type.
Le coerciteur associé à une note est spécifié par
le mot-clé :COERCER suivi par un spécificateur de
type Common Lisp. Seules les sous-notes se conformant au final à ce spécificateur
de type sont conservées dans le résultat. "Au final"
signifie que la coercition est appliquée à l'ensemble résultat
des sous-notes, après tout autre calcul comme les transformations de
propriétés numériques et le positionnement des notes....
Prenons cet exemple :
(realize (score (:c)(:d)(fermata :e)))

Maintenant, avec un coerciteur ne sélectionnant que les sous-notes de
type fermata :
(realize (score :coercer fermata (:c)(:d)(fermata
:e)))

Un coerciteur plus utile est le spécificateur de type note-type.
Sa forme est :
(note-type type [:hei typespec] [:dur typespec]
[:pos typespec] [:voi typespec] [:dyn typespec])
Spécifier le premier paramètre type d'un coerciteur note-type
nécessite d'avoir une connaissance du modèle de classe de compo,
ce qui dépasse le cadre de cette documentation utilisateur. Pour le moment,
admettons que la valeur t (valeur vrai en Lisp) suffit à
le neutraliser, et considérons les autres paramètres. Les crochets
indiquent que chaque spécificateur de type associé à une
propriété numérique est optionnel. Si le spécificateur
de type n'est pas spécifié pour une propriété donnée,
aucun filtre ne s'applique en fonction de la valeur de cette propriété.
En d'autres termes :
:coercer (note-type t :hei t)
<=> :coercer (note-type
t) <=> :coercer
t
note-type permet de spécifier des filtres selon les valeurs
des propriétés numériques, de tels filtres s'appliquant
à l'ensemble résultat des sous-notes. Par exemple, (note-type
t :pos (integer 2 4))est un filtre sur les positions tel que seules les
sous-notes dont la position est une valeur entière comprise entre 2 et
4 inclus, sont conservées dans le résultat.
(realize (score (:c)(:d)(:e)(:f
:8th)(:g :8th)(:a)))

Filtré de cette manière :
(realize (score :coercer (note-type
t :pos (integer 2 4))
(:c)(:d)(:e)(:f
:8th)(:g :8th)(:a)))

Tout mot-clé de propriété est accepté dans un spécificateur de type, et est remplacé par sa valeur numérique :
:coercer (note-type t :dur (rational
:q :w)) <=> :coercer
(note-type t :dur (rational 1 4))
Les coerciteurs décrits ci-dessus sont des filtres. Plus généralement,
les coerciteurs peuvent modifier les sous-notes plutôt que les filtrer.
Compo fournit quelques coerciteurs de ce genre : les temperaments, mode
et shuffle.
Les tempéraments disponibles sont eq-temp (tempérament
égal), py-temp (tempérament pythagoricien), zar-temp
(tempérament zarlinien) et bali-temp (tempérament
balinais). Ils sont destinés à être utilisés en mode
d'exécution midi, avec le type de note midi. Notons qu'une
structure de note de type midi a comme coerciteur par défaut
eq-temp, et non t. Ceci garantit qu'une exécution
midi jouera la note selon un tempérament égal par défaut,
ce qui est de nos jours le résultat normalement attendu par une oreille
occidentale. Attention au fait que si l'on spécifie un coerciteur au
niveau d'une structure midi, cela annule le coerciteur eq-temp
par défaut. Par conséquent, afin de conserver le comportement
de tempérament par défaut, tout coerciteur n'étant pas
lui-même un tempérament, devant être affecté au niveau
d'une structure midi, devrait en principe être combiné
avec eq-temp de cette manière :
(realize (midi :coercer (and eq-temp other-coercer) ...))
Le coerciteur déplace les hauteurs de
chaque sous-notes vers le degré le plus proche d'un mode fourni en paramètre.
Toute mélodie en mode Majeur par exemple :mode
(realize (score (:c5)(:d5)(:e5)(:c5)(:d5)(:b)(:c5)(:g)))

Peut facilement être minorisée ainsi :
(realize (score :coercer (mode :c :d :ef :f :g :af :b)
(:c5)(:d5)(:e5)(:c5)(:d5)(:b)(:c5)(:g)))

Le coerciteur shuffle décale, selon une valeur de delta,
la position des subnotes qui ne tombent pas sur un temps (beat). Le beat
et le delta sont donnés en paramètres. Ainsi, toute mélodie
écrite selon un rythme binaire :
(realize (score (:8th (:d5)(:c5)(:d5))(:c5)(:d5
:8th)))

Peut aisément être ternarisée :
(realize (score :coercer (shuffle 1 1/6)
(:8th (:d5)(:c5)(:d5))(:c5)(:d5 :8th)))

Concrètement, l'usage pratique de shuffle est de l'appliquer
à l'exécution midi et non à l'impression de partition.
L'exemple ci-dessus pourrait être géré de cette manière
:
La structure musicale est définie dans un premier temps, avec une mention jazzy, indiquant qu'elle doit être interprétée en ternaire :
(setf *example* (note (:8th ("Swing"
:d5)(:c5)(:d5))(:c5)(:d5 :8th)))
L'expression d'impression de partition se réfère simplement à cette structure "abstraite" :
(realize (score *example*))

Tandis que l'exécution midi la ternarise :
(realize (midi :coercer (shuffle 1 1/6) *example*)) => entendre
Naturellement, les coerciteurs ne sont pas nécessairement appliqués à la racine. C'est même leur principal intérêt d'être utilisable localement.
Compo définit une interface de programmation (API) permettant, parmi d'autres extensions, de définir de nouveaux coerciteurs. La description de cette API déborde le cadre de cette référence utilisateur. Veuillez vous référer à la référence de l'API compo (en cours de rédaction) pour plus de détail sur les coerciteurs.
(compo-help)
Cette fonction décrit la grammaire du langage compo.
Le fichier compo/src/localization.lisp contient la liste de tous
les messages textuels utilisés par le système. N'hésitez
pas à modifier les textes (seulement les textes, pas les nomsde variables)
afin de les traduire dans votre langue naturelle. Il suffit ensuite de redémarrer
compo. Dès lors, vos modifications sont prises en compte par le système.