Thèse de doctorat
en
Intelligence Artificielle
[arrêté du 30 mars 1992]
Présentée par :
Vincent LESBROS
Sujet de la thèse :
Atelier Incrémentiel pour la
Musique Expérimentale
Directeur de thèse :
M. Harald WERTZ
Université Paris 8
Département Informatique
Laboratoire d’Intelligence Artificielle
Soutenue le 24 Octobre 1995
devant le jury composé de :
M.M. Patrick GREUSSAY Président
Daniel ARFIB Rapporteur
Claude CADOZ Rapporteur
Giuseppe G. ENGLERT
Curtis ROADS
Harald WERTZ
Remerciements
Je souhaite remercier ici tous ceux qui au cours de ce travail m'ont apporté leur précieuse aide.
Depuis mon arrivée à l'université, Giuseppe G. ENGLERT a guidé mes pas dans le monde de la musique expérimentale, en m'accueillant dans l'équipe du GAIV, m'initiant tant à la programmation qu'à la composition et me permettant de concrétiser, par de nombreux concerts, les rêves qui me hantaient. Notre travail d'équipe s'est transformé progressivement en étroite collaboration, voire en travail de concert sur des oeuvres communes. Je ne peux mesurer l'étendue de ma reconnaissance envers lui.
Harald WERTZ, Daniel GOOSSENS et Patrick GREUSSAY m'ont ouvert les yeux sur l'intelligence artificielle, et lancé sur les chemins de la recherche. Je les remercie pour les bagages qu'ils m'ont fourni, dans lesquels je puise les ressources me permettant d'affronter ces sentes escarpées, et ces parois rocheuses. Je leur dois la vue sur ce paysage magnifique.
Je remercie les membres du GAIV (Groupe Art & Informatique de Vincennes à St DENIS), son fondateur retraité Patrick GREUSSAY, Giuseppe G. ENGLERT, feu Gilbert DALMASSO, Marc BATTIER, Lirio MARTINEZ, Guillaume BILLAUX, Alawa BOUABDALLAH, Max HEDIGUER et Jean HOLLEVILLE. Que Marcel PROVOST soit remercié également pour sa bienveillance discrète et efficace envers cette équipe.
Je remercie Claude CADOZ et Daniel ARFIB de participer au jury et d'avoir accepté d'être les rapporteurs de cette thèse.
Je remercie Curtis ROADS, pour l'interêt qu'il a manifesté à l'égard de mes travaux ainsi que pour sa participation au jury.
Je remercie Daniel GOOSSENS, grâce à qui l'idée de phonogramme a pu prendre naissance, pour tous ses conseils, suggestions et remarques avisés.
Je remercie Marc BATTIER, Giuseppe ENGLERT et Pierre MARIETAN d'avoir contribué au développement de notre atelier au travers d'expériences, parfois émaillées d'erreurs...
Je remercie les enfants qui ont dessiné des phonogrammes, Corentin, Solène, et Fanny.
Que cette phrase soit une formule arborescente de remerciements pour Claude LENORMAND et Pierre AUDIBERT.
Mon goût pour la musique expérimentale a été renforcé grâce à Horacio VAGGIONE, Marc BATTIER, André RIOTTE, Joel CHADABE, Pierre MARIETAN.
Je remercie les membres du Laboratoire d'Intelligence Artificielle de Paris 8, Patrick GREUSSAY, Harald WERTZ, Françoise BALMAS, Damien PLOIX, Thierry DELAMARE, Sophie DELAMARE, ALI CHERIF, Jean MEHAT, Renaud DUMEUR pour les nombreuses discussions qui ont contribué à l’achèvement de cette étude.
Je remercie Thierry DELAMARE, Marie Solange TOUZEAU et Maurice AMSELLEM grâce à qui le GAIV peut communiquer.
Ce message à pour objet tous mes remerciements et pour récepteurs Philippe KRIEF et François PACHET.
Je remercie mes patients relecteurs et parents.
Notre travail, portant sur le domaine de la composition dans la musique expérimentale, a abouti à la création d'un atelier informatique propice au développement de trois grandes catégories d'applications : les éditeurs de représentations graphiques de pièces musicales et de sons pour la composition, la synthèse et l'analyse des sons, ainsi que le pilotage de synthétiseurs en temps réel; les applications pour la musique algorithmique en temps réel, et enfin les applications pour la musique algorithmique interprétée par des instrumentistes.
Nous présenterons d’abord notre système de représentation graphique des sons : les phonogrammes., ainsi que les principes et les techniques développées pour la représentation graphique de formes musicales et de sons, tels les trajectoires de mobiles virtuels.
Nous montrerons également l'utilisation d’un système s’apparentant au modèle physique des couplages élastiques dans les modules graphiques, dans les procédés d'analyse et de synthèse du son, et même dans les algorithmes compositionnels. Ceci débouchera sur l'exposé de nos systèmes de synthèse et d'analyse induits par ces représentations graphiques.
Ensuite nous exposerons le module Métronome, cœur des applications de génération en temps réel. Ce noyau est utilisé par des étudiants en musicologie, pour développer des applications musicales expérimentales variées. Nous l'avons également utilisé pour la réalisation de systèmes générateurs de formes musicales réagissant à des stimuli musicaux externes : modes, harmonie, mélodie, rythmes. Le résultat principal de ce module est un séquenceur algorithmique interactif. Des algorithmes de génération mélodique seront présentés, en particulier l'algorithme de composition de la partie de contrebasse d'une pièce mixte : Méduse pour contrebasse et phonogramme.
Nous examinerons enfin le module de génération automatique de partitions, utilisé en particulier pour la composition d’une pièce pour orchestre et piano concertant.
Nous pensons que le processus de composition de musique par ordinateur nécessite une connaissance simultanée des domaines musical et informatique, et qu'aucun système ne fournira la possibilité ni à un musicien non informaticien d'exploiter toutes les possibilités que peuvent offrir les machines dans ce domaine, ni à un informaticien non musicien de faire de la musique. Aboutissant toutefois d'une part à des outils purement informatiques et d'autre part à des applications utilisables par des compositeurs, nous préférons une approche où les compositeurs-informaticiens peuvent s'exprimer dans des espaces multiples, sans leur imposer une conception préétablie.
Résumé ........................................................................................................................................ 4
1. Introduction............................................................................................................... 10
1.1. Vocabulaire................................................................................................................. 10
1.2. AIME, l’atelier incrémentiel..................................................................................... 11
1.3. Une représentation graphique des sons pour la synthèse additive en temps réel 16
1.4. Trajectoires élastiques de mobiles virtuels........................................................... 20
1.5. Couplages élastiques................................................................................................ 21
1.5.1. L’aspect statique des réseaux de couplages......................................................... 21
1.5.2. L’aspect dynamique des réseaux de couplages................................................... 24
1.6. La transformée élastique.......................................................................................... 24
1.7. Un séquenceur algorithmique interactif................................................................. 27
1.8. Un générateur de partitions pour piano et orchestre........................................... 29
1.9. Conversions............................................................................................................... 36
2. Représentation graphique des sons....................................................................... 40
2.1. Principe des phonogrammes.................................................................................... 41
2.1.1. Échelle microtonale des phonogrammes................................................................ 41
2.2. Représentation interne des phonogrammes.......................................................... 45
2.2.1. Dissection des images.............................................................................................. 45
2.2.2. Algorithme d’intégration d’un segment................................................................ 47
2.2.3. Vectorisation.............................................................................................................. 51
2.2.4. Conversion vectorielle/bitmap................................................................................ 54
2.2.4.1. Traitement numérique d'images............................................................................... 55
2.3. Outils graphiques spécialisés.................................................................................. 56
2.3.1. Pinceau à harmoniques............................................................................................. 60
2.3.2. Pinceau à timbres....................................................................................................... 62
2.3.3. Tracé élastique de courbes et de droites............................................................... 67
2.3.4. Masques pour échelles microtonales..................................................................... 68
2.4. Synthèse et analyse des sons dans Phonogramme............................................. 69
2.4.1. Les images de Phonogramme.................................................................................. 69
2.4.2. La synthèse sonore à partir des images................................................................. 70
2.4.2.1. Synthèse additive ou synthèse directe.................................................................. 70
2.4.2.1.1. Traitement du signal................................................................................................. 76
2.4.2.1.2. Visualisation du signal............................................................................................. 77
2.4.2.1.3. Accès disque, flux et flux AIFF............................................................................... 77
2.4.2.2. Conversion des phonogrammes vers la norme MIDI.......................................... 78
2.4.2.2.1. Exécution en temps réel des phonogrammes........................................................ 78
2.4.2.2.2. Génération de fichiers MIDI.................................................................................... 81
2.4.3. L'analyse du son pour la synthèse d'images......................................................... 81
2.4.3.1. Transformée de Fourier Rapide............................................................................... 81
2.4.3.2. Transformée de Fourier discrète............................................................................. 86
2.5. Organisation temporelle des phonogrammes........................................................ 88
2.5.1. Les marques............................................................................................................... 88
2.5.2. Les schémas............................................................................................................... 90
2.5.2.1. Structure et réflexes des schémas........................................................................... 90
2.5.2.1.1. Structure des cellules et des flèches...................................................................... 90
2.5.2.1.2. Propriétés des cellules et des flèches..................................................................... 91
2.5.2.1.3. Surfaces sensibles et déclencheurs........................................................................ 94
2.5.2.2. La clepsydre ou le sablier......................................................................................... 96
2.6. Convolutions............................................................................................................. 97
2.6.1. Génération de suites............................................................................................... 102
2.6.2. Les multiplications.................................................................................................. 104
2.6.3. Des nombres infinis à gauche vers une méthode de multiplication...................... 106
2.6.3.1. Représentation graphique des tables de divisions et multiplications............. 116
2.6.3.1.1. Division..................................................................................................................... 117
2.6.3.1.2. Multiplication........................................................................................................... 117
2.6.3.1.3. Constructions.......................................................................................................... 119
3. Oscillateurs et trajectoires...................................................................................... 122
3.1. Le bruissement des feuilles.................................................................................... 122
3.2. Les trajectoires......................................................................................................... 123
3.3. Mise en œuvre des trajectoires............................................................................. 128
3.4. Conversion de phonogrammes vers des trajectoires......................................... 130
3.5. Expériences avec les trajectoires........................................................................... 131
4. Couplages élastiques.............................................................................................. 138
4.1. Des interfaces graphiques..................................................................................... 138
4.2. De la transformation, de l'analyse et de la création de sons............................. 146
4.2.1. Filtrage...................................................................................................................... 149
4.2.2. Synthèse................................................................................................................... 150
4.3. Le carré de la distance............................................................................................ 154
4.4. Simulation de ressorts............................................................................................ 154
4.5. Imprécision du calcul dans la simulation............................................................. 161
4.6. Résonateurs à couplages élastiques.................................................................... 162
4.6.1. Expérience avec les graphes de couplages élastiques...................................... 162
4.7. Génération de trajectoires à partir de réseaux de couplages............................. 172
4.8. Conversion des trajectoires en réseaux élastiques circulaires......................... 176
4.9. Interface graphique pour les graphes de couplages élastiques............................. 177
5. Transformée élastique............................................................................................ 179
5.1. Analyse acoustique directe................................................................................... 179
5.2. Procédé d'analyse.................................................................................................... 179
5.3. Contrôle de la résonance........................................................................................ 182
5.4. Optimisation............................................................................................................. 183
5.5. Algorithme des résonateurs.................................................................................. 184
5.6. Étalonnage des fréquences des résonateurs...................................................... 185
5.7. Étalonnage des niveaux des résonateurs............................................................ 186
5.8. Production de signal par bancs de résonateurs................................................. 191
5.9. Stimulation des bancs de résonateurs par des flux MIDI................................. 192
5.10. Filtrage d'un signal par bancs de résonateurs.................................................... 192
5.11. Génération d’un réseau élastique à partir d’un signal....................................... 192
6. Métronome : noyau d’applications pour la composition algorithmique en temps réel 195
6.1. Infrastructure........................................................................................................... 195
6.1.1. Le système hôte....................................................................................................... 195
6.1.2. Un squelette d’application..................................................................................... 196
6.1.3. Boîte à fenêtres........................................................................................................ 196
6.1.4. Boîte à outils............................................................................................................ 197
6.1.4.1. Visualisation automatique d’allocations dynamiques....................................... 198
6.1.4.1.1. Points d'entrée......................................................................................................... 200
6.1.4.1.2. Détection des pointeurs......................................................................................... 202
6.1.4.1.3. Représentation graphique des blocs de mémoire............................................... 203
6.1.4.1.4. Actualisation dynamique et élastique.................................................................. 205
6.1.4.1.5. Calcul des tensions élastiques.............................................................................. 208
6.1.4.1.6. Manipulation des représentations........................................................................ 209
6.1.4.1.7. Vent (ou placement semi-automatique)................................................................ 209
6.1.4.2. Descriptions de contrôles...................................................................................... 210
6.2. Le module Métronome............................................................................................ 212
6.3. Interface MIDI, le Système MIDIShare................................................................ 213
6.3.1. Enregistrement de flux MIDI dans les phonogrammes...................................... 214
6.3.2. Traitement MIDI...................................................................................................... 214
6.4. Algorithme rythmique & dynamique de Métro3................................................ 215
6.4.1. Les durées................................................................................................................ 215
6.4.2. La dynamique........................................................................................................... 217
6.4.2.1. Accentuation dynamique aléatoire....................................................................... 217
6.4.2.2. Accentuation dynamique arborescente............................................................... 218
6.5. Harmonies................................................................................................................. 219
6.5.1. Gammes..................................................................................................................... 222
6.5.2. Intervalles................................................................................................................. 225
6.5.3. Accords.................................................................................................................... 225
6.5.4. Composition algorithmique.................................................................................... 232
6.5.4.1. Module Intervalle.................................................................................................... 232
6.5.4.2. Le module Module.................................................................................................. 236
6.5.4.3. Le module Pouzzolane............................................................................................ 243
6.5.4.3.1. Structure des mémoires mélodiques..................................................................... 245
6.5.4.3.2. Algorithme de Pouzzolane..................................................................................... 246
6.5.4.4. Le module Alpha..................................................................................................... 249
6.6 Exosmose.................................................................................................................. 251
7. Générateurs de partitions....................................................................................... 252
7.1. Éditeurs de partitions.............................................................................................. 253
7.2. Chnrng14 : Générateur de partitions pour piano et orchestre................................ 253
7.3. Impression de partitions......................................................................................... 254
7.3.1. Notation musicale.................................................................................................... 255
7.3.1.1. Structures des pages.............................................................................................. 258
7.3.1.2. La lecture.................................................................................................................. 263
7.3.2. Module d'impression.............................................................................................. 264
7.3.2.1. Structure des événements sonores et silencieux................................................ 264
7.3.2.1.1. La structure des notes............................................................................................ 266
7.3.2.2. Information de mise en page et de sélection....................................................... 271
7.3.2.3. Décomposition en éléments graphiques.............................................................. 275
7.3.2.4. Tension élastique pour la mise en page............................................................... 276
7.3.2.5. Position des altérations.......................................................................................... 278
7.4. Production de partitions à partir de phonogrammes.......................................... 278
7.5. Conversion de partitions en phonogrammes...................................................... 283
7.6. Lecture automatique de partitions musicales...................................................... 285
7.7. Liberté Verticale....................................................................................................... 285
7.7.1. Le mouvement.......................................................................................................... 286
7.7.2. La mémoire................................................................................................................ 288
7.7.3. Les modes et les positions de doigts................................................................... 289
7.8. Algorithme de génération mélodique................................................................... 293
7.8.1. Irlandais, pour violon.............................................................................................. 293
7.8.1.1. Reels et Hornpipes, structure rythmique, harmonique et mélodique.................... 294
7.8.1.2. Base modale............................................................................................................. 295
7.8.1.3. Ligne mélodique...................................................................................................... 297
7.8.1.4. Règles de pondération des tirages aléatoires..................................................... 298
7.8.1.4.1. Arbres d’appels de fonction pseudo-aléatoire................................................... 302
7.8.1.4.2. Interface de construction des arbres binaires..................................................... 311
7.8.1.5. Paramétrage des choix aléatoires.......................................................................... 312
7.8.1.6. Plans de copies........................................................................................................ 312
7.8.1.6.1. Les plans locaux : recopie d'une note................................................................... 312
7.8.1.6.2. Les plans généraux : forme ABAC........................................................................ 313
7.8.2. Méduse, pour Contrebasse et Phonogrammes................................................... 314
Conclusion .................................................................................................................................... 317
8.1. Les limitations actuelles et l’évolution de l’atelier............................................. 318
8.1.1. Les limitations actuelles de AIME dans le domaine graphique............................. 318
8.1.2. Limitations temporelles........................................................................................... 320
8.2. Développements actuels et perspectives............................................................ 321
Annexe 1 Dimensions physiques des sons........................................................................................................... 331
L'effet Doppler .................................................................................................................................... 337
Annexe 2 : Irlandais .................................................................................................................................... 342
Annexe 3 : Règle de couplage (frottement)............................................................................................................ 351
Annexe 4 : Phénomènes Physiques en Acoustique, Étude expérimentale du timbre des sons........................... 353
Analyse d’un son complexe par les résonnateurs (sic)................................................................................ 353
Composition des sons complexes.................................................................................................................... 355
Références bibliographiques................................................................................................................................... 356
Nous présentons notre atelier informatique d’expérimentation musicale : AIME (Atelier Incrémentiel pour la Musique Expérimentale), qui est le premier atelier musical permettant d’utiliser à la fois les outils de notation, de génération, de transformation de sons (ou de formes musicales) et la totalité des fonctionnalités de traitement des images, permettant au compositeur/interprète d’utiliser indistinctement l’une ou l’autre de ces représentations, dépendant des actions particulières (transpositions, étirement temporel, modifications dans le domaine spectral, collages, etc.) qu’il désire effectuer.
Dans cet atelier sont nées de multiples applications (dont Phonogramme, Métro3, Chnrng14) représentant des approches compositionnelles fondées sur des concepts spécifiques, inventés spécialement pour une pièce, ou permettant au contraire une expression directe des compositeurs à l’aide d’outils génériques, leurs offrant divers systèmes de représentation des formes musicales et des moyens de conversion d’une forme à une autre.
Avant de présenter les trois principales applications qui serviront de support pour notre exposé, nous souhaitons ici introduire brièvement différents systèmes de représentation du son que nous utilisons dans la suite, ainsi que certains termes désignant nos systèmes ou procédés :
Les sons échantillonnés (ou signaux sonores échantillonnés), ou sons numériques, sont conservés sous la forme amplitude/temps. Un son est alors représenté par une suite de valeurs numériques décrivant les variations de pression de l’air[1] par rapport à la pression normale. Une façon intuitive de le présenter est de dire que les valeurs indiquent la position de la membrane du haut-parleur (ou du micro, ou encore du tympan) à chaque instant.
Les sonogrammes (ou sonagrammes selon Xavier RODET (RODET 1977)) sont des représentations du son dans un espace fréquence/temps. Un sonogramme est constitué d’une succession de spectres instantanés, chaque spectre donnant l’énergie du signal en fonction de la fréquence pour une fenêtre ou tranche temporelle donnée.
Les phonogrammes sont des représentations des sons proches des sonogrammes (dans le même espace fréquence/temps), mais l’échelle des fréquences est logarithmique. Nous en avons étudié la structure de données pour faciliter leur exploitation, tant du point de vue graphique que sonore.
Les couplages élastiques, sont des liens reliant les nœuds d’un graphe et appliquant une tension sur ces nœuds. Les nœuds du graphe peuvent être fixes ou mobiles : seuls les nœuds mobiles subissent un changement de coordonnées fonction des tensions des liens.
La transformée élastique est notre système d’analyse des sons basée sur les couplages élastiques. Elle permet de transformer des sons échantillonnés en phonogrammes.
Les trajectoires que nous mentionnons ci-après sont les trajectoires de mobiles virtuels, dont la projection de la position sur un axe au cours du temps nous sert à construire un signal sonore échantillonné.
Les applications : Un programme exécutable, dans l’environnement Macintosh est désigné par le terme application. Nous avons gardé cette terminologie.
Les modules : Nous dénommons module un ensemble cohérent de fonctions et structures de données, relatives à un problème particulier.
Les squelettes. : Un squelette est un programme type similaire aux schémata de Françoise BALMAS (BALMAS 1995), définissant les éléments minimums nécessaires pour implémenter une architecture particulière. Ce programme, est destiné à être recopié, puis transformé pour le spécialiser.
L’atelier est formé par un ensemble d’applications, de bibliothèques de fonctions et de squelettes d’applications. L’écriture de nouvelles applications ou de nouveaux modules contribue à l’enrichissement de l’atelier, tant au niveau de la programmation (création de nouvelles bibliothèques, ou ajout de fonctions génériques dans les bibliothèques) qu’au niveau musical, l’activité de composition étant facilitée par les nouvelles fonctionnalités. Toutes les applications de l’atelier peuvent être connectées les unes aux autres via le système de communication implémenté dans MIDIShare. MIDIShare est développé à GRAME[2] (ORLAREY 1989) (cf. § Interface MIDI, le Système MIDIShare).
Ci dessous nous présentons brièvement Phonogramme, Métro3 et Chnrng14 qui représentent les trois grandes classes d'applications musicales que nous avons développées dans le cadre de cette thèse :
• Phonogramme (LESBROS 1995a, 1995b) (ROADS 1995) est fondé sur le concept d'édition interactive. Comme une palette graphique, les documents qu'il permet d'éditer sont des images, mais ces images sont encodées sous une forme telle qu'elles peuvent être interprétées comme des sonogrammes et être jouées en temps réel ou produire des fichiers de sons échantillonnés.

Figure 1.1 : Exemple d’image créée dans l’application Phonogramme.
Cette image (Figure 1.1) représente des sons d’intensités différentes exprimées en valeur de gris. Les traits superposés conservant constants les écarts verticaux sont ici à des distances correspondant à des harmoniques.
À l'inverse de cette possibilité de génération, des sons produits par des sources externes peuvent être intégrés aux images par notre procédé de transformée élastique. Dans la même application sont intégrés d'autres systèmes de représentation graphique des sons, telles que le module d'édition de trajectoires élastiques permettant la synthèse de vibrations amorties, et un module d'édition graphique de réseaux de couplages élastiques permettant une forme de synthèse par simulation de la propagation des vibrations, ainsi que le filtrage de sources sonores externes par la propagation des vibrations dans le réseau.

Figure 1.2 : Exemple de trajectoire.
Au cours de la simulation, la trajectoire se déforme sous l’action des couplages élastiques connectant les points successifs de la trajectoire. La projection sur l’axe horizontal de la position du mobile virtuel circulant le long la trajectoire au cours du temps fournit un son échantillonné.
Voici à présent un exemple de réseau de couplages élastiques (figure 1.3). L’interface homme-machine permet de créer et modifier le réseau directement à l’aide de la souris.

Figure 1.3 : Exemple de réseau de couplage
Noeud fixe,
Noeud mobile,
Couplage élastique
Émetteur,
Récepteur.
Les émetteurs permettent d’exciter le réseau en déplaçant chacun un ou plusieurs noeuds[3] selon les valeurs d’amplitude provenant d’un fichier de son échantillonné. Les récepteurs permettent de produire chacun un fichier de son échantillonné à partir de la position des noeuds et/ou de la longueur des liens auxquels ils sont connectés. Au cours de la simulation, les couplages modifient la position des noeuds mobiles, l’image est animée.
• Métro3 (ENGLERT 1993), dont le concept central est celui d'un séquenceur (Métronome), est une application permettant la préparation et l’exécution en direct de pièces de musique synthétique. Son interface et ses fonctionnalités en font un outil sophistiqué, permettant le contrôle de la génération des événements sonores, et des transformations des séquences de notes en temps réel. Son modèle est exploité dans d'autres applications (cf. § Composition algorithmique) temps réel à base algorithmique que nous présentons dans la suite.
• Chnrng14 (change ring 14) est représentative parmi nos applications pour la musique algorithmique générée automatiquement en vue d'une exécution par des instrumentistes. Elle comporte un module de génération spécifique d'une pièce : Chacones, pour orchestre et piano concertant (ENGLERT 1995), et un module de mise en page et d'impression de partitions pour orchestre et pour piano. Ce dernier module est utilisé dans d'autres applications génératrices de partitions, dont les modules de génération sont contrôlés par un ensemble de paramètres dépendants de l’algorithme tels que les instruments, l’ambitus, la densité d’événements, les paramètres rythmiques, etc.
L'exposé des différents passages existant entre les formes de représentations manipulées dans le système nous permettra de découvrir les cheminements possibles des compositeurs utilisant notre atelier (cf. § Conversions).
En effet, nous pouvons créer des sons d’après des images, nous pouvons modifier, transformer ces sons, utiliser des sons existant pour former de nouvelles images, transformer ces images, utiliser notre système pour produire une partition, ou au contraire intégrer une partition[4] dans une image. Les productions des algorithmes de génération peuvent également être intégrés dans les images, ou inversement, l’interprétation des images peut être transformée par l’application d’algorithmes. Toutes ces transformations et les conversions possibles entre différents modes de représentation du son ou des séquences musicales offrent de nouvelles voies dans le domaine de la composition de musique expérimentale.
Par exemple Marc BATTIER a composé sa pièce TOCA (BATTIER 1994), en utilisant Phonogramme pour transformer en son des images obtenues à partir de l’analyse spectrale de sons réels[5]
Une pièce en quarts de tons est jouable par deux pianos : Chaque piano, pris séparément est accordé normalement, en demi-tons et peut être joué naturellement. Mais un des deux pianos est accordé un quart de ton plus haut que l’autre. Cet entrelacement des deux échelles, mis en valeur par un long travail de synchronisation, de mimétisme du jeu et des mouvements des interprètes, permet la perception pour l’auditeur de l’existence d’une unique échelle en quarts de tons.
Nous avons transposé cette idée, pour l’appliquer à un banc de seize synthétiseurs[6] limités chacun à la gamme chromatique[7]. Chaque synthétiseur a donc été accordé sur un seizième de demi-ton particulier. L’entrelacement des échelles chromatiques donnant ainsi naissance à une unique échelle microtonale en trente-deuxièmes de ton.

Figure 1.4 : Cette figure représente graphiquement l’entrelacement entre les différentes échelles, d’abord par un instrument seul, ensuite par deux, et ainsi de suite. En augmentant le nombre d’instruments chromatiques (numérotés à gauche), nous obtenons des échelles de plus en plus fines. Pour n instruments, l’échelle obtenue est en demi-tons divisé par n.

Figure 1.5 : L’échelle totale dont nous disposons avec les 16 synthétiseurs couvre 128 demi-tons avec un pas de 1/32ième de ton (2048 notes).
Notre but initial étant la synthèse en temps réel de sons représentés dans le domaine temps-fréquence tel les sonogrammes, nous avons créé une représentation particulière, proche de sonogrammes, adaptée à la visualisation et aux manipulations graphiques, qui est principalement une tablature pour ce système d’échelles multiples entrelacées. Nous désignons cette représentation par le terme phonogramme.

Figure 1.6 : Cette figure présente un extrait d’une page de la pièce Phonographiques (LESBROS 1994) représentant environ 85 secondes. L’image est ici réduite à 50% de sa taille originale.
Les traits épais de la figure 1.6, orientés horizontalement et dessinés à la souris forment des sons harmoniques à caractère vocal. La série de barres verticales prolongées par des traits horizontaux représentent des sons percussifs subissant une diminution d’amplitude assez rapide suivie d’une résonance. Le nuage de points dans le registre aigu (la partie supérieure de l’image) a été formé aléatoirement et produit des sons évoquant des tintements ou cliquetis de petits objets légers et durs.
Les phonogrammes permettent à la fois la représentation des images et des sons. L’exécution en temps réel d’un phonogramme consiste globalement à transmettre des messages décrits par ces structures aux seize modules de synthèse externes. Ceci est réalisable avec un micro-ordinateur de faible puissance[8].
Ce système de représentation a ouvert un champ de recherche et d’investigation important et nous avons développé des outils et des fonctionnalités d’une part pour explorer ce domaine et établir des liens avec d’autres systèmes de représentation de la musique (partitions, signaux échantillonnées, trajectoires, etc.) et d’autre part pour rendre accessible un système de composition graphique de musique à d’autres compositeurs.
La base du système, le module d’exécution des phonogrammes a été développée en utilisant le module Métronome (cf. Chapitre 6). Puis nous avons adjoint des outils graphiques spécifiques, en particulier un pinceau à timbres, que nous présentons dans le chapitre Outils graphiques spécialisés. Nous nous sommes affranchis des modules de synthèse externes[9] en implantant la synthèse additive (cf. § Synthèse additive ou synthèse directe), quitte à perdre les avantages de l’exécution en temps réel, mais en gagnant le contrôle complet sur le signal généré.
Les problèmes d’entrée/sortie des images étant résolus (import de fichiers au format PICT[10], copie des images depuis et vers le presse-papiers), le passage des images aux sons existant sous plusieurs formes, il nous manquait la possibilité de passer de signaux sonores vers la représentation en phonogramme correspondant. Nous présentons dans le chapitre L'analyse du son pour la synthèse d'images, les systèmes classiques d’analyse que nous avons utilisé : les convolutions, la transformée de FOURIER (SOIZE 1993) (BEAUCHAMP 1987) (BRACEWELL 1986), puis dans les chapitres suivants, nous présentons notre système de transformée élastique, mieux adapté à ce traitement. Les sons percussifs de l’image précédente (figure 1.6) ont été obtenus par la transformée élastique d’un signal échantillonné préexistant.
Nous avons utilisé les phonogrammes dans des œuvres différentes, parmi lesquelles : Farni-NT[11], une pièce réalisée pour mettre en musique une histoire mise en scène par les enfants de l’école de CHELLES, Phonographiques, une pièce pour phonogramme basée sur l’usage de différentes techniques graphiques : par exemple le choix des supports et des outils, ainsi que l’exploitation de différentes techniques gestuelles utilisées pour créer les graphismes, Pouzzolane, une pièce composée pour un festival sur la microtonalité[12], et Midisonnante composée pour le centième anniversaire de Prélude à l’après-midi d’un faune de Debussy[13].
Giuseppe ENGLERT a utilisé Phonogramme[14] pour réaliser l’intégralité de la pièce Triptyque . Dans un concert à KOBE, Marc BATTIER (BATTIER 1993) fut le premier à utiliser des sons produits par Phonogramme , avec la création de la pièce Toca, pour sons électroniques et marimba.
Avant d’être perçu, le son est une vibration. Pour synthétiser des sons nous devons construire des oscillateurs. Nous présentons dans le chapitre Oscillateurs et trajectoires, des oscillateurs numériques basés sur la construction de signaux résultant de la projection sur une dimension, de trajectoires de mobiles virtuels d’un espace à deux dimensions.
Les déformations élastiques appliquées sur des trajectoires permettent la synthèse de sons à caractère naturel. Un cas particulier de trajectoires élastiques correspond à l’algorithme de Karplus-Strong (KARPLUS STRONG 1983) (JAFFE SMITH 1983) pour la synthèse de sons de cordes pincées et de percussions.
La simplicité avec laquelle nous pouvons dessiner les trajectoires et obtenir les sons nous a conduit à la réalisation d’une application indépendante de Phonogramme, nommée Sound Potato, que des enfants peuvent utiliser pour créer des sons avec la souris.
Les premières simulations de couplages élastiques que nous avons réalisées (LESBROS 1988) étaient exploitées uniquement sur le plan graphique. Le réalisme de la simulation du mouvement ne nous intéressait pas, seule la convergence du réseau formé par les couplages, entre points fixes et points mobiles vers un état stable était l’objet de notre étude.
Le traitement de la propagation de l’influence mutuelle des tensions élastiques dans le réseau était initialement écrit de manière récursive. Ceci reste correct tant que l’on souhaite n’utiliser que l’état final du réseau, mais les configurations intermédiaires du réseau dépendaient de l’ordre de traitement de l’action des liens sur les points, lui-même dépendant de l’ordre de construction du réseau.
Voici, par exemple un réseau très simple (figure 1.7), constitué de trois points fixes reliés à un point mobile.

Figure 1.7 : Un réseau de couplages élastiques
La représentation interne que nous avions adoptée donnerait le schéma correspondant ci-dessous (figure 1.8) :

Figure 1.8 : Représentation interne d’un réseau de couplages
Les points connaissent leur position et la liste (ordonnée par construction) de leurs liens, les liens pointent sur les deux points qu’ils relient.
Nous pouvons simplifier la représentation interne, en éliminant la représentation des liens en tant qu’objets indépendants (figure 9), et en les représentant implicitement par la liste des points voisins de chaque point. Les liens seront alors incapables de mémoriser des caractéristiques particulières (telle la tension), mais le schéma correspondant s’éclaircit considérablement.

Figure 1.9 : Représentation interne simplifiée du réseau de couplages.
L’ordre de traitement des tensions est déterminé ici par l’ordre d’apparition des liens dans la liste des liens du point ou dans la liste des voisins d’un point selon la représentation choisie.
L’algorithme de traitement pouvait se résumer ainsi :
Déplacement d’un point :
• Calculer les tensions appliquées sur ce point[15]
• Si la tension est supérieure à un seuil[16]
• Changer la position du point
• Effectuer récursivement le déplacement des points voisins.
Cet algorithme entraîne l’effet suivant : des parties du réseau peuvent se stabiliser localement, puis les modifications des positions des points se propagent à d’autres parties du réseau, jusqu’à la stabilisation globale.
Dans le cas de réseaux linéaires, tels ceux utilisés pour le trajet des flèches des schémas temporels de Phonogramme (voir ci-dessous), ou ceux utilisés dans le module de mise en page des pentagrammes (cf. chapitre Générateurs de partitions), la conjugaison de ce principe résulte en une simple boucle, qui, applique la tension sur chaque point l’un après l’autre.
L’utilisation des réseaux de couplages élastiques pour la synthèse et l’analyse de signaux acoustiques a nécessité la prise en compte des états intermédiaires des réseaux élastiques en cours de stabilisation, ou excités continûment par un apport externe d’énergie. C’est-à-dire la prise en compte de la dynamique du réseau donnée par le mouvement des points.
La description des mouvements s’effectue dans l’espace et dans le temps (alors que la position stable d’un réseau ne nécessite qu’une description spatiale).
Ce nouveau paramètre, le temps, doit subir une discrétisation, de façon à pouvoir manipuler des états successifs du réseau de couplage.
La représentation doit permettre de fournir la position de tout point à un instant donné de manière à calculer la position des points pour l’instant suivant. Le calcul des positions au temps ti+1 ne doit pas modifier les données concernant la position au temps ti.
L’implémentation des réseaux de couplages élastiques que nous présentons dans le chapitre Couplages élastiques, utilise un algorithme simulant le parallélisme temporel de l’influence des couplages élastiques sur la position des points.
La synthèse sonore à partir de réseaux de couplages élastiques est effectuée en enregistrant les mouvements des points du réseau au cours du temps. D’autre part, nous avons utilisé les réseaux élastiques pour filtrer des sons : nous pouvons exciter le réseau en déplaçant un ou des points selon les valeurs d’amplitudes de signaux existant, et enregistrer les mouvements d’autres points du réseau. Suivant la configuration du réseau, les tensions des couplages, et la viscosité[17] du milieu, nous obtenons des filtrages différents. Ceci nous a conduit à la réalisation de bancs de résonateurs constitués d’un point fixe, d’un point mobile et d’un point mu par le signal. Le réglage de la tension des couplages entre ces points s’avère lié à la fréquence de résonance du système. Le banc de résonateur agit comme un banc de filtres, chaque filtre étant sensible à une bande de fréquence réduite. Nous nommons transformée élastique le processus de filtrage d’un signal par ce type de banc de résonateurs en vue de la production d’un phonogramme.

Figure 1.10 : Spectre obtenu par le banc de résonateurs à partir d’un signal sinusoïdal. De chaque coté, on voit que, en dessous d’un seuil donné, seul un resonateur sur 16 reste actif.

Figure 1.11 : Un extrait de Summer time joué par Charlie Parker (PARKER 1988) analysé par la transformée élastique entre 100 et 3000 Hertz.
La transformée élastique peut être utilisée pour analyser des séquences musicales (figure 1.11). Dans les harmoniques, on voit nettement le vibrato (variation de fréquence des notes) sur les notes tenues. L’image a été traitée pour ne retenir que les valeurs dépassant un certain seuil.
Outre la synthèse directe et l’analyse des sons, la composition de musique expérimentale nécessite des outils permettant la manipulation de diverses formes sonores, par exemple des séquences de notes. Phonogramme permet d’analyser un son (par la transformée élastique) et de le transformer en séquences de notes (sous forme de fichiers MIDI). Ou inversement, le séquenceur Métro 3, décrit dans le paragraphe suivant, peut générer des séquences qui seront retranscrites en phonogrammes en vue de leur transformation et/ou de leur synthèse.
Depuis 1982, nous développions[18] des programmes de composition musicale interactifs, permettant une exécution en temps réel. Nous utilisions le système Synclavier Model A[19], constitué d’un micro-ordinateur et d’un module de synthèse mixte basé sur la modulation de fréquence. La mémoire de cette machine était de 64 kilo octets (32 K mots de 16 bits), et nous ne disposions pas de mémoire de masse autre que des disquettes souples d’une capacité inférieure à 300K. Ces contraintes physiques nous imposaient l’élaboration d’algorithmes de génération musicale nécessitant peu de mémoire, utilisant donc des modèles de génération basés sur un ensemble restreint de paramètres. Il était pratiquement impossible de mémoriser l’ensemble des événements d’une pièce.
Pour chaque œuvre, nous réécrivions un système complet comprenant un niveau de lutherie pour l’élaboration des timbres, un niveau de construction d’événements constituant les enveloppes à partir de segments successifs, et un ou plusieurs niveaux macrocompositionnels, pour l’organisation générale. La tâche la plus délicate étant l’écriture du système d’organisation temporelle des événements, permettant de gérer indépendamment plusieurs voix, tout en offrant la possibilité de synchronisation. Lirio MARTINEZ (MARTINEZ 1995), développe actuellement un atelier de composition, d’expérimentation, et d’interprétation de musique informatique basé sur ce synthétiseur, et interfacé avec les machines de type PC sous l’environnementWindows.
Le passage vers des micro-ordinateurs plus puissants (mémoire de l’ordre du mégaoctet, et unité de disque dur), munis d’écran graphiques, et associés à des synthétiseurs externes commandés par des interfaces MIDI nous à fait reconsidérer notre démarche. Les timbres étant élaborés grâce à des applications existantes, et synthétisés par les modules externes, notre programmation pouvait s’abstraire de la gestion de ceux-ci. Les couches de gestion des interfaces MIDI et du temps étant déléguées à une bibliothèque externe[20], nous avons pu construire un modèle de programme plus général, utilisable par plusieurs compositeurs, permettant de gérer des séquences mélodiques, et d’appliquer des traitements sur ces séquences.
La base de ce système est le traitement de séquences de hauteurs exprimées en numéro de demi-ton. Nous pouvons créer des séquences de longueurs diverses, les mémoriser, les visualiser simplement sous forme de textes, les copier, et appliquer des transformations telles que la transposition, les inversions (de hauteur ou d’intervalles mélodiques). Nous pouvons également opérer des combinaisons de séquences telles les insertions, la concaténation, ou encore des combinaisons logiques telles que le ou exclusif des hauteurs exprimées sous leur forme binaire. Les séquences peuvent être générées par un algorithme pseudo-aléatoire entre des limites fixées.
Le système est organisé en huit voix indépendantes. Chaque voix peut être activée ou désactivée et jouée de façon cyclique ou non.
Chaque voix possède ses propres valeurs des paramètres rythmiques, son propre timbre.
L’interface permet une commande indépendante pour chaque voix, ou bien la commande simultanée de plusieurs voix sélectionnées.
Tous les paramètres de l’interface peuvent être mémorisés dans des registres de configurations. Et l’ensemble des configurations peuvent être sauvegardées dans des fichiers.
Les œuvres composées avec ce système (ENGLERT 1992), (MARIETAN 1991) nécessitent une préparation des configurations et des séquences, puis lors de l’exécution, une partition indique à l’interprète les opérations à effectuer.
Toutes les opérations de traitement peuvent être effectuées pendant l’activité du système. Certaines opérations, telles que les mutations d’une séquence vers une autre n’opèrent que pendant l’exécution de la séquence.
Nous exposerons en particulier le système rythmique et dynamique que nous avons développé pour ce séquenceur. En effet, les séquenceurs existants (YAVELOW 1992) mémorisent des séquences contenant pour chaque événement (ou note) non seulement la hauteur de la note, mais également d’autres données. La durée et l’intensité sont les deux principales. Notre séquenceur génère automatiquement les durées et les intensités d’après un algorithme que nous détaillerons dans le paragraphe Algorithme rythmique & dynamique de métro3.
Les générateurs obtenus par l’utilisation du module Métronome et le développement d’algorithmes spécifiques permettent la commande de synthétiseurs en temps réel (ou synthèse mixte). Mais certaines compositions utilisant des instruments traditionnels, nécessitent l’écriture de partitions classiques. Dans le paragraphe suivant, nous introduisons CHNRNG14, un générateur de partitions pour orchestre.
Nous avons conçu et réalisé, avec la collaboration de Giuseppe G. ENGLERT, un système capable de produire l’ensemble du matériel d’orchestre[21] et les partitions pour le piano d’une pièce : CHACONES, pour orchestre et piano concertant.
Figure 1.12
La page précédente (Figure 1.12) est le premier système de la première page de la partition de piano de CHACONES. L’impression est réduite à 80%.
Le module d’impression est spécialisé de manière à contrôler finement toutes les caractéristiques graphiques des partitions. Il eut été possible en effet de se consacrer uniquement sur l’aspect génératif de la pièce, et de déléguer l’impression à des éditeurs de partition externes (BELKIN 1994) en utilisant un format standard tel que les fichiers MIDI (MIDI 1989), ou des formats plus complets, spécialisés pour les partitions et intégrant les articulations, mais notre but était d’assurer l’intégralité de la composition et de la mise en page automatiquement, pour éviter toute intervention manuelle.
Globalement, la forme interne que produit le module générateur de la pièce est un ensemble de chaînages d’événements, sonores ou silencieux, ordonnés chronologiquement et répartis selon des pistes.
Les pistes correspondent pour la partition d’orchestre à des portées, et pour les parties séparées à des instruments. Elles peuvent toutefois changer d’instrument dans la partition d’orchestre, et pour la partition de piano, la répartition des notes sur les portées est déterminée uniquement par leur hauteur, les pistes ne représentent alors que la possibilité harmonique de l’instrument.
Le module d’impression permet la visualisation sous plusieurs formes de cette structure interne. Son rôle est de calculer les signes graphiques qui doivent apparaître sur une page (ou sur une section de page) du matériel d’orchestre.

Ci-dessus (Figure 1.13), une page de la partie de la première flûte. Réduction 75%.
La composition, œuvre de Giuseppe ENGLERT, réalisée par le module générateur, est basée sur une structure verticale, constituée d’une suite de 14 accords, qui subit les 52 périodes d’un algorithme de permutation avant de retrouver l’ordre initial. La partie de piano et la partie d’orchestre utilisent la même séquence de 52 périodes mais dans l’ordre inverse. Les modules de génération de la partie d’orchestre et de la partie de piano sont séparés et indépendants.
L’algorithme utilise des générateurs pseudo-aléatoires pour effectuer des choix, mais les graines[22] sont initialisées de manière à générer toujours la même pièce. Le contrôle de l’algorithme s’étend sur les hauteurs, les durées des notes et également sur les articulations (trémolo, vibrato, staccato, etc...) mais n’englobe pas la dynamique, qui est fixée par l’auteur après l’impression finale du résultat, et d’après une écoute mentale du produit de la synthèse.
Les articulations sont visualisées par la forme des têtes des notes, ou par des signes suivant la note ou encore pour les trémolos, par des barres obliques sur les hampes des notes.
Nous avons particulièrement travaillé sur la simplicité et la lisibilité de la partition d’orchestre[23]. D’après BYRD (BYRD 1994), l’écriture musicale est beaucoup plus complexe que l’écriture Chinoise. Cette complexité s’explique, malgré le nombre restreint de symboles, par le nombre de contraintes, de liaisons et de règles d’écritures. BYRD donne des exemples de partitions classiques (telles les Variations GOLDBERG de J.S.BACH) enfreignant les règles habituelles, mais qui sont tout à fait lisibles par les instrumentistes.

Figure 1.14 : Extrait de CHACONES
Voici un extrait (figure 1.14) de la partition avec dans la portée supérieure, les deux voix de flûte, et dans la portée inférieure les deux voix de hautbois. Chaque instrument est distingué par l’orientation des hampes des notes, et la position des silences. L’alignement vertical des signes correspond en principe à une synchronicité des événements sonores, mais cette règle peut être contrariée par des déplacements imposés pour la lisibilité des altérations ou la proximité des notes : le troisième temps de la portée inférieure est à gauche du troisième temps de la portée supérieure, à cause des densités différentes. Nous avons utilisé des couplages élastiques pour effectuer la mise en page horizontale des éléments graphiques apparaissant dans chaque mesure.
La pièce doit pouvoir être préparée avec peu de répétitions d’orchestre. Par contre, la partie de piano est soumise au soliste longtemps à l’avance et le travail d’interprétation peut être plus important.

Ci-dessus (figure 1.15) un extrait de la partition d’orchestre de CHACONES (premier groupe d’instruments) neuvième période. Réduction 75%. Une page de la partition complète représente 5 fois cette hauteur (25 portées).
Notre système intègre également la possibilité de jouer la pièce par groupe d’instruments, mais cette fonctionnalité, écrite dans un but de contrôle, n’a pratiquement pas été utilisée. Nous présentons dans le chapitre Générateurs de partitions, les méthodes développées pour traiter les problèmes sensibles de la mise en page, et nous montrons l’utilisation de couplages élastiques reliant les éléments graphiques.
Nous détaillerons ensuite l’algorithme de génération d’une pièce pour piano seul, utilisant le même module d’impression, et dont la base de la génération repose sur des couplages élastiques reliant une représentation virtuelle des mains du pianiste.
Nous exposerons enfin notre travail portant sur un algorithme de génération de monodies pour violon dont le principe nous a été inspiré par l’observation de propriétés des airs de danse Irlandais; et une adaptation de ce générateur à la contrebasse pour une pièce mixte intégrant les phonogrammes et la contrebasse.
Nous manipulons l’information musicale et sonore sous différentes formes :
• Les signaux sous forme de fichiers ou tables d'échantillons.
• Les phonogrammes.
• Les codes MIDI.
• Les images sous forme de bitmaps ou pixmaps.
• Les partitions.
Nous ajoutons à cette liste les éléments suivants :
• Les trajectoires élastiques.
• Les réseaux élastiques, et bancs de résonateurs.
Qui ne représentent pas directement de l’information sonore mais peuvent la produire ou la transformer.
Notre atelier permet des passages entre des systèmes de représentation qui étaient autrefois séparés. L’avantage des possibilités de conversion est évidemment la richesse et la multiplicité des traitements que l’on pourra appliquer sur les sons. Nous offrons ainsi un large choix de nouvelles possibilités pour les compositeurs, en ouvrant la possibilité d’utiliser toutes les fonctions de traitement des images pour la transformation du son.
Nous résumons dans la table ci-dessous les conversions possibles ou les concepts apparaissant à la jonction entre ses éléments pris deux à deux.
Les cellules de la table revoient chacune à un ou plusieurs paragraphes.
|
|
Signal |
Phono-gramme |
MIDI |
Bitmap |
Réseau élastique |
Trajectoire |
Partition |
|
Signal |
Traite-ment du signal. Accès disque, flux et flux AIFF |
FT. FFT
Transfor-mée élastique d'un signal par un banc de résona-teurs
Analyse acousti-que directe |
|
Visuali-sation du signal |
Généra-tion d’un réseau élastique à partir d’un signal |
|
|
|
Phonogramme |
Synthèse additive |
Édition palette d'outils graphi-ques
|
Conver-sion des phono-grammes vers la norme MIDI Exécution temps réel des phono-grammes Généra-tion de fichiers MIDI |
Conver-sion vectoriel-le/bit-map |
Conver-sion de phonogrammes en réseaux élastique |
Convers-ion de phono-grammes vers des trajectoi-res |
Produc-tion de parti-tions à partir de phono-grammes |
|
MIDI |
Liaison avec un synthéti-seur externe |
Enregis-trement MIDI |
Traite-ments MIDI |
|
Stimula-tion des bancs de résona-teurs par des flux MIDI |
|
Éditeurs de parti-tions |
|
Bitmap |
|
Conver-sion bitmap vers Phono-gramme, vectori-sation |
|
Traite-ment numéri-que d'images |
|
|
|
|
Réseau élastique |
Produc-tion de signal par bancs de résona-teurs. Filtrage d'un signal par bancs de résona-teurs |
Transfor-mée élastique. |
Réseau - MIDI |
Représen-tation graphi-que du réseau |
Édition de réseaux |
Généra-tion de trajectoi-res à partir de réseaux de couplages |
Composi-tion utilisant les résona-teurs (mouve-ments des mains) |
|
trajectoi-res |
Parcours du mobile le long de la trajectoi-re en évolution |
|
|
Représen-tation graphi-que de la trajectoi-re |
Conver-sion des trajectoi-res en réseaux élasti-ques circulai-res |
|
|
|
Partition |
Exécution de parti-tions par un instru-mentiste |
Conver-sion de parti-tions en phono-grammes
Lecture automa-tique de parti-tions musicales |
Par exécution dans un éditeur de partition classique |
Forme graphi-que de la partition |
|
|
|
|
|
Signal |
Phono-gramme |
MIDI |
Bitmap |
Réseau élastique |
Trajectoire |
Partition |
De très nombreux auteurs dans le domaine de l’informatique musicale utilisent des représentations graphiques des sons ou des structures musicales. L’utilité de ces représentations, au delà d’une simple illustration (il est difficile de transmettre un son sur du papier), est parfois liée au processus même de l’élaboration des sons. On parle alors de synthèse graphique des sons (ROADS 1995). L’UPIC[24] de XENAKIS en est l’exemple le plus net. Son système permet de créer les sons à partir d’images composées d’arcs dans l’espace fréquence/temps (XENAKIS 1971). Le système UPIC actuel nécessite un matériel dédié pour réaliser la synthèse sonore.
GOGINS (GOGINS 1991) utilise les fonctions itérées (IFS Iterated Fonctions Systems) (BARNSLEY 1989) qui sont habituellement utilisées pour la création d’images (ou leur compression) pour générer des structures musicales. Nous avons également et indépendamment utilisé des fractales pour générer des sons. Dans ces expériences, des fractales générées par Harald WERTZ (WERTZ 1994) ont été directement intégrées dans des phonogrammes. À la différence du système de GOGINS, les notes n’étaient pas limitées aux seules notes de la gamme chromatique, mais étaient prises dans l’échelle microtonale des phonogrammes[25]. Nous pensons que ces fractales doivent être expressément conçues en vue de la synthèse pour obtenir des résultats sonores intéressants. En effet, les fractales que nous avons utilisées étaient destinées principalement à séduire l’œil et leur utilisation en tant que phonogrammes peut déboucher sur des résultats sonores très divers selon les choix des paramètres d’exécution tels que la vitesse, ou la position et l’échelle[26] de l’image.
CORDIS-ANIMA (CADOZ 1993, 1994) est un système utilisant la simulation de modèles physiques pour produire les images, le son, et des effets tactiles. L’image est ici au même niveau que le son, un élément perceptible du modèle simulé dans le système. Dans notre simulation de couplages élastiques et de ressorts, nous avons également la visualisation et la sonorisation d’un modèle, l’image n’est alors plus directement liée au son, elle permet d’aider à la construction du modèle produisant le son.
Daniel ARFIB (ARFIB 1993) utilise des représentations formées de deux images, une pour visualiser l’amplitude (sonogramme) et l’autre pour visualiser la phase (phasogramme) en fonction des fréquences par rapport au temps.
Les sonogrammes sont utilisés par SCHOTTSTAEDT en tant que traduction graphique des événements décrits dans le langage Pla (SCHOTTSTAEDT 1983). L’épaisseur des lignes correspondant à l’amplitude, il est impossible alors d’utiliser l’image pour reconstruire un son.
Les phonogrammes sont des graphes plans dont la dimension horizontale représente le temps et la dimension verticale représente les hauteurs des sons. Un trait horizontal dans ce graphe représente un son de fréquence fixe, plusieurs traits superposés représentent un accord. Toute image peut se décomposer en une juxtaposition de traits horizontaux et être interprétée comme un phonogramme.
L’implémentation des phonogrammes est conditionnée par le double but de représentation de sons et d’images. La structure des phonogrammes est proche des structures musicales telles les notes (événements possédant une amplitude, une durée, un instant de départ et une hauteur) et est directement exploitable en tant qu’image (les segments horizontaux les constituant possèdent leur valeur de gris et leurs coordonnées).
Afin d’expliquer le principe physique utilisé dans les phonogrammes, nous donnons en annexe un rappel de notions acoustiques (Dimensions Physiques des sons)
Dans les phonogrammes, nous utilisons une gamme tempérée microtonale, décomposant chaque demi-ton en 16 parties égales, décomposant ainsi l'octave en 12 x 16 = 192 intervalles.
Chaque ligne horizontale du phonogramme représente une fréquence.

où pitch est le numéro de la ligne (position verticale)
et 69 est le numéro du demi-ton correspondant à la note “la” 440.0 Hertz en notation MIDI.
12 est le nombre de demi-tons dans une octave.
et 16 est le nombre d'intervalles de notre échelle correspondant à un demi-ton.
Pour construire le signal sous la forme amplitude/temps à partir d'un phonogramme, nous effectuons une synthèse additive dont les composants ne sont pas en rapport harmoniques.
Le signal s(t) est une somme de sinus, chaque terme étant pondéré par un coefficient d’amplitude Ai(t) :
s(t) = A0(t) . sin ( w0 t + F0 ) + ... + An(t) . sin (wn t + Fn )
La fréquence angulaire, wi, de chaque terme peut s’écrire :
wi = 2πfi
Où la fréquence fi, se calcule à partir de la fréquence la plus grave, f0, correspondant à la fréquence de la première ligne, par le produit avec une puissance entière de e :
fi = f0 . e i
e correspond au pas de l’échelle microtonale utilisée (192 intervalles égaux dans une octave) :
e = 2 (1/192)
Les amplitudes Ai(t) sont fonction du temps pour rendre compte des enveloppes et de l'évolution du son au cours du temps. Elles sont représentées par les valeurs de gris des pixels du phonogramme.
La fréquence f0 est celle de la première ligne. les fréquences fi sont en progression géométrique, alors que les fréquences de la série de Fourier étaient en progression arithmétique.
Voici un exemple de signal (figure 2.1), produit à partir d’un rectangle dans un phonogramme. Le rectangle est composé de lignes couvrant les fréquences de 680 Hertz à 800 Hertz en allant par seizième de demi-ton. Les amplitudes sont constantes et égales. Toutes les phases Fi sont fixées à 0 au début.
Figure 2.1 : Signal produit à partir d’un rectangle dans un phonogramme.
Dans la vue globale, ci-dessus, des pics d’amplitude apparaissent régulièrement. Les pics sont séparés de 370 millisecondes (fréquence 2,7 Hertz).
Dans la vue de détail, ci-dessous, nous voyons nettement la variation d’amplitude : un phénomène de battement apparaît lorsque toutes les phases sont égales.

Figure 2.2 : Détail du signal de la figure 2.1
Dans l’exemple suivant, obtenu à partir du même phonogramme, les phases Fi sont fixées aléatoirement au début du processus, indépendamment pour chaque ligne.
Figure 2.3 : Signal produit par un rectangle, avec déphasage aléatoire.

Figure 2.4 : Détail du signal de la figure 2.3
Avec les phases aléatoires (figure 2.3 et 2.4), l’enveloppe est plus régulière, et l’effet des battements est nettement moins perceptible. Les battements sont toujours présents, mais l’importance relative des pics les plus élevés par rapport à l’amplitude moyenne est plus faible.
Nous traitons deux types de phonogrammes : les phonogrammes en noir et blanc, et les phonogrammes en niveaux de gris.
Nous détaillons maintenant différentes implémentations des structures supportant la mémorisation, le rappel, et la modification des phonogrammes.
Nous sommes familiers avec la décomposition des images en pixels[27] et la méthode de représentation d'une image[28], par un système de table :
En noir et blanc, chaque bit d'une zone mémoire contient l'information pour un pixel, avec une convention associant le noir à la valeur 1 et le blanc à la valeur zéro (ou la convention inverse).
La zone mémoire contiguë est déroulée de gauche à droite et ligne à ligne sur l'image. La mémoire, pour des raisons techniques[29], est préférentiellement découpée en mots (paquets de 8, 16, 32 bits), Lorsque la largeur de l'image n'est pas un multiple de la taille du mot, quelques bits sont ignorés à chaque fin de ligne, de manière à recommencer une nouvelle ligne au début d'un mot.
À l'intérieur d'un mot, ont peut utiliser les bits, du poids faible au poids fort, pour ranger les pixels, soit de gauche à droite, soit de droite à gauche.
Cette mémoire d'image est nommée bitmap.
Exemple d'accès en lecture à un pixel de l'image :
Image(x, y) =
(bitmap [ ((largeur + M - 1)//M)*y + x//M ] >> (x%M)) & 1
où M est le nombre de bits du mot, et largeur la largeur de l'image en nombre de pixels, // la division entière, % le reste de la division entière, & l'opération et logique (pour extraire le bit après l'opération de décalage des bits >>). La formule ((largeur + M - 1)//M) donne le nombre de mots par ligne.
Lorsque plus d'un bit par pixel est nécessaire pour encoder l’information de couleur, deux solutions se présentent : soit on forme autant de bitmaps (ayant la structure précédemment décrite) qu'il faut de bits par pixel (structure par plans de bits), soit on encode chaque pixels par le nombre de mots nécessaires (et on juxtapose les pixels). C'est cette seconde solution qui est la plus fréquemment retenue (l’information concernant un pixel n’est pas dispersée).
Nous allons maintenant voir les images d'une tout autre manière : à la loupe, l'image apparaît comme une collection (ordonnée et indéxée) de lignes. Chaque ligne de l'image est une entité indépendante des autres lignes (quelque soit l'image représentée). Disséquons une ligne à présent : au microscope, elle nous apparaît comme une succession de couleurs, mais souvent (en particulier dans les images en noir et blanc), la même couleur apparaît plusieurs fois de suite. Nous formerons donc une ligne en enchaînant des segments monochromes. Les lignes blanches ne contiennent aucun segment. En sélectionnant un meilleur grossissement sur notre microscope, nous discernons les composants d'un segment : l'abscisse de départ, l'abscisse de fin du segment, et (si l'image n'est pas uniquement noire et blanche) l'information donnant la couleur du segment.
Avec la lentille C (un filtre sur le microscope), la ligne est une structure donnant le nombre de segments alloués, le nombre de segments actifs, et un pointeur vers une table de structures segment. Les structures segment comprennent les champs x1, x2 pour mémoriser les abscisses de début et de fin du segment, et un champ pour mémoriser sa couleur.
Avec une lentille Smalltalk (GOLDBERG, ROBSON 1989) (LESBROS 1989), la classe Ligne possède une variable d'instance segment, (pour chaque ligne, la variable segment pointe vers le premier segment de la ligne). La classe Segment a ses variables d'instance x1 et x2 pour les abscisses et des variables suivant et précédant, pour indiquer les segments voisins dans la même ligne. Une sous classe SegmentColoré possède en outre l'information de couleur.
Les opérations à effectuer sur les images peuvent se décomposer en des opérations à appliquer sur des lignes.
Les opérations sur les lignes se résument à trois primitives :
• Copier tout ou partie d’une ligne.
• Intégrer un segment dans une ligne.
• Effacer un segment d’une ligne.
La copie d’une ligne est nécessaire pour assurer la possibilité d’annuler l’effet de toute action sur un phonogramme. Par exemple, quand on donne un coup de pinceau, on intègre de nouveaux segments dans le phonogramme, nous souhaitons permettre d’annuler le coup de pinceau (et pouvoir agir de même pour toute opération modifiant un phonogramme). Avant l’intégration d’un segment dans une ligne, ou avant l’effacement d’un segment, nous mémorisons une copie de la ligne (si elle n’est pas déjà copiée). Lors de l’annulation, nous permutons les lignes mémorisées avec les lignes actuelles. Ainsi, deux annulations successives restaurent l’état modifié. Avant chaque action considérée comme unitaire, nous libérons l’espace occupé par les copies.
La figure ci-dessous indique les treize positions relatives que peuvent prendre deux segments en considérant leurs bornes : nous devons distinguer les cas ou les bornes sont inférieures, égales ou supérieures. Le segment délimité par x1 et x2 en haut de la figure représente un segment existant dans le phonogramme, et les 13 positions représentent les positions d’un segment à intégrer ou à effacer.

Figure 2.5 : Positions relatives de deux segments
L’algorithme d’intégration n’est pas le même en noir et blanc et en niveaux de gris. En effet, la position 3 par exemple provoquera un allongement du segment à gauche en noir et blanc ou lorsque les niveaux de gris des deux segments sont égaux, alors qu’avec des niveaux de gris différents, le segment sera raccourci à gauche et un nouveau segment sera inséré. De même, dans la position 9, l’intégration en noir et blanc est immédiate, il n’y a pas de modification, alors que lorsque les niveaux de gris sont différents, le segment initial sera remplacé par trois segments adjacents.
Notons z1 et z2 les coordonnées du segment à intégrer.
La comparaison de la borne z1 avec x1 et x2 crée cinq cas :
a/ (z1 < x1) positions 1, 2, 3, 4, et 5
b/ (z1 = x2) positions 6, 7 et 8.
c/ (z1 > x1) et (z1 < x2) positions 9, 10 et 11.
d/ (z1 = x2) position 12.
e/ (z1 > x2) position 13.
La comparaison de la borne z2 avec x1 et x2 détermine (avec les cas précédents) la position du segment.
On traite les segments existants dans la ligne de gauche à droite. S’il n’y a pas de segment, ou si on doit continuer l’intégration à droite avec le segment suivant (positions 5, 8, 11, 12 et 13) et qu’il n’y a pas de segment suivant, on crée un nouveau segment.
Le terme insérer signifie créer un nouveau segment avant le segment courant. et le terme ajouter signifie créer un nouveau segment après le segment courant.
Le terme remplacer signifie que l’on conserve le segment et son niveau de gris, mais que l’on change une de ses bornes.
Lorsqu’on change le niveau de gris du segment dont la borne supérieure est égale à x2, (positions 4, 7, et 10), nous devons vérifier le niveau de gris du segment suivant : Si le niveau de gris est différent ou s’il n’y a pas de segment suivant, la vérification s’arrête. Si le niveau de gris est égal, le segment suivant doit être supprimé et le segment courant remplacé avec la borne supérieure du segment suivant, puis, la vérification se poursuit tant que le segment suivant est adjacent (x1 du suivant = x2 du segment).
Dans l’algorithme ci-dessous, les cas notés n&b signifient que le niveau de gris du segment à insérer est égal au niveau du segment courant, ou que le phonogramme est en noir et blanc. Le cas gris est à appliquer dans les autres cas.
1 : (z2 < x1)
insérer (z1, z2) avant (x1, x2)
2 : (z2 = x1)
n&b : remplacer (x1, x2) par (z1, x2)
gris : insérer (z1, z2) avant (x1, x2)
3 : (z2 > x1) et (z2 < x2)
n&b : remplacer (x1, x2) par (z1, x2)
gris : remplacer (x1, x2) par (z2, x2), insérer (z1, z2) avant (z2, x2)
4 : (z2 = x2)
n&b : remplacer (x1, x2) par (z1, x2)
gris : remplacer (x1, x2) par (z1, x2)
donner un nouveau niveau de gris.
vérification du niveau de gris à droite.
5 : (z2 > x2)
supprimer le segment (x1, x2)
continuer l’intégration avec le segment suivant à droite.
6 : (z2 < x2)
n&b : néant
gris : remplacer (x1, x2) par (z2, x2), insérer (z1, z2) avant (z2, x2)
7 : (z2 = x2)
n&b : néant
gris : donner un nouveau niveau de gris
vérification du niveau de gris à droite.
8 : (z2 > x2)
position traitée comme la position 5
9 : (z2 < x2)
n&b : néant
gris : insérer (x1, z1) avec le niveau de gris de (x1, x2),
insérer (z1, z2),
remplacer (x1, x2) par (z2, x2).
10 : (z2 = x2)
n&b : néant
gris : remplacer (x1, x2) par (x1, z1), ajouter (z1, z2)
vérification du niveau de gris à droite.
11 : (z2 > x2)
n&b : supprimer le segment (x1, x2)
remplacer z1 par x1
continuer l’intégration avec le segment suivant à droite.
gris : remplacer (x1, x2) par (x1, z1)
continuer l’intégration avec le segment suivant à droite.
12 : (z2 = x2)
n&b : traitement identique à 11.
gris : continuer l’intégration avec le segment suivant à droite.
13 : (z2 > x2)
continuer l’intégration avec le segment suivant à droite.
Les treize configurations[30] ci-dessus sont décrites dans l’article de ALLEN (ALLEN 1983) et citées dans (BARBAR 1995), elles portent sept dénominations :
Cas 1 : Z before X, cas 13 : X before Z
Cas 2 : Z meets X, cas 12 : X meets Z
Cas 3 : Z overlaps X, cas 11 : X overlaps Z
Cas 4 : X finishes Z, cas 10 : Z finishes X
Cas 5 : X during Z, cas 9 : Z during X
Cas 6 : Z starts X, cas 8 : X starts Z,
Cas 7 : Z equal X
L’intégration d’une image bitmap externe dans un phonogramme constitue une étape de vectorisation de l’image. En effet, notre représentation est intermédiaire entre les images bitmap et les images vectorielles. Les images vectorielles sont constituées d’une liste d’ordres d’appels de primitives graphiques avec leurs paramètres (par exemple tracé d’un cercle dont le centre est à telles coordonnées et de rayon tant, tracé d’un segment de droite de tel point à tel autre, tracé d’un rectangle ou d’un polygone). C’est cette représentation qui est utilisée dans les fichiers et images au format PICT[31] (Apple 1985).
Dans notre représentation l’image est vue comme une liste d’instruction de tracé de droites horizontales (ou de rectangles suivant l’échelle de visualisation).
Voici un exemple d’image vectorielle (figure 2.6), les éléments constitutifs de cette image sont indépendants, et peuvent être individuellement modifiés.

Figure 2.6
La réduction de cette image vectorielle produit ceci (figure 2.7) :

Figure 2.7
L’exemple de texte est remis en forme (par le programme) pour occuper moins de place, mais la fonte et le corps des caractères ont été conservés, toutes les entités constituantes sont tracées avec de nouvelles coordonnées. Les épaisseurs des lignes sont toujours d’un pixel.
En traduisant l’image en bitmap, puis en appliquant une réduction de l’image bitmap, certaines lignes ou points disparaissent (figure 2.8).

Figure 2.8
En traduisant l’image bitmap initiale en phonogramme, puis en réduisant le phonogramme, nous ne perdons pas de lignes ni de points (figure 2.9). Les éléments ne sont plus des cercles ni des rectangles ni du texte, mais des segments de droites horizontaux.
Les lignes verticales sont constituées de lignes horizontales juxtaposées. Les lignes horizontales (à gauche dans l’image) se placent sur le pixel le plus proche de leur position théorique. Toutes les lignes sont présentes. Le texte a été traité de la même façon et est réduit, à cette échelle. Il reste alors lisible.
![]()
Figure 2.9
En grossissant l’image provenant du phonogramme (figure 2.10), les segments de droites sont traduits automatiquement en rectangles sans autre perte d’information que l’identité de la structure initiale (les entités cercles, rectangle, etc.).
![]()
Figure 2.10
L’opération de conversion des bitmaps en phonogrammes est finalement une vectorisation simple, puisque, une fois la conversion faite, l’image complète est représentée par des segments de droites. Mais il n’y a évidemment aucune reconnaissance de formes géométriques. La traduction est triviale.
Lors de la visualisation, nous bénéficions tout de même de l’avantage de pouvoir afficher et modifier les phonogrammes à toutes les échelles (figure 2.11 et 2.12). En grossissant, chaque segment est représenté par un rectangle.

Figure 2.11 Échelle 1

Figure 2.12 : Échelle 5
La conversion vectorielle/bitmap est immédiatement réalisée par la bibliothèque graphique. Il suffit d’allouer un espace mémoire suffisant pour l’image en fonction de sa taille et de sa résolution, puis de bâtir un contexte graphique portant sur cette mémoire. Ensuite, toutes les opérations graphiques de la bibliothèque seront effectuées dans cette image au lieu d’être effectuées dans la mémoire vidéo.
Un principe similaire est utilisé pour générer les images au format PICT, telles que celles transmises dans le presse-papiers du Macintosh. En ouvrant un contexte graphique portant sur une mémoire représentant une image vectorielle (Picture), les opérations graphiques sont enregistrées en séquence dans cette image. Pour les images dépassant 32 Ko il est souhaitable de rediriger le vecteur[32] correspondant à l’écriture dans la mémoire de l’image pour écrire dans un fichier.
La possibilité de convertir des phonogrammes en bitmaps donne accès à toutes les possibilités offertes par les logiciels de traitement d’image.
Nous laissons la grande partie des traitements numériques des images aux applications externes, avec lesquelles nous pouvons toutefois communiquer. Le presse-papiers du Macintosh permet de transmettre des images vectorielles et bitmaps d’une application à l’autre. Nous pouvons également lire un format d’image standard (PICT). Le seul traitement que nous effectuons localement est la modification de valeur des phonogrammes en niveau de gris, ce qui correspond à une opération courante musicalement : la modification de la dynamique. Les opérations de copie et mixage de deux images sont également effectuées localement, mais ce ne sont pas véritablement des traitements d’images.
Mis à part les transformations spatiales des images, telles la sphérisation, les homotéties...., nous utilisons fréquemment une transformation proposée par le logiciel PHOTOSHOP : la facétisation : elle agit en fabriquant une mosaïque de facettes unicolores de formes diverses reproduisant globalement les intensités lumineuses de l’image originale.
Nous utilisons ce filtre pour simplifier les images produites par l’analyse de sons, ou pour simplifier les images provenant de digitalisation en niveaux de gris. La simplification obtenue étant la réduction du nombre de segments des phonogrammes pour un résultat globalement équivalent.


Figure 2.13
A gauche (figure 2.13), l’image originale, et à droite, l’image facétisée.
Si les traitements graphiques standard sont laissés aux soins d’autres applications, nous avons ressenti rapidement le besoin d’intégrer des outils graphiques correspondants à des opérations dans l’espace sonore, ou à des facilités pour construire des éléments sonores. Ces outils sont décrits dans le paragraphe suivant.

Figure 2.14 : Facétisation d’un son (Échelle 1 et 5)
Les premières expériences avec phonogramme ont été réalisées en dessinant les phonogrammes à la main, en utilisant des crayons, stylos, des plumes et de l’encre de chine. Les dessins sont digitalisés, puis intégrés dans les phonogrammes. Avec une résolution de 240 points par pouce, l’échelle des hauteurs complète tient dans la petite dimension d’un format A4, et nous avons à peu près une octave pour deux centimètres[33].

Figure 2.15 : Phonogramme (extrait de Phonographiques) réduit à 20% de la taille originale.
Les lignes tracées à la main ne sont pas rigoureuses, et il est délicat de tracer des lignes exactement en rapport harmonique par exemple ou encore à une distance verticale constante l’une de l’autre. Ceci est important pour que les sons produits se recomposent en un timbre. Si plusieurs lignes se superposent, sans conserver des écarts constants, plusieurs sons distincts sont perçus. Si a contrario, les lignes superposées conservent des écarts constants, un son complexe unique est perçu.

Figure 2.16 : Phonogramme (extrait de Phonographiques).
Pour tracer manuellement des lignes espacées d’écarts arbitraires ou correspondant aux distances entre les harmoniques, nous nous sommes inspiré des plumes utilisées pour tracer les portées des partitions. Ces plumes sont en forme de griffes et laissent cinq traces parallèles en un seul mouvement. Nous avons découpé des plumes diverses dans du carton (figure 2.17) en ménageant des pointes correspondant à chaque partiel du son à dessiner.

Figure 2.17 : Une plume en carton

Figure 2.18 : Détail d’une trace de plume en carton (les lignes sont pratiquement parallèles et l’épaisseur varie selon la pression).
Ce qui importe ici (figure 2.18) n’est pas le parallélisme des traits, mais la conservation des écarts verticaux entre les traits, les écart verticaux correspondant aux intervalles entre les sons.
![]()
Figure 2.19 : Phonogramme (extrait de Phonographiques) dessiné uniquement avec des plumes en carton.
Les traits laissés par les plumes en carton forment des accords ou des sons harmoniques, suivant les écarts. Les traits sont plus ou moins épais. Pour permettre de réaliser de tels tracés directement à l’écran, et en contrôlant exactement l’épaisseur et les écarts entre les traits, nous avons implémenté un pinceau à harmoniques.
Le pinceau à harmoniques permet de tracer automatiquement les harmoniques en traçant uniquement le fondamental. Dans la procédure intégrant un rectangle à un phonogramme, nous adjoignons deux paramètres donnant le nombre d’harmoniques à tracer et un mode de calcul de l’amplitude relative des partiels.
Les partiels peuvent avoir soit la même intensité que le son fondamental, soit l’intensité du fondamental divisé par le rang du partiel, soit encore l’intensité du fondamental divisé par le rang du partiel si le rang est impair ou une intensité nulle si le rang est pair.
Ces trois règles de calcul (figure 2.20) ont été choisie arbitrairement pour l’expérience, elles devraient être complétées, ou définissable par l’utilisateur. Par exemple à l’aide d’une courbe donnant l’amplitude relative en fonction du rang. Nous verrons dans la suite que le pinceau à timbres permet de définir des amplitudes relatives différentes ainsi que leur évolution au cours du temps.
Voici des exemples de tracés réalisés avec le pinceau à harmoniques :

Figure 2.20 : Les trois règles. Figure 2.21 La valeur augmentant.
Les traits peuvent être tracés avec une valeur constante, ou augmentant ou diminuant au cours du déplacement (figure 2.21).
Comme l’échelle des fréquences des phonogrammes est logarithmique, l’écart entre les partiels est constant quelque soit le fondamental. Nous précalculons donc une table donnant le nombre de pixels d’écart entre le fondamental et les partiels successifs. Au contraire, dans une échelle linéaire des fréquences (telle celle des sonogrammes), les écarts entre les partiels changent en fonction de la hauteur du son. Dans un phonogramme, nous pouvons copier un son harmonique ou complexe, et le transposer sans changer le rapport des fréquences, par une simple translation verticale.
Les distances inter partiels sont arrondies au seizième de demi-ton le plus proche. Seul le calcul des octaves est correct. Nous produisons donc des harmoniques tempérées au seizième de demi-ton.
Les expériences montrent que les sons produits sont perçus comme des sons uniques, le timbre seul étant affecté. En synthèse mixte, les seize synthétiseurs produisent des sons correspondant à leur échelle chromatique et l’addition des partiels est réalisée de manière analogique par la table de mixage.
Le pinceau à timbres permet d’utiliser un phonogramme en tant que source ou description de timbre pour tracer des sons dans un autre phonogramme.

Figure 2.22 : Phonogramme source (l’image source est basée à l’origine, la partie grisée est en dehors du phonogramme).

Figure 2.23 : Phonogramme destination.
L’image source (figure 2.22) est transférée dans la destination (figure 2.23) à chaque coup de pinceau, elle est déformée pour suivre les mouvements du pinceau.
L’image source peut contenir n’importe quel dessin, mais a priori, nous dessinons dans la source un seul son avec ses partiels, et les variations des partiels dans le temps, en amplitude, en épaisseur, en hauteur.

Figure 2.24
Voici un exemple (figure 2.24) de phonogramme source, en noir et blanc, nous avons épaissi les partiels correspondants au moment de l’attaque.
L’image source est transférée dans la destination colonne par colonne au cours du déplacement du pinceau. Si le pinceau se déplace de plus d’un pixel horizontalement, la colonne de la source est étirée pour atteindre le nombre de pixels correspondant. La colonne de la source subit une translation verticale correspondant à la position verticale du pinceau.

Figure 2.25
Ci-dessus (figure 2.25), des exemples de tracés du pinceau à timbres avec la source précédente (figure 2.24). Le pinceau peut se déplacer dans toutes les directions, la source sera contrainte à suivre les mouvements de celui-ci (le dernier son à droite est tracé en deux temps, de droite à gauche et de gauche à droite).
Si le déplacement du pinceau est rapide, la source est allongée, et la durée du son résultant sera plus grande.
Les valeurs de gris de la source peuvent être utilisées directement ou être mélangées (moyenne) avec la valeur de gris sélectionnée. Ceci permet d’utiliser la même source en faisant varier les amplitudes.
Nous avons introduit une option permettant de respecter l’échelle de visualisation ou non. C'est-à-dire que la source peut être intégrée dans la destination à la même échelle ou bien à l’échelle de visualisation courante. Ceci permet de grossir ou de réduire l’image source d’un facteur entier.

Figure 2.26
La figure 2.26 est un exemple de sons différents formés avec une source identique, les sons produits sont perçus comme ayant le même timbre, malgré les variations de durée et de hauteur. Les partiels de ce timbre sont en rapports harmoniques.

Figure 2.27
Dans cet exemple (figure 2.27), les sons sont également perçus comme ayant le même timbre, la source est une image où les partiels ne sont pas harmoniques.
Les mouvements de la souris sont difficiles à contrôler, par exemple, pour tracer des courbes ou des droites régulières. Nous avons créé un outil permettant de lisser les tracés effectués à la souris. Cet outil est basé sur l’utilisation des couplages élastiques.
La trace initiale est mémorisée sous la forme d’une liste de points. Puis une tension élastique est appliquée, entre les points consécutifs, comme pour la tension des trajectoires ou des trajets des flèches des schémas. Ensuite, la liste de points est parcourue, une droite est tracée avec le pinceau reliant chaque point de la liste.
Les droites sont tracées en utilisant l’algorithme de BRESENHAM (ROGERS 1988). Chaque point d’une droite représente un coup de pinceau prenant en compte la taille du pinceau, les harmoniques éventuelles, et l’activité des canaux[34]. Différentes règles de tension sont applicables sur le tracé initial et permettent d’obtenir des variations de la qualité du trait, ou de son allure générale.

a/ b/ c/ d/
Figure 2.28
Différentes règles de tension appliquées sur le trait sont présentées ci-dessus (figure 2.28) : la première (a) tend à lisser la courbe, les points du tracé initial sont déplacés dans le sens de la tension calculée d’après ses voisins. La seconde (b) introduit un vecteur supplémentaire dans le calcul de la tension, et ce vecteur effectue une rotation au cour du déplacement au long du trait, ceci produit des boucles si le tracé comporte beaucoup de points, ou des ondulations si le tracé initial est plus tendu, c'est-à-dire effectué plus promptement. La troisième image (c) est formée par l’application d’une règle de tension ajoutant un vecteur constant orienté vers le bas donnant un effet de poids. Enfin, la dernière image (d) est obtenue avec la règle suivante :
En chaque point, les tensions avec le point suivant et le point précédent sont calculées, si une des deux tensions est supérieure à un seuil donné (ou si les deux tensions sont égales au seuil), alors la tension est appliquée normalement c'est-à-dire, en provoquant le déplacement du point d’un pixel dans le sens de la tension, sinon, si l’une des tensions est inférieure au seuil, alors la tension opposée est appliquée. Ceci est calculé indépendamment en x et en y. Cette règle a pour conséquence de favoriser les segments orientés à 45 degrés par rapport aux axes.
La sélection des canaux permet de choisir une échelle des hauteurs dont le pas, compris entre le 32ème de ton et le demi-ton, est une puissance du demi-ton : 1/2, 1/4, 1/8 ou 1/16ème de demi-ton.
Nous avons adjoint un système permettant de masquer les lignes de phonogramme dont le numéro n’appartient pas à une classe résiduelle donnée d’un module donné. Par exemple : nous pouvons masquer toutes les lignes dont le reste de la division par 3 du numéro n’est pas égal à 2. Le module (3) et le reste (2) étant réglables dans l’interface.
Ceci permet d’utiliser tous les outils précédemment décrits, ainsi que toutes les fonctions d’analyse dont la description suit, en contraignant l’écriture dans une échelle microtonale régulière dont le pas est un multiple du seizième de demi-ton. Les masques agissant aussi bien sur les fonctions de dessin que sur la fonction d’effacement, nous pouvons les utiliser pour retrancher les notes appartenant à une échelle donnée d’une image existante.
Les outils décrits précédemment aident à construire de nouvelles images ou modifier des images existantes. Pour obtenir des images correspondant aux sons provenant du monde réel, nous avons besoin de fonctions d’analyse du son; pour produire les sons correspondant aux images, nous avons besoin de fonction de synthèse. Nous présentons ces fonctions dans les paragraphes suivants.
Nous présentons une adaptation de la Transformée de Fourier Discrète (TFD) pour la génération d'images de Phonogramme à partir de sons échantillonnés.
Les images de Phonogramme sont une représentation du son en trois dimensions : Le temps, sur l'axe des x, Les fréquences, sur l'axe des y, et enfin l'amplitude, représentée par des niveaux de gris, ou, simplement l'absence ou la présence d'énergie supérieure à un certain seuil, quand l'image est en noir et blanc.
Cette représentation est proche d'un sonogramme, mais, d'une part elle ne contient pas l'information de phase obtenue lors de l'analyse d'un son par une transformée de Fourier, et d'autre part, l'échelle des fréquences habituellement linéaire a été choisie logarithmique pour faciliter les correspondances entre les opérations graphiques et leurs contreparties musicales.
L’information de phase a souvent été décrite comme étant secondaire voire non significative (RISSET 1969) quant à la perception des timbres : Si l’on change la phase d’un partiel (ou de plusieurs partiels) lors de la synthèse additive, le son produit est perçu inchangé. Mais, les phases instantanées délivrées par la transformée de Fourier sont de nature différente[35], elles sont nécessaires à la reconstitution exacte du son analysé, comme montrent ARFIB et DELPRAT (ARFIB 1993-95) qui proposent également un système de représentation du son dans l’espace fréquence/temps mais démontrent l’importance de la phase en effectuant des transformations sonores modifiant uniquement les phases.
Les deux procédés que nous avons élaborés pour faire la synthèse du son à partir de ces images régénèrent des phases arbitraires pour chaque partiel : le procédé temps réel, fonctionnant par commande de modules de synthèse externes ne contrôle pas assez finement le temps (limitation du protocole MIDI), et ne dispose pas de commande permettant de spécifier les phases, et le procédé de synthèse directe, qui propose deux modes de génération des phases : toutes les phases synchronisées à zéro au premier pixel, ou un déphasage aléatoire choisi pour chaque fréquence, puis conservé tout au long du traitement.
Cette information de phase n'est pas conservée dans notre représentation car des sons identiques quant aux fréquences des partiels, et synthétisés avec un réglage des phases différent sont perçus comme étant similaires.
Dans certains cas, pourtant, la phase est une information importante, notamment sur les attaques des sons instrumentaux (dans les transitoires). Les effets des variations de phase sont particulièrement sensibles si, par exemple, tous les partiels se voient attribuer une phase différente à un instant précis au cours du son, la perception du timbre est alors modifiée.
Les déphasages aléatoires ont étés introduits dans le procédé de synthèse pour contrecarrer les effets des battements dus à la proximité des fréquences : lorsque tous les partiels sont en phase au départ, les battements provoquent des pics d'amplitude réguliers nettement perceptibles, et d'une grande importance par rapport à l'amplitude moyenne, par contre, avec des phases attribuées au hasard, les conjonctions sont rares, et les pulsations parasites disparaissent.
La synthèse additive est la méthode de synthèse nous paraissant la plus primitive, ou fondamentale. Elle est limitée, dans son exploitation informatique, par le nombre d’oscillateurs à simuler pour produire les sons complexes (SNELL 1977), mais elle ne l’est pas, théoriquement, quant aux classes de timbres qu’elle permet de produire. Quand on définit les timbres simplement en termes d’amplitudes relatives de partiels harmoniques, la classe de timbres produite est restreinte aux seuls sons harmoniques et périodiques, mais si les oscillateurs peuvent être commandés par des enveloppes d’amplitudes dynamiques, et que les fréquences ne sont pas limitées aux fréquences harmoniques, toutes les classes de timbres deviennent accessibles. La puissance des ordinateurs augmentant, cette méthode de synthèse devient exploitable avec plus de souplesse. Un système actuel de génération de timbres, SeaWave, utilise la synthèse additive (ETHINGTON 1994) préférentiellement à d’autre méthodes de synthèse telles la synthèse granulaire (ROADS 1978) ou la synthèse par modulation de fréquence (CHOWNING 1973) (CHOWNING 1986) (HOLM 1992). Pour générer les timbres d’orgue, COMERFORD utilise également la synthèse additive. Il compare la synthèse additive avec l’utilisation de banques de sons échantillonnés (COMERFORD 1993) dans le but de la reproduction fidèle de timbres instrumentaux.
La synthèse additive décrite ici est la conversion des phonogrammes en signal amplitude/temps. Globalement, l'algorithme est très simple, mais certains détails techniques méritent une description.
À chaque ligne du phonogramme correspond une fréquence particulière, donnée par la formule suivante :

Chaque ligne du phonogramme est composée d'une suite de segments, chaque segment comportant la coordonnée de départ (x1), la coordonnée de fin (x2) et une valeur proportionnelle à l'amplitude pour les phonogrammes en niveaux de gris.
phonogramme [ y ] = ligne
ligne = (segment 1, segment 2, ... , segment n)
segment i = { x1, x2, gris } | { x1, x2 }
La conversion est effectuée pour une valeur donnée de la vitesse d'interprétation de l'image en millisecondes par pixel. Connaissant également la fréquence d'échantillonnage souhaitée, nous pouvons calculer le nombre d'échantillons correspondant à une colonne de pixels, ainsi que le nombre total d'échantillons à produire pour la section d'image à convertir.
Chaque segment du phonogramme représente un son périodique de durée et d'amplitude déterminés qu'il faut additionner au résultat. Le son doit débuter par une attaque, se maintenir, puis choir. Nous avons choisi une enveloppe la plus simple possible : l'attaque correspond au premier pixel du segment, et la chute débute au dernier pixel et les pentes d'enveloppes sont linéaires. Dans le cas d'un segment représentant un unique pixel, nous avions dans une première implémentation (en noir et blanc) condensé l'attaque et la chute dans la durée du pixel, mais pour simplifier les formes d'enveloppes résultant de l'addition de plusieurs segments mono-pixels consécutifs en niveaux de gris, nous avons opté pour une attaque pendant la durée du pixel suivie par une chute pendant la durée du pixel suivant.

Figure 2.29
Le schéma ci-dessus (figure 2.29) représente une ligne constituée de trois segments consécutifs (en haut, le premier segment en gris moyen, le second en noir et le troisième en gris clair). En dessous, nous avons tracé les enveloppes de chaque segment, puis l’enveloppe du son résultant de la somme des trois.
La forme de l'enveloppe influe sur le son, le timbre est modifié par le choix de la courbe suivie par l'enveloppe d'amplitude. Ceci pour les mêmes raisons que celles qui déterminent les fenêtres des fonctions d'analyse.
Les fréquences parasites apparaissent surtout à la jonction des segments linéaires de l'enveloppe quand l'angle formé est trop fort. En fait, d'après la règle de construction de l'enveloppe décrite ci-dessus, cet angle est déterminé par l'amplitude du segment de phonogramme et la vitesse en millisecondes par pixel. Il ne nous a pas semblé nécessaire, aux vue et ouie des résultats d'affiner ce point.
Pour éviter des appels constant à une fonction sinus, il est nécessaire de mémoriser dans une table une période de la fonction (ou un quart de la période en utilisant les symétries). Ceci permet également de changer la période de base sans changer le code.
Le problème principal est de savoir trouver, en fonction du temps, de la fréquence à produire et de la taille de la table d’onde, l’indice de l’échantillon à prendre dans la table.
Par exemple, si la fréquence d’échantillonnage est 22000 Hertz, et que la table d’onde a une longueur de 16000 échantillons, la fréquence produite en recopiant les échantillons de 1 en 1 sera de 22000 / 16000 = 1,375 Hertz. En prenant un échantillon sur 10, nous obtiendrons 13,75 Hertz, etc.
En prenant 1 échantillon sur n, nous obtenons toutes les fréquences harmoniques de la fréquence de la table d’onde. Si n n’est pas un multiple de la longueur de la table, il faut faire comme si la table était circulaire pour éviter les ruptures dans le signal (opération modulo sur l’indice).
Mais les fréquences à produire ne sont pas forcément des harmoniques de la fréquence de la table. Pour produire ces fréquences intermédiaires, il faudrait pouvoir prendre des valeurs entre les échantillons de la table. Une méthode d’interpolation serait envisageable, mais ces calculs nous ont semblés trop lourds. Nous avons préféré construire une approximation du rapport entre la fréquence à reproduire et la fréquence de la table par une fraction, puis écrire un algorithme calculant en entier, utilisant le numérateur et dénominateur de cette fraction ainsi que les propriétés de l’arithmétique modulaire.
Algorithme de calcul en entier pour trouver les échantillons dans la table d’onde
Constantes pour tout le phonogramme :
length_wave_buffer = 16K (16384 échantillons dans la table d’onde)
wave_buffer_frequency = sample_rate / length_wave_buffer (valeurs réelles)
Pour chaque ligne :
ratio = line_frequency / wave_buffer_frequency
±= num / den
(num et den sont des entiers qui approchent la valeur de ratio)
length_den = length_wave_buffer * den
Pour le premier échantillon :
moduleNum = (sample modulo length_den) * num
Pour chaque échantillon suivant :
value = wave_buffer[(moduleNum / den) modulo length_wave_buffer]
moduleNum += num
if(moduleNum == length_den) moduleNum = 0
L’opération modulo length_wave_buffer est réalisée par un ET logique car length_wave_buffer est une puissance de deux.
Ensuite la valeur obtenue est modifiée par le coefficient d’amplitude donné par l’enveloppe, puis elle est ajoutée à la valeur de la mémoire du signal.
Comme les fréquences des lignes de phonogramme sont constantes, nous précalculons la table des fractions. Cette table n’est recalculée que si l’on souhaite désaccorder, en donnant une nouvelle fréquence pour le la[36].
Nous avons développé cet algorithme indépendamment des techniques habituelles utilisant l’incrémentation d’un registre de phase par une valeur en correspondance avec la fréquence. La partie haute du registre de phase indexant la table d’onde (SNELL 1977). Notre système demande une division supplémentaire (la division de moduleNum par den) mais donne une approximation de la fréquence plus précise.
Les techniques de traitement du signal ne sont pas développées particulièrement dans l'atelier AIME. Les seuls traitements appliqués directement sur les signaux sous la forme échantillonnés sont la mise à l'échelle et la fusion de deux fichiers monophoniques en un fichier stéréophonique. La mise à l’échelle (scaling), permet, par le simple produit de chaque échantillon par un coefficient, de ramener l'amplitude de crête à la valeur maximale autorisée par la définition du format. Cette opération est faite sur fichiers d'échantillons 32 bits produits par l'algorithme de synthèse additive, par la simulation de couplages élastiques, ou par l'exécution d'une trajectoire, pour les ramener au format 16 bits. L'algorithme de synthèse écrit les échantillons sur 32 bits, en mémorisant l'amplitude maximale (en valeur absolue), puis nous effectuons cette opération en lisant et écrivant dans le même fichier. La structure des fichiers d'échantillons le permet, car ils sont composés d'une entête suivie par la séquence d'échantillons. Comme la taille des nouveaux échantillons est plus petite (ou égale dans le pire des cas) à celle des échantillons à lire, le chevauchement entre la position d'écriture et celle de la lecture est impossible[37].

Figure 2.30
Le fichier est éventuellement tronqué à la fin de l'opération.
Nous utilisons le format AIFF (Audio Interchange File Format) le standard Macintoch pour le stockage des sons échantillonnés. Ceci a l'avantage de permettre les échanges inter-applications, de profiter d'outils standards pour la génération des entêtes des fichiers, de garantir la compatibilité ascendante, et enfin d'utiliser toutes les routines spécialisées du SoundManager qui permettent l'enregistrement (prise de son direct to disk), l'exécution (émission sur la sortie audio), la compression, etc...
Par contre, nous avons dû programmer les routines nécessaires à la lecture de tels fichiers (décodage des entêtes et localisation des blocs de données), de manière à être en mesure d'accéder simplement aux échantillons. Nous ne reconnaissons pas actuellement toutes les possibilités offertes par le standard, mais les plus courantes sont traitées, et en particulier celles que nous générons.
Au cours du travail d'un timbre ou d'un son particulier, la visualisation du signal sous la forme amplitude/temps peut apporter de l’information, nous l'avons utilisée en particulier pour contrôler la production des algorithmes de synthèse. Mais cette visualisation n'est généralement pas très intéressante dans le travail de composition. Elle l'est dans certains cas, pour avoir une vision précise dans le temps d'une partie du signal, ou au contraire pour avoir une vue globale de l'enveloppe (vue en réduction). Par contre elle est imprécise dans la dimension des amplitudes (les amplitudes d'un signal 16 bits varient entre -32768 et 32767 alors que la hauteur de l'écran de visualisation est de l'ordre du millier de pixels).
Les problèmes d'échelle se posent également dans la dimension temporelle. Dès que le signal dépasse le dixième de seconde, l'échelle doit être réduite pour en voir la totalité, et l’on doit choisir entre le détail ou l'ensemble. Cela prend du temps par exemple pour localiser une discontinuité dans le signal (glitch), car elles ne sont visibles qu'à l'échelle 1, tout en produisant un effet sonore nettement perceptible et désagréable.
Nous déléguons la visualisation du signal à d'autres applications qui permettent de surcroît l'édition, quelques manipulations élémentaires, et certains traitements ou analyses avec des techniques standard.
Les accès disque pour la lecture ou l'écriture des fichiers d'échantillons sont étagés sur trois niveaux :
• Un premier niveau (nommé disque) permet d'encapsuler les appels aux routines standard du Macintosh (pour le choix des fichiers par l'utilisateur, l'ouverture, la fermeture des fichiers, etc...), de manière à être plus facilement portable dans d'autres environnements. Les routines de ce niveau sont utilisées dans d'autres modules accédant aux fichiers.
• Un second niveau (nommé flux) joue un rôle similaire aux Streams de Smalltalk, il gère une mémoire tampon pour limiter les accès disques.
• Le dernier niveau (nommé fluxAIFF) spécialise les flux pour le format AIFF.
Nous proposons deux façons de passer d’un phonogramme vers la norme MIDI :
1/ En exécutant le phonogramme, c’est-à-dire en déclenchant le jeu par l’émission d’un flux MIDI.
2/ En générant un fichier MIDI, ce qui correspond à l’enregistrement du flux MIDI associé à de l’information temporelle.
Chaque segment du phonogramme est traduit en une note : Le début du segment (x1) correspond à l’émission d’un message Note On[38], et la fin du segment (x2) correspond à l’émission d’un message Note Off[39] pour la même hauteur. Ces messages contiennent l’information de canal MIDI sélectionnant un instrument (calculé par l’opération modulo 16 appliquée au numéro de ligne de phonogramme), l’information de hauteur (numéro de demi-ton) étant ici le reste de la division du numéro de ligne par 16, et enfin la vélocité (ou intensité) donnée par le niveau de gris du segment (ou par une variable globale si le phonogramme est en noir et blanc).
Pour envoyer les messages MIDI nous utilisons le système de gestion d’événements de MIDIShare (cf. § Interface MIDI, le Système MIDIShare). Les événements de MIDIShare sont des structures typées et datées, contenant toute l’information à transmettre dans le message MIDI. Une note est émise en créant un événement, en renseignant ses champs, puis en appelant la routine d’émission. La date à laquelle l’événement doit physiquement être émis peut être postérieure à la date d’émission logique de l’événement : MIDIShare réorganise automatiquement les événements selon leur date.
Nous pouvons ainsi précalculer tous les messages MIDI correspondant à la section de phonogramme à jouer : c’est la première forme d’exécution. Quelques secondes (ou quelques dixièmes de secondes) sont nécessaires pour préparer et envoyer les événements. Il est impossible alors d’arrêter l’exécution du phonogramme[40].
Une deuxième forme d’exécution consiste à traiter le phonogramme par tranches temporelles successives. Pour chaque tranche, toute la hauteur du phonogramme est parcourue, et les segments des lignes débutant dans cette tranche sont traduits en événements. La structure décrivant une ligne de phonogramme contient un champ qui permet de mémoriser le numéro du dernier segment traité, de manière à optimiser le temps de recherche des segments. Le calcul d’une tranche est effectué sous interruption, par la routine Métronome appelée regulièrement à chaque terminaison d’une tranche temporelle. L’avantage de cette seconde forme d’exécution est la possibilité d’arrêter l’exécution à chaque tranche. L’inconvénient est le risque d’imprécision temporelle due au fait que l’horloge de MIDIShare s’arrête tant qu’une routine d’interruption s’exécute. Dans la première forme, en effet, toutes les dates d’émission sont respectées, car, le programme principal, générant les événements est interrompu par l’exécution de la routine d’émission des événements (de priorité plus forte). Dans la deuxième forme, au contraire, la génération des événements possède le même niveau de priorité que leur émission, et un décalage peut apparaître. Ce décalage est surtout sensible sur des machines de faible puissance de calcul, ou lorsque la densité du phonogramme est grande. Le résultat perceptible étant une suspension des sons durant le calcul de chaque tranche, suivie par l’émission précipitée de tous les événements suspendus au début de chaque tranche.
La conversion de flux MIDI en signal audio est réalisée par les synthétiseurs externes. Le point critique pour nous dans cette opération est le goulet d’étranglement engendré par la vitesse de transmission fixée par le norme MIDI à 31250 bauds. En effet, le programme générateur des événements MIDI parvient à saturer les synthétiseurs dès que la densité de l’image dépasse un certain seuil : 2 ou 3 octets sont nécéssaires (suivant le contexte) pour envoyer un message de début ou de fin de note. Chaque octet est transmis sur 10 bits, donc nous ne pouvons dépasser le millier de messages par seconde. Nous émettons 8 canaux sur un premier port de sortie, et les 8 autres sur un second port[41]. Les modules de synthèse externes reçoivent donc chacun un flux destiné à huit modules, et il doivent sélectionner dans le flux d’une part les messages qui leur sont spécifiquement adressés (par un numéro de canal sur 4 bits contenu dans le message), et d’autre part les messages système destinés à tous les modules. Une solution envisagée est de créer un module matériel pour effectuer la séparation des canaux MIDI, et insérer ce module entre l’ordinateur et les synthétiseurs.
La solution actuelle, pour limiter l’étranglement, consiste en la répartition de toutes les notes correspondant à une colonne de pixels sur la durée totale correspondant à la colonne, par l’ajout d’un délai aléatoire (entre 0 et le nombre de millisecondes par pixel) au temps calculé pour le départ de la note soit :
t = ts + ((s->x1 - xd) * mspp) + aléatoire(0, mspp - 1)
où : t est l’instant de départ du segment s.
ts : est l’instant de départ de la section à jouer.
s->x1 la coordonnée horizontale du segment s.
xd : la coordonnée horizontale de la section à jouer.
mspp : la vitesse d’exécution en millisecondes par pixel.
Ceci peut être considéré comme étant l’équivalent MIDI du déphasage aléatoire utilisé dans l’algorithme de synthèse directe, la différence étant la durée du décalage temporel : dans le cas de la synthèse directe liée (inversement proportionnelle) à la fréquence, et dans le cas MIDI, liée à la vitesse d’éxecution.
La seconde façon de transformer un phonogramme en notation MIDI agit de manière similaire à la première, mais au lieu d’émettre les notes, celles-ci sont rangées dans un fichier ; soit canal par canal, soit tous canaux confondus suivant le format MIDI souhaité (format 0 ou 1). Dans le fichier, une indication temporelle (time stamp) est associée à chaque message MIDI.
Pour obtenir le contenu spectral d’un son au cours du temps, c’est-à-dire le sonogramme (constitué du succession de spectrogrammes), on emploie habituellement l’algorithme de transformée de Fourier rapide (FFT : Fast Fourier Transform) (SOIZE 1993) (BRACEWELL 1986).
Notre première approche a donc été d'utiliser l'algorithme de transformée de Fourier rapide appliqué à une fenêtre (rectangulaire) se déplaçant tout au long du signal à traduire, avec un pas de déplacement correspondant à la durée représentée par un pixel (une colonne de pixels) de l'image.
La première difficulté a été de trouver la règle permettant de faire correspondre les niveaux de gris (valeurs entières comprises entre 0 et 126), représentant des vélocités de notes MIDI, et les modules des nombres complexes résultant de la transformée, représentant les amplitudes. En effet, chaque fenêtre contient une tranche du signal qui a son énergie propre, et avant d'avoir analysé tout le signal, nous ne pouvons pas connaître l'énergie maximale.
Si nous appliquions les méthodes classiques d’analyse du signal telles qu’elles sont appliquées pour la reconnaissance vocale par exemple, nous calculerions simplement les extremums des modules indépendamment pour chaque position de fenêtre analysée, et nous assignerions la valeur de gris maximale aux valeurs de module maximales. Mais ceci, bien que plus simple à implanter, donne des images à rayures verticales, dues à la différence d’énergie d’une fenêtre à l’autre.
Pour obtenir une continuité horizontale dans l’image, il faut que la correspondance entre les modules et les valeurs de gris soient la même pour toutes les positions prises par la fenêtre. Malheureusement, avant l’analyse effective, nous ne savons pas quelles seront les valeurs extrêmes des modules. Une solution consisterait à conserver tous les résultats sous forme de module jusqu’à la fin du traitement, puis, d’effectuer la correspondance d’après les extremums de l’ensemble. Nous n’avons pas retenu cette solution pour deux raisons :
D’une part l’espace nécessaire au traitement eut été trop important, d’autre part, nous préférions une solution où les résultats se forment progressivement sur l’écran pendant le traitement, pour que l’utilisateur puisse connaître l’état d’avancement du processus.
Nous parcourons l’ensemble des échantillons à traiter, pour déterminer les extremums d’amplitude, ce qui permet ensuite de normaliser le signal, c’est-à-dire amener les amplitudes entre -1 et 1, avec le même facteur pour tous les pas (toutes les positions de fenêtre).
Pour chaque pas, nous calculons l’énergie du signal
, puis après
l’application de la FFT, nous calculons l’énergie spectrale
nous
obtenons enfin la correspondance recherchée par :

Les résultats obtenus sont exploitables musicalement, les sons vocaux, analysés par cette méthode puis reconstitués par synthèse additive différée sont reconnaissables. On reconnaît la voix, et le locuteur. Mais le son est perceptiblement transformé. Une sorte de granularité apparaît dans le timbre.
Le signal étant échantillonné à la fréquence Fe, la réponse de
FFT est un spectre harmonique dont la fréquence fondamentale est donnée par
, où N est la
puissance de deux représentant le nombre d’échantillons de la fenêtre.
Donc, les réponses sont données pour des fréquences multiples de
.
D’autre part, lorsqu’on augmente la précision fréquencielle, la précision temporelle diminue et inversement.
Or nous voulons obtenir des réponses pour la totalité des lignes des phonogrammes dont les fréquences sont données par :
fi = f0 . e i
e = 2 (1/192)
où f0 représente la fréquence de la première ligne, ceci conduirait à l’utilisation d’une précision fréquencielle maximale, imposant une perte totale de précision temporelle, et l’utilisation de fenêtres d’une taille interdisant les manipulations en mémoire.
En utilisant des valeurs raisonnables (de l’ordre de 212 à 214) pour la taille des fenêtres, le résultat de la FFT est une image constituée de lignes horizontales séparées par des espaces importants dans les basses fréquences, et allant en diminuant vers les hautes fréquences.
Le résultat graphique n’est donc pas satisfaisant, et cela est dû à l’incompatibilité entre les échelles de fréquences harmoniques délivrées par la FFT, et l’échelle microtonale des phonogrammes.

Figure 2.31 : Transformée de Fourier Rapide dans un phonogramme
Ceci (figure 2.31) est le résultat de l’analyse par la transformée de Fourier Rapide, avec une vitesse de 10 millisecondes par pixel de la phrase “parmi des milliers d’étoiles...”. On observe principalement le resserrement des harmoniques vers les fréquences aiguës. Cette figure est à comparer avec celle obtenue par notre système de transformée élastique, pour le même échantillon sonore (figure 2.32).

Figure 2.32 : Résultat de la transformée élastique (cf. chapitre suivant), même échantillon sonore, même vitesse de 10 millisecondes par pixel. Les réglages du banc de résonateurs étaient de 0.995 pour la viscosité, de 5 pour le seuil d’activité, et 8 pour le seuil d’affichage. Le coefficient d’amplitude a varié de 7.10-11 à 5.10-11. La différence entre le seuil d’activité et le seuil d’affichage étant trop faible, on aperçoit, sur les attaques, les lignes correspondant aux résonateurs insomniaques.
Pour obtenir des réponses dans la gamme de fréquences correspondant à l’échelle microtonale des phonogrammes, nous sommes donc revenus à l’étape antérieure à la FFT, en utilisant la transformée de Fourier discrète :


représente la fréquence
angulaire.
La fréquence correspondante est
.
La formule permet d’obtenir les réponses pour N intervalles égaux entre -Fe/2 et +Fe/2.
N est le nombre de réponses fréquencielles et M la taille de la table d’échantillons.
En remplaçant eiw par cos(w) + i sin(w) et en calculant indépendamment les valeurs réelles et imaginaires, nous pouvons obtenir la transformée pour n’importe quelle fréquence entre -Fe/2 et +Fe/2, avec toujours, une précision dépendant de la longueur de la fenêtre.
Nous précalculons un peigne de fréquences correspondant aux fréquences des lignes de phonogrammes. Les fonctions sinus et cosinus sont précalculées également dans des tables.
Transformée de Fourier adaptée à un peigne de fréquences non harmonique :
• Pour chaque ligne :
*(peigne + ligne) =
TailleTableSinus * fréquence(ligne)
/ FréquenceEchantillonnage.
Le pas d’avance de la fenêtre doit correspondre à une colonne de pixels de l’image :
PasDAvance = FréquenceEchantillonnage
* NombreDeSecondeParPixel ;
• Pour chaque position de fenêtre
• Pour chaque fréquence du peigne (indéxée par ligne)
Initialisation à zéro de la somme (partie imaginaire et réelle)
somme.reel = somme.image = 0
• Pour chaque échantillon m de la fenêtre :
l’index dans la table des sinus et cosinus est la valeur du peigne multiplié par l’indice de l’échantillon (m) modulo la longueur de la table de sinus.
index = fmod(*(peigne + ligne) * m,
TailleTableSinus)
Si l’index est négatif, on ajoute la taille de la table.
Nous pouvons maintenant calculer les sinus et cosinus :
expon.reel = *(tableCos + index)
expon.image = *(tableSin + index)
Faire le produit par la valeur d’amplitude de l’échantillon :
expon.reel *= *(signal + m)
expon.image *= *(signal + m)
Puis cumuler le résultat dans la somme :
somme.reel += expon.reel
somme.image += expon.image
• Fin de boucle sur m
Calcul du module :
module = sqrt (somme.reel * somme.reel
+ somme.image * somme.image)
Le module est rangé dans la table de résultats à l’index correspondant à la fréquence. La phase n’est pas utilisée.
• Fin de boucle sur ligne
• Fin de boucle sur les fenêtres
Les résultats obtenus sont conformes à ceux attendus, les images ont un aspect continu, nous n’avons plus de manques (de lignes vides), et le procédé de calcul de l’énergie est toujours applicable pour obtenir une continuité horizontale. Mais le temps de calcul est rédhibitoire.
La taille de la fenêtre d’analyse peut couvrir un temps supérieur à la durée correspondant à un pixel, dans ce cas, les fenêtres se chevauchent, et une optimisation est possible. Mais ce n’est pas toujours le cas (suivant la précision d’analyse et la vitesse en millisecondes par pixel). Une machine parallèle serait mieux adaptée à ce traitement, puisque les calculs sont indépendants pour chaque ligne.
Cet échec nous a orienté vers d’autres procédés d’analyse[42], par exemple chercher une possibilité physique (matérielle) d’analyse (prisme sonore, cf § Analyse acoustique directe), ou encore le procédé que nous nommons la transformée élastique qui sera finalement retenu.
L’organisation temporelle est primordiale dans l’écriture d’algorithmes de génération musicale. La représentation par phonogramme possède une relation très simple avec le temps : Une longueur correspond à une durée. Il suffit de spécifier une vitesse d’exécution, et l’interprétation temporelle des éléments graphiques est déterminée.
Mais ceci ne fait que reporter dans la structure de l’image le problème de l’organisation temporelle de la pièce. Le programme n’effectue qu’une simple multiplication pour chaque extrémité de segment du phonogramme, le compositeur, graphiste, doit composer, décomposer, structurer et organiser le temps.
Nous présentons dans ce chapitre le système de marquage des sections temporelles des phonogrammes et notre système de schémas d’organisation temporelle.
Pour repérer des sections temporelles précises dans les phonogrammes, nous avons donné la possibilité de placer des marques dans la marge de pied des fenêtres de phonogrammes, flottant au dessus des graduations. Lors d’un déplacement d’une marque, une ligne verticale indique précisément la position de la marque par rapport à l’ensemble de la fenêtre. Les marques sont identifiées par des lettres et sont créées et détruites par couple (marque de début et de fin de section).

Figure 2.33 : Exemple de phonogramme avec deux couples de marques a et b.
Les marques servent à définir, par exemple, la section à traduire en fichier MIDI ou la section à synthétiser. Les marques servent également d’interface pour déclencher l’exécution de la section.
En dessinant, plaçant des marques, et déclenchant l’exécution de sections, qui peuvent être exécutées en parallèle, nous pouvons improviser avec des phonogrammes. L’exécution étant traitée par interruption, elle ne bloque pas l’usage des outils graphiques[43].
Pour permettre une planification abstraite et automatiser l’enchaînement des sections temporelles des phonogrammes, nous avons conçu un éditeur de graphes provoquant le déclenchement des sections marquées. Nous désignerons ce type de graphe par le terme schéma. (figure 2.34)

Figure 2.34 : Exemple de schéma permettant le déclenchement des marques a et b.
Les schémas sont constitués de cellules et de flèches reliant les cellules.
Les cellules et les flèches possèdent des réflexes graphiques simplifiant leur création, leur manipulation et leur destruction.
Les cellules possèdent un pointeur vers la cellule qui les englobe. Les cellules principales du schéma n’ont pas de cellule englobante. Chaque cellule possède un chaînage contenant les références vers ses sous-cellules, un autre chaînage vers les flèches partant de cette cellule, et un dernier chaînage contenant les références vers les flèches incidente à cette cellule (figure 2.35). Tous les chaînages sont bidirectionnels pour simplifier l’écriture des fonctions de manipulation du graphe.
Les cellules possèdent enfin des données indépendantes de la structure du graphe : le texte et les coordonnées du cadre de la cellule. Et l’information concernant la gestion du temps et les mécanismes que nous décrirons ci-après.
Cellule :
Cellule englobante
Sous-cellules
Flèches partantes
Flèches incidentes
Texte
Cadre
Information temporelle
Mécanismes
Figure 2.35
Flèche :
Cellule origine
Cellule arrivée
Point origine
Point arrivée
Trajet de la flèche
Mécanismes
Figure 2.36
Les flèches (figure 2.36) possèdent un pointeur vers la cellule d’origine, et un pointeur vers la cellule d’arrivée, elles connaissent les coordonnées des points de l’origine et de l’extrémité ainsi que tous les points du trajet de la flèche mémorisés dans un double chaînage.
Les cellules peuvent s’emboîter les unes dans les autres, elles détectent la relation d’inclusion (dans le schéma ci-dessus, figure 2.34, la cellule b est emboîtée dans une autre). Les cellules sont représentées par des rectangles dont les cotés sont parallèles aux axes verticaux et horizontaux (rectangles droits). Si une cellule est déposée ou créée à l’intérieur d’une autre, elle apparaîtra au dessus de sa cellule englobante[44].

Figure 2.37
La relation d’inclusion des cellules n’est pas la relation mathématique d’inclusion des rectangles des cellules. Dans le schéma ci-dessus (figure 2.37), le rectangle de B est inclus à la fois par le rectangle de A et de E, mais l’historique des créations et déplacements a une influence, et une cellule ne peut être incluse que dans une seule cellule englobante. Ce schéma pourrait être formulé par l’expression E, A(C(D), B). L’inclusion des cellules définit une relation d’ordre partielle. Le graphe d’inclusion est toujours un arbre dont la racine est le schéma.
Toutes les cellules englobées se déplacent lorsque la cellule englobante est déplacée (en déplaçant A on déplace B, C et D de la même translation). Mais, à l’inverse, si l’on déplace une cellule englobée, on peut la faire sortir de sa cellule englobante (en déplaçant C on emmène D mais A et B restent en place).
Les cellules d’un même niveau d’imbrication sont tracées dans un ordre qui est modifié lors d’un déplacement ou d’un changement de taille d’une cellule. La dernière cellule déplacée ou modifiée apparaît devant (comme la cellule A apparaît devant E dans le schéma).
Chaque cellule peut contenir un texte (ici les lettres désignant les cellules, mais le texte est limité à 32K caractères).
Pour créer une cellule, il suffit de faire une trace formant une boucle avec le pointeur de la souris en gardant le bouton enfoncé. Dès que l’on relâche le bouton, près de la position d’origine, une nouvelle cellule est créée dont le cadre est le plus petit rectangle droit contenant tous les points du trajet du pointeur de la souris. Un double clic est un cas particulier de trajet (à un seul point) formant une boucle, le double clic déclenche donc la création d’une cellule ayant la taille minimale attribuée aux cellules pour qu’elles puissent contenir une lettre.
Quand des touches du clavier sont pressées, la dernière cellule déplacée ou modifiée entre en mode d’édition, et l’on peut modifier, éditer son texte. On quitte le mode d’édition en cliquant en dehors de la cellule.

Figure 2.38
Pour déplacer une cellule, on clique dans la partie supérieure de la cellule (bandeau de déplacement, figure 2.38). Pour l’agrandir ou la réduire, indépendamment de son contenu, on attrape la cellule par le coin bas droite (changement de taille). Le coin bas gauche (zoom) permet de changer la taille de la cellule en modifiant proportionnellement la taille des cellules englobées.
Les flèches partent d’une cellule, arrivent à une autre cellule. Pour les former, une trace ouverte, partant d’une cellule suffit. Leur point d’origine ou leur pointe peuvent être en dehors de toute cellule, mais si aucune des extrémités n’est dans une cellule, la flèche est supprimée.
Le trajet des flèches subit l’action de couplages élastiques lors de leur création ou lors du déplacement ou des modifications des cellules. Nous décrivons ceci dans le chapitre portant sur les couplages élastiques.
Les différentes zones indiquées dans la figure 2.38 ci-dessus sont gérées par une structure de la bibliothèque boîte à outils que nous nommons surface sensible.
Une surface sensible est un dictionnaire faisant correspondre des listes ordonnées de déclencheurs à des clefs formées par les coordonnées des points d’une grille virtuelle.
Un déclencheur est une structure comprenant un cadre (un rectangle droit limitant la portée du déclenchement ou zone) un pointeur de fonction et un pointeur vers le ou les paramètres à fournir à la fonction.

Figure 2.39
Lors d’un clic de l’utilisateur, les coordonnées du point indiqué sont tronquées pour correspondre à un point d’une grille virtuelle puis concaténées (l’abscisse et l’ordonnée forment un mot de 32 bits). Cette clef permet de sélectionner immédiatement (par recherche dichotomique binaire) une liste de déclencheurs correspondant à ce point de la surface. Les différents déclencheurs pointent vers les fonctions de création des cellules et des flèches, les fonctions de déplacement et modification des cellules. Le premier déclencheur de la liste est exécuté. Son exécution consiste en l’appel de la fonction avec la référence aux paramètres, et c’est la fonction elle-même qui connaît la nature et le nombre des paramètres précalculés.
Les déclencheurs sont dans une liste, pour pouvoir superposer les zones sensibles. En effet, les cellules peuvent se chevaucher, et dans ce cas, ce sont les fonctions de la cellule placée en dernier qui doivent être déclenchées en priorité. Mais lors d’un déplacement ou d’une suppression de la cellule, tous ses déclencheurs doivent être retirés, laissant alors la priorité aux déclencheurs suivants dans les listes. Nous nommons mécanismes l’ensemble des zones sensibles d’un élément graphique. Les flèches possèdent également des mécanismes, situés sur les extrémités, et permettant les déplacements de celles-ci. Par contre, les réflexes élastiques des trajets permettent d’élider l’installation de mécanismes le long du parcours.
La bibliothèque permet d’installer une zone sensible dans une surface sensible en la plaçant prioritaire, ou de retirer une zone sensible quelle que soit sa priorité.
L’avantage de cette représentation des actions liées à des éléments graphiques mobiles est le temps constant (et immédiat) de réponse à l’action de l’utilisateur quelque soit le nombre d’éléments graphiques actifs à gérer. En effet, la démarche habituelle est de parcourir la structure décrivant les éléments graphiques pour calculer l’élément sur lequel porte l’action (en calculant d’après l’ordre des superpositions et les coordonnées des éléments), puis de détailler éventuellement, en fonction de la position dans l’élément, pour déterminer la fonction à lancer. Lorsque le nombre d’éléments augmente, ce temps peut devenir non négligeable, et il est situé entre le moment de l’action de l’utilisateur, et le déclenchement d’un effet en retour visible par celui-ci (feed-back visuel), ce qui est un moment critique par rapport au confort de l’interface. Dans notre système, cette réaction arrive immédiatement, par contre, l’installation des mécanismes prend du temps (c’est une sorte de précalcul de l’ensemble des actions que l’utilisateur pourra faire). Mais cette installation des mécanismes n’intervient qu’après la terminaison de l’action de l’utilisateur, pendant que celui-ci voyant le résultat de son action réfléchit à ce qu’il fera ensuite, et qu’il n’est pas encore prêt à agir de nouveau.
Les réflexes des cellules et des flèches permettent la création, la modification et la suppression[45] des éléments du graphe sans avoir recours à des menus, ou des palettes d’outils, simplement en analysant le point d’origine et la forme des mouvements effectués par l’utilisateur. Nous avons utilisé une démarche similaire pour construire l’interface des réseaux de couplages élastiques.
Les clepsydres et les sabliers sont des instruments de mesure du temps très anciens, leur principe est d’utiliser le mouvement d’un fluide pour représenter analogiquement l’écoulement du temps.
Nous utilisons les cellules des schémas comme des réservoirs, dont la contenance dépend de la surface, et les flèches comme des conduits. Les cellules peuvent contenir des grains de temps, qui s’écoulent le long des flèches.
Les flèches prélèvent un grain de temps à leur origine et l’ajoutent à leur arrivée. Si l’origine de la flèche n’est dans aucune cellule, la flèche crée le grain de temps. Si la flèche n’arrive dans aucune cellule, la flèche détruit le grain de temps.
Lorsqu’une cellule est remplie, un événement est déclenché, et la cellule est vidée de son contenu. L’événement peut être le déclenchement de l’exécution d’une section de phonogramme marquée par une lettre correspondant au texte de la cellule. L’événement peut également être le remplissage de toutes les sous cellules.
Le traitement (l’activation des flèches) est effectué en tâche de fond, avec une très faible priorité : L’activation n’est faite que si aucune action de l’utilisateur n’est en cours. La routine d’activation ne traite que les flèches du schéma actif (le schéma de la fenêtre active, au premier plan) et ne déclenche les événements que dans le phonogramme actif (la dernière fenêtre de phonogramme à avoir été activée).
Pour éviter les cycles, dans la circulation des grains de temps, les flèches étant traitées séquentiellement, le traitement n’est fait que si la valeur d’un tirage aléatoire dépasse un seuil. Ceci permet de ne pas traiter les flèches dans un ordre constant, et permet une répartition équitable des grains dans les sorties d’une cellule possédant moins de sources que de sorties par exemple.
Pour comprendre la transformée de Fourier, nous avons étudié les convolutions (et les corrélations). Cette étude a débouché sur un nouvel algorithme de multiplication applicable sur les grand nombres. Nous présentons dans ce chapitre le principe des convolutions, puis nous introduirons une modification de ce principe permettant de produire des séries de nombre connues, telles la suite de Fibonacci et la suite des nombres Catalans, et enfin nous détaillerons notre algorithme de multiplication.
La convolution de deux fonctions est :

ou f(x) * g(x)
Prenons deux séries de nombres {ai} et {bi} écrivons les ai de gauche à droite et les bi de droite à gauche sur deux bandes de papier indépendantes, puis amenons a0 en face de b0 (figure 2.40):

Figure 2.40
On note le premier produit a0.b0.

Figure 2.41
Puis on déplace la bande b un cran sur la droite et on effectue la somme des produits des valeurs face à face (figure 2.41).

Figure 2.42
On réitère jusqu'à ce que la dernière valeur de a soit en face de la dernière valeur de b.
La suite des sommes de produits ainsi obtenue est le résultat de la convolution de a et de b.
{ai} * {bi} = {a0.b0 a0.b1+a1.b0 ... an.bm} = {hi}
Une autre façon de le noter, sans utiliser les bandes de papier glissantes, est de former une grille rectangulaire, de porter les bi verticalement en index de ligne, et les ai horizontalement en index des colonnes.

Figure 2.43
Puis de porter dans chaque case le produit des index.

Figure 2.44
Et enfin de faire la somme des valeurs des diagonales :

Figure 2.45
En permutant les deux séries, a et b, les résultats seraient équivalents :

Figure 2.46 La même grille après rotation de 90° et miroir horizontal : la convolution est commutative.
Si les ai et les bi étaient les coefficients de deux polynômes, les hi obtenus par {hi} = {ai} * {bi} seraient les coefficients du produit de ces deux polynômes.
(a0 + a1x + a2x2 + ... anxn ) . (b0 + b1x + b2x2 + ... bmxm)
= a0.b0 + (a0.b1+a1.b0)x + ... an.bm.x(n+m)
= h0 + h1x + h2x2 + ... h(n+m-1)x(n+m)
Voici un exemple plus simple :
(a + b) . (a + b)

Figure 2.47
la notation en grille rectangulaire correspondante :

Figure 2.48
Tous les termes de la suite n’ont pas besoin d’être connus :

Figure 2.49
{1 1} * {1 2 3 4 5... } = {1 3 5 7 9 ...}
ou encore :

Figure 2.50
{1 -1} * {1 2 3 4 5 ...} = {1 1 1 1 1 ...}
Nous pouvons effectuer la convolution de deux suites semi-infinies :
par exemple {1 2 3 4 5 ... } * {1 2 3 4 5 ... } = {1 4 10 20 35 ...}
Les premiers termes suffisent pour trouver les premiers termes du résultat.

Figure 2.51
Cette idée nous a conduit à générer des suites, en supposant les premiers termes connus, et en déterminant les suivants par le calcul de la convolution.
Nous construisons une suite A avec les résultats de la convolution des premiers éléments connus de la suite A avec une autre suite B qui elle, reste constante.
La suite de Fibonacci : Fibonacci = {0 1 ...} * {1 1}

Figure 2.52
On commence avec les suites A = {0 1} et B = {1 1}, on calcule le deuxième terme de la convolution : 0 x 1 + 1 x 1 = 1 puis on ajoute ce résultat à la fin de la suite A. Dorénavant A = {0 1 1}. Continuons la convolution, le troisième terme est 1 x 1 + 1 x 1 = 2. On ajoute le 2 à la suite A qui devient A = {0 1 1 2}. En itérant ce processus, tous les termes de la suite de Fibonacci sont générés.
Construisons maintenant une suite avec elle-même.
La suite des nombres Catalans : Catalan = {1 ...} * {1 ...}

Figure 2.53
Première étape : {1} * {1} = {1}, nous ajoutons ce 1 à la fin de la suite : {1 1}, ce qui permet de calculer la valeur suivante, le 2, etc...
La multiplication est une convolution : {2} * {3 2 9 5 } = {6 4 18 10}
La figure 2.54 montre comment obtenir le résultat de la multiplication à partir de la convolution.

Figure 2.54
Les nombres écrits en base B avec la suite de chiffres {ai} peuvent être vus comme un polynôme :
a0.Bn + a1.Bn-1 + ... + an.B0
La convolution des séries formées par les chiffres des deux opérandes produit une nouvelle suite de nombres correspondant au résultat de la multiplication si on les considère comme les coefficients des différentes puissances de la base, mais ces chiffres peuvent être supérieurs à la base.
L'opération qui est effectuée après la convolution est la propagation des retenues. Pour la multiplication de 23 par 257, la convolution donne :
{2 3} * {2 5 7} = {4 16 29 21}

Figure 2.55
Puis la propagation des retenues donne le résultat : 5911.
La convolution utilise n.m multiplications de chiffres (6 dans cet exemple) et (n-1).(m-1) additions de nombres (2 dans cet exemple)
Le système de la multiplication musulmane exposé dans "Les nombres et leurs mystères" d'André Warusfel (page 24) (WARUSFEL 1961) est très proche de celui-ci, mais plus pratique pour la gestion des additions et des retenues. Le nombre écrit verticalement l'est de bas en haut, et l'autre nombre reste écrit de gauche à droite. Enfin, les produits de chiffres sont inscrits dans les cases clivées par une diagonale, les dizaines des produits sont placées en bas à gauche et les unités en haut à droite de chaque case. Les additions sont faites diagonale par diagonale, en débutant en haut à droite, et en reportant la retenue éventuelle dans la diagonale suivante (en dessous à gauche). Le résultat est alors directement lisible, inscrit de gauche à droite puis de bas en haut.

Figure 2.56 : 23 x 257 = 5911
Prenons le nombre suivant ...2068965517241379310344827586 et multiplions le par 3. Ce nombre est infini à gauche c'est-à-dire que les chiffres qui sont donnés doivent être répétés indéfiniment vers la gauche.
...2068965517241379310344827586
x 3
= ...206896551724137931034482758
Le résultat est identique au nombre lui-même divisé par 10 (en division entière).
Ce nombre a été construit de la manière suivante :
Choisissons un couple de chiffres quelconque, ici le 6 et le 3, multiplions ces chiffres, 3 x 6 = 18, le 8 est donc le chiffre suivant et la retenue est de 1, continuons en multipliant 8 par 3, ajoutons la retenue ce qui donne 25, le chiffre suivant est 5 et la retenue 2, etc... Continuons ainsi pour l'éternité.
01212021110002210102011122200.. (retenues)
68572844301397314271556986026.. (chiffres de gauche à droite)
3
L'éternité n'est pas très grande par ici, l'état de l'automate capable d'effectuer cette alchimie numérique ne dépend que du multiplicateur et de la base d'une part, et du couple formé par le dernier chiffre découvert et de la retenue. En base 10, en multipliant un chiffre par 3, la retenue ne peut prendre de valeur que dans {0, 1, 2}. Dans le pire des cas, nous aurons fait le tour en 30 pas. Dans cet exemple il a suffi de 28 pas. C'est étonnamment proche de 30, hasard extraordinaire ou cas normal ?
Nous sommes passés par la quasi totalité des couples (chiffre, retenue) avant de revenir sur le point de départ. Évidemment, en base 10 avec 3 pour multiplicateur, si nous repartions de n'importe quel chiffre de 1 à 9 nous obtiendrions le même résultat, à une permutation circulaire près.
Représentons ces choses sous forme de graphes dont les points seront les couples (chiffre, retenue) et les arcs pointant vers le couple suivant dans la série.

Figure 2.57 Graphe de la multiplication par trois en base dix. Les carrés noirs dans les coins des cases représentent les retenues.

Figure 2.58 : Graphe de la multiplication par deux en base dix.
Soit B la base du système de numération, (x, y) le couple (retenue, chiffre), et M le multiplicateur avec 0 < M < B.
E est l'ensemble des couples (retenue, chiffre) :
E = { (x, y) | x [ 0, M-1] , y [ 0, B-1] } = [ 0, M-1] x [ 0, B-1]
soit f l'application qui fait correspondre la valeur n à chaque couple.
f : E Æ [ 0, M.B-1]
(x, y) Æ x.B + y = n
Son application réciproque f -1 permet de retrouver à partir d'un entier positif ou nul inférieur à M.B le couple correspondant :
f -1 : [ 0, M.B-1] Æ E
n Æ ( n // B , n % B )
.//. représente la division entière et .%. le reste de la division.
Soit d de E dans E l'application symétrique définie par :
d (x, y) = (M-1-x, B-1-y)
on a bien d'une part (x, y) E fi (M-1-x, B-1-y) E
et d'autre part la symétrie :
d(d(x, y)) = (M-1-(M-1-x), B-1-(B-1-y)) = (x, y)
L'application R de E dans E qui à un couple (x, y) fait correspondre le couple suivant dans notre automate est :
R: EÆ E
(x, y) Æ (x', y') | M.y + x = n = x'.B + y'
On multiplie le chiffre y par M et on ajoute la retenue, on obtient un entier positif ou nul n < M.B qui transformé par f -1 donne (x', y').
f (R (M-1, B-1)) =
M.(B-1) + (M-1) = M.B - 1 = (M-1).B + (B-1) = f (M-1, B-1)
donc
R (M-1, B-1) = (M-1, B-1).
On a aussi f(R(0, 0)) = 0 = f (0, 0).
Soit (x, y) et (x',y') | R(x, y) = (x', y')
d(x, y) = (M-1-x, B-1-y)
f(R(d(x, y))) =
M.(B-1-y) + M- 1 - x =
MB - M - y.M + M - 1 - x =
MB - (M.y + x) - 1 =
MB - (x'.B + y') - 1 =
B.(M-x') - y' - 1 =
(M-1-x').B + B - y' - 1 =
f(d(x', y')).
donc R(x, y) = (x', y') fi R(d(x, y)) = d(x', y')
Ce qui explique et démontre la symétrie du graphe de R, quelle que soit la base et le multiplicateur, choisi inférieur à la base.
En disposant le graphe sous forme de table, les choses se simplifient.
Voici le graphe de la multiplication par 2 en base 3 (figure 2.59)
Les retenues sont 0 ou 1, en entête, et les chiffres 0, 1 et 2 en index.

Figure 2.59
Un couple (retenue, chiffre) détermine une ligne de la table, et le point dans cette ligne indique une colonne désignant ainsi le couple suivant.
Prenons un exemple : 221(base 3) à multiplier par 2.
Au départ la retenue est 0 le chiffre est 1 (le chiffre de droite du nombre 221(3)), nous visons donc la deuxième ligne, qui contient un point dans la troisième colonne désignant le chiffre 2 que nous posons, et la nouvelle retenue 0. Nous prenons le chiffre suivant dans le nombre : 2, et nous réitérons : (0, 2) -> (1, 1) nous posons 1 (ce qui fait à présent 12), et formons le nouveau couple (1, 2) qui donnera (1, 2), nous posons le 2 : 212, et nous continuons avec le couple (1, 0) puisque nous avons traité tous les chiffres du nombre. (1, 0) -> (0, 1), nous posons le 1 ce qui fait 1212, et continuons avec le couple (0, 0). mais (0,0) donne (0,0) ce qui formera une infinité de 0 devant le résultat : ...0001212(3)
retenues chiffres (r, c)
. 1 -> (0, 2)
0 2 -> (1, 1)
1 2 -> (1, 2)
1 . -> (0, 1)
0 . -> (0, 0)
0 . . ...
Rien n'empêche de former des tables pour un multiplicateur plus grand que la base. Voici la table de la multiplication par 3 en base 2 (figure 2.60).

Figure 2.60
Cette table (figure 2.60) ressemble étrangement à la table précédente (figure 2.59) : les points sont à la même place à une inversion des lignes et colonnes près. C'est comme si on lisait la table précédente à l'envers : La multiplication par M en base B est équivalente à la division par B en base M.
Prenons dix : 1010(2) en base 2 et appliquons notre table.
retenues chiffres (r, c)
. 0 -> (0, 0)
0 1 -> (1, 1)
1 0 -> (0, 1)
0 1 -> (1, 1)
1 . -> (0, 1)
0
Le résultat est bien 11110(2) trente en base 2, (qui se lit de bas en haut dans la colonne c).
Peut-on faire l'opération inverse ?
Essayons avec trente et divisons par 3 en utilisant la table dans l'autre sens. Cette opération inverse est possible, puisque qu'il n'y a qu'un seul point par colonne dans la table. Cette fois ci, nous écrivons le chiffre en commençant par le plus à gauche
retenues chiffres (r, c)
. 1 >- (1, 0)
1 1 >- (0, 1)
0 1 >- (1, 0)
1 1 >- (0, 1)
0 0, >- (0, 0),
0 .
Le résultat est bien 1010 (qui se lit dans la colonne c mais de haut en bas cette fois).
Et avec un nombre non divisible par 3 comme 1101(2) qu'adviendra-t-il ?
retenue chiffre (r, c)
. 1 >- (1, 0)
1 1 >- (0, 1)
0 0 >- (0, 0)
0 1, >- (1, 0),
ici nous avons la partie entière 0100(2) = 4(10)
1 . >- (2, 0)
il reste quelque chose, continuons...
2 . >- (1, 1)
1 . >- (2, 0)
nous avons déjà été dans cet état 2 lignes plus haut
2 . >- (1, 1)
comme il n'y a plus que des zéros dans notre
1 . . ...
nombre, la division continue indéfiniment.
Le résultat est donc 100.01010101...(2) c'est-à-dire 4,33333... en base dix.

Figure 2.61 : La table des 5 en base 2.
Comment construire les tables.
Les chiffres vont de 0 à B-1, les retenues vont de 0 à M-1. La table est une grille carrée de coté M.B. On dépose un point dans la première case : (0, 0), puis on compte M cases sur la droite, et on descend d'une ligne pour déposer le point suivant.
Quand nous avons rempli les B premières lignes, il suffit de les recopier M-1 fois en les décalant d'une case sur la droite à chaque fois.
Il doit y avoir un point dans la dernière case. La grille est symétrique par rapport au centre.
En fait, tous ces graphes peuvent être résumés par la formule suivante :
Dans le sens de la multiplication :
r' = (c.M + r ) // B. (.//. est la division entière)
c' = (c.M + r) % B. (.%. est la reste de la division entière).
Le couple (r, c) produit le résultat (r', c') dans la table de M en base B.
En particulier pour la base 2, la formule se simplifie terriblement ; comme le chiffre c ne peut-être que 0 ou 1, le produit c.M devient 0 ou M d'où :
Multiplication en base 2 :
si c = 0
r' = r >> 1
c' = r & 1
si c = 1
r' = (M+r) >> 1
c' = (M+r) & 1
Où a >> b est l'opération de décalage des bits de a de b rangs vers la droite (en perdant les bits de poids faible) ce qui correspond à la division entière par 2 lorsque b vaut 1. Et & est l'opération et logique, appliquée bit à bit. Le masque 1 permet de ne conserver que le bit de poids faible, et force les autres bits à zéro, ceci fournissant le reste de la division entière par 2, encore nommée parité.
Cet algorithme de multiplication ou de division de (grands) nombres ou de polynômes est très efficace lorsque que le diviseur et la base sont constants[46]. La table, ne dépendant que du diviseur (ou du multiplicateur) et de la base, n’est à construire qu’une seule fois lorsque ceux-ci sont constants.
Une fois la table construite, l’opération, division ou multiplication, est effectuée en un temps directement proportionnel au nombre de chiffres de l’opérande.
On peut envisager pour certaines applications de spécifier les tables au niveau matériel (hardware), et de câbler l’algorithme de multiplication ou de division lorsque qu’un haut débit est nécessaire et que les multiplicateurs et/ou les diviseurs sont en petits nombres.
Cet algorithme a été utilisé par Sabah BEKKOUCHE, (BEKKOUCHE 1994) pour la division polynomiale employée dans un algorithme de détection d’erreur lors des transferts de données dans les réseaux.
Les tables précédentes peuvent être condensées, en utilisant pour index les chiffres de la base d’une part et les valeurs possibles des retenues d’autre part. Les cellules des tables doivent alors contenir des couples (chiffre, retenue).
Nous proposons ici une représentation graphique de ces tables la figure 2.62 représente la table de division et de multiplication par 2 en base 10.

Figure 2.62 : table de 2 en base 10
En haut comme en bas, apparaît deux fois la série des dix chiffres de la base. Chaque série représente une valeur possible de retenue. Les chemins blancs mènent d’un couple (chiffre, retenue) à un autre.
Pour faire une division, on écrit d’abord le nombre à diviser, prenons par exemple 47, puis on regarde le premier chiffre à partir de la gauche (4). On repère ce chiffre dans la première série du haut et on suit le chemin blanc jusqu’en bas. Le 4 descend vers le 2 de la première série. On écrit 2. On cherche le chiffre suivant (7) dans la même série en haut. Le 7 conduit au 3 de la seconde série. On écrit 3. Le résultat est donc 23 en entier, mais on peut continuer la division après la virgule, (notre nombre est 47.000...) le chiffre suivant à chercher est le 0 dans la même série que le dernier résultat obtenu (la seconde). Le 0 mène au 5 de la première série. On écrit 5 et on continue. Le 0 de la première série mène au 0 de la première série, il y a donc une infinité de 0 après le 5. Le résultat est 23.50000...
Pour faire une multiplication, le principe est le même : on commence toujours dans la première série, mais on prend les chiffres du nombre à multiplier de droite à gauche et on cherche les chiffres dans les séries du bas pour écrire les résultats donnés par les séries du haut.
Par exemple pour multiplier 19, on cherche le 9 en bas, ce qui donne 8 en haut (dans la seconde série, ce qui correspond à une retenue), puis on cherche le 1 dans la seconde série du bas, ce qui donne 3 dans la première série en haut. Le résultat est 38, mais on peut continuer avec 0 qui donne 0, etc... le résultat est ...00038 (avec une infinité de zéros à gauche).
La table ci-dessous est la table de division et de multiplication par 3 en base 10. On l’utilise de la même façon. Elle est formée de 3 séries de dix chiffres.

Figure 2.63 : Table de 3 en base 10.
Pour construire une table, de N en base B, on répète N fois les chiffres de la base. Puis on regroupe les chiffres en B groupes (numérotés de 0 à B-1) de N chiffres en numérotant les chiffres de 0 à N-1 dans chaque groupe. Les résultats sont les numéros des groupes (qui correspondent à des chiffres de la base). Pour réordonner les chiffres de façon d’une part à pouvoir les écrire dans l’ordre en bas, et d’autre part à guider vers les bonnes séries, on permute les chemins des couples de chiffres dont celui de gauche porte un numéro plus grand que celui de droite, et on répète l’opération jusqu’à ce que plus aucune permutation ne soit possible. Chaque chemin conduit alors vers le chiffre des séries du bas de la table (qui correspond au numéro du groupe du chiffre de départ).
Par exemple pour écrire la table de 5 en base 2 on répète 5 fois les chiffres 0 et 1.
0 1 0 1 0 1 0 1 0 1
Nous regroupons les chiffres en 2 groupes de 5.
0 1 2 3 4 0 1 2 3 4
Puis nous permutons les couples de numéros dont le second est inférieur au premier.
0 1 2 3 4 0 1 2 3 4
0 1 2 3 0 4 1 2 3 4
0 1 2 0 3 1 4 2 3 4
0 1 0 2 1 3 2 4 3 4
0 0 1 1 2 2 3 3 4 4
Lorsque plus aucune permutation n’est possible. La table est complète, et les numéros indiquent les chemins à suivre.
0 1 0 1 0 1 0 1 0 1
-------------------
0 1 2 3 4 0 1 2 3 4 Nous partons de 2 groupes de 5
0 1 2 3 0 4 1 2 3 4
0 1 2 0 3 1 4 2 3 4
0 1 0 2 1 3 2 4 3 4
0 0 1 1 2 2 3 3 4 4 Nous arrivons à 5 groupes de 2
-------------------
0 1 0 1 0 1 0 1 0 1
Par exemple pour diviser vingt, 10100 en base 2 par cinq on obtient :
1 -(1)-> 0 (groupe 1)
0 -(2)-> 0 (groupe 2)
1 -(0)-> 1 (groupe 0)
0 -(0)-> 0 (groupe 0)
0 -(0)-> 0 (groupe 0)
Le résultat est bien 00100 quatre en base 2.
L’exploration de l’univers mathématique est pour nous une source inépuisable d’éléments étonnants, voire magiques, alimentant nos recherches. La transmutation de ces formules opaques en éléments musicaux est une alchimie passionnante. La représentation des objets mathématiques par des formules ne correspond pas à notre propre représentation mentale de ces objets. C’est pourquoi nous recherchons des représentations graphiques telles que la précédente.
Deux points de vue, opposés et complémentaires, sont apparus au cours de nos démarches compositionnelles : soit les formules (ou objets mathématiques) sont elles-mêmes le modèle que nous cherchons à écouter, le programme est alors, tel un stéthoscope, un outil pour rendre audible un phénomène existant; soit les formules ne sont que les outils à adapter pour produire les effets sonores désirés.
Les trajectoires, présentées dans le chapitre suivant, peuvent être utiles à ces deux points de vue : l’objet mathématique sous-jacent est présenté sous forme graphique et peut être écouté.; d’autre part, la création de trajectoires peut être orientée selon le type d’effet sonore recherché.
Les synthétiseurs numériques, tels qu’ils nous sont proposés sur le marché, deviennent de plus en plus fermés : ce sont des boîtes noires, produisant des sons préfabriqués utilisant différents systèmes de synthèse. Les réglages accessibles à l'utilisateur ont tendance à se limiter à la simple sélection de timbre, et non au contrôle des procédés de synthèse comme c'était le cas il y a une dizaine d'années.
D'autre part, les ordinateurs deviennent de plus en plus performants, et possèdent, pour les applications multimédias, la possibilité de jouer des sons mémorisés sous la forme de fichiers d'échantillons.
La conjonction de ces deux points favorise l'écriture de modules logiciels de synthèse[47]. Nous effectuons la synthèse en temps différé actuellement, elle pourrait être en temps réel en utilisant les capacités des processeurs spécialisés dans le traitement du signal : les DSP (Digital Signal Processor)[48].
Pour synthétiser (des sons) il faut osciller. Osciller, vibrer, bouger, aller et venir, tourner autour d'un point, zigzaguer..., sans rupture dans le temps, bref, il faut générer une suite de valeurs qui commandera finalement les déplacements de la membrane du haut-parleur au cours du temps.
Avec les couplages élastiques, nous avons de bons oscillateurs : le déplacement d'un point d'une chaîne de couplages génère des sons intéressants. Mais nous pouvons trouver d'autres formules très simples aboutissant à des suites de valeurs que l'on peut rendre audibles.
Nous pourrions aussi écouter des phénomènes qui naturellement ont des fréquences très basses et/ou des amplitudes très faibles, et qui une fois ramenés dans une plage audible pourraient être appréhendés d'une manière nouvelle. Prenons un arbre par exemple, ses branches oscillent lentement sous l'effet du vent, nous entendons le bruissement des feuilles (une sorte de bruit coloré) mais nous n'entendons pas les branches. En enregistrant les déplacements des branches et en les accélérant, peut-être pourrions-nous déceler des différences de sonorités entre les espèces d’arbres. Ou encore en enregistrant le mouvement des ailes d’un oiseau en vol : nous sommes bien capable de distinguer un moustique d’une mouche ! Je pense qu’en augmentant la fréquence des battements d’ailes des oiseaux, nous pourrions discerner à l’oreille les caractéristiques des styles de vols.
La possibilité de transformer la trace d'un phénomène en fichier d'échantillons peut sans doute nous permettre d'utiliser nos capacités auditives pour l'analyse des données (au lieu de les visualiser).
L’oscillation la plus simple (pour un informaticien) est fournie par une boucle qui génère alternativement un zéro puis un un.
01010101010101....
Ceci produit un signal carré (il apparaît carré si on trace les lignes verticales reliant les traits horizontaux) (figure 3.1) :

Figure 3.1
En étirant l’image verticalement on change l’amplitude (l’intensité sonore), et en étirant horizontalement, on change la fréquence (qui correspond à la hauteur du son).
Une formule plus générale pourrait être ainsi :
" t [0, n] s(t) = A . ((t.w ) & 1).
L’opérateur & désignant l’opération et logique.
La suite des nombres entiers, écrite en binaire (figure 3.2) donne autant d’oscillateurs qu’il y a de bits dans la représentation :

Figure 3.2
En se déplaçant d’une colonne vers la gauche, on divise la fréquence par 2 (on descend d’une octave).
Si nous comptions en base dix, notre onde ne serait plus carrée mais en dent de scie (figure 3.3) :
" t [0, n] s(t) = A . ((t.w ) % Base).
où l’opérateur % désigne l’opération modulo.
- - -
- - -
- - -
- - -
- - -
- - -
- - -
- - - -
- - - -
- - - -
012345678901234567890123456789012...
Figure 3.3
On peut voir la dent de scie comme étant la valeur d’un accumulateur, incrémenté à chaque pas, et vidé d’un coup lorsqu’une valeur limite est atteinte.
Des discontinuités, des passages abrupts d’un échantillon à l’autre par des valeurs extrêmes, existent dans le carré et la dent de scie (figure 3.4),.

Figure 3.4
L’onde triangulaire au contraire est continue (figure 3.5) :
![]()
Figure 3.5
Elle est avec l’onde sinusoïdale, le carré et la dent de scie une onde de base (des plus simples) et des plus fréquemment rencontrées dans les générateurs.
Comment générer le triangle ? Si nous le voyons comme un accumulateur, il faudra incrémenter celui-ci tant qu’il est inférieur à une limite, puis le décrémenter tant qu’il est supérieur à zéro. Ceci implique la mémorisation d’un état indiquant si on est dans une phase montante ou descendante.
Au contraire, si nous voyons le triangle comme étant la trace dans le temps d’un mobile faisant des allers et retours entre deux points (comme faisant les cent pas entre deux murs (figure 3.6)), nous n’avons plus d’état particulier à mémoriser : il suffit d’inverser le signe de la vitesse (de valeur absolue constante) du mobile à chaque fois que la position atteint une limite.

Figure 3.6 Figure 3.7
La sinusoïde peut s’interpréter de la même façon, comme étant la trace dans le temps d’un mobile dont la trajectoire est circulaire (figure 3.7), en observant cette trajectoire de profil.
La dent de scie (figure 3.8) est la trace dans le temps d’un mobile se déplaçant toujours dans le même sens, mais dans un espace torique (Quand le mobile sort d’un côté, il rentre de l’autre - d’où le lien avec l’opération modulo).

Figure 3.8
Le carré n’est qu’un cas particulier de dent de scie (dans un espace discret), avec un module de 2.
Cette vision sous forme de projection de la trajectoire d’un mobile sur une droite (la vue de profil) et le développement des points projetés dans le temps nous permet d’unifier tous ces oscillateurs (y compris les couplages élastiques) et nous suggère de nouvelles façons de créer des oscillateurs.
Nous pourrions par exemple simplement dessiner une trajectoire à l’aide de la souris et générer directement le son correspondant.
Un cercle donnerait un son sinusoïdal pur, mais que donnerait une trajectoire en huit, en lemniscate, ou en patate ?
Toutes les formes fixes de trajectoires donneront évidemment des sons périodiques (chaque tour correspondant à une période).
La fréquence sera donc déterminée par la vitesse du mobile. L’amplitude quant à elle étant la largeur de la trajectoire (perpendiculairement au sens de projection).
Les trajectoires pourraient se déformer progressivement, introduisant des modifications dynamiques du spectre.
La trajectoire du mobile peut également être décrite par des règles et non par une suite de valeurs prédéterminées.
Le mobile peut avoir ses règles de conduite, et interagir avec un environnement, introduisant ainsi des variations de la trajectoire. Les variations de trajectoire impliquent des modifications de timbre. Par exemple en enfermant une mouche dans une boîte de forme spéciale (figure 3.9), et en faisant en sorte que la mouche vole toujours, repoussée par les murs.

Figure 3.9
Nous avons réalisé un programme permettant de créer les trajectoires à l’aide de la souris, puis de générer les fichiers d’échantillons correspondant à la projection sur l’axe des x, de la position d’un mobile circulant sur cette trajectoire. Nous avions précédemment élaboré un module implémentant les couplages élastiques des trajets des flèches de graphes, en calcul entier, et le module permettant de construire des réseaux de couplages à maillage linéaire, carré ou cubique.
Nous avons combiné les deux modules pour représenter les trajectoires. Une trajectoire de notre système sera une liste de points, formant une boucle, chaque point étant relié au point suivant et précédent par un couplage élastique.
Un geste de la souris avec le bouton enfoncé dans une fenêtre de trajectoires permet de former une trajectoire. Le dernier point étant automatiquement relié au premier. Pendant le geste, la trajectoire se forme sur l’écran.
Pendant la simulation, les tensions des couplages élastiques appliquées sur les points des trajectoires déplacent ceux-ci, modifiant la trajectoire, et modifiant ainsi le signal correspondant. Tous les points de la trajectoire sont mobiles[49]. L’état initial de la trajectoire est conservé en mémoire de façon à ce que la production de son à partir d’une trajectoire ne soit pas destructeur.
Toute la couche d'interface, gestion des fenêtres de trajectoires, de l'association entre les fenêtres et les données correspondantes, des barres de défilement, de la sauvegarde des documents, de l'impression, des actions du clavier et de la souris, a été réalisée à partir d'un squelette préexistant : il suffit de recopier et changer le nom de la structure associée au nouveau type de fenêtre pour obtenir un squelette fonctionnel. Puis, l'intégration dans le programme principal est localisée au niveau des fonctions gérant l'action des menus, qui doit pouvoir distinguer les différents types de documents coexistants.
La structure associée aux fenêtres de trajectoires est une liste (double chaînage) de trajectoires. Chaque trajectoire est constituée d'un pointeur vers une structure élastique (double chaînage de points en coordonnées entières) mémorisant l’état initial, d'un pointeur vers un réseau linéaire de même taille (mais en coordonnées flottantes) pour la simulation, et enfin d'une structure contenant les paramètres de réglage des propriétés du réseau : tension des couplages, viscosité, plus les valeurs enregistrées lors des expériences telles que la durée du son, la fréquence d'échantillonnage souhaitée.
Il semble impossible de convertir des phonogrammes ou d’autres représentations spectrales en trajectoires dans le sens où nous l’avons utilisé Comment retrouver la trajectoire d’un mobile hypothétique dont la projection sur une dimension correspondrait au signal dont la transformée est le phonogramme original ?
Par contre, en élargissant la notion de trajectoire à une succession de positions dans un espace quelconque au cours du temps, nous pouvons construire des trajectoires à partir de sonogrammes ou de phonogrammes. FEITEN et GÜNZEL (FEITEN 1994) utilisent une notion similaire pour classifier les sons dans une base de données : Les sons sont d’abord analysés avec la transformée de Fourier rapide, par tranches temporelles successives. Les spectres sont rapprochés de ceux d’une grille de spectres types préexistants en utilisant un réseau neuromimétique. Chaque spectre est alors assimilé à un point de la grille. Le sonogramme étant constitué d’une succession de spectres, une trajectoire dans la grille est ainsi constituée. Une nouvelle grille contenant des trajectoires est utilisée alors pour classifier (à l’aide d’un second réseau neuromimétique) la trajectoire correspondant au son analysé.
Nous présentons ici les résultats obtenus avec les trajectoires, nous montrons ensuite l’analogie avec l’algorithme de Karplus-Strong (KARPLUS 1983), (JAFFE 1983).

Figure 3.10 : Un exemple de trajectoire

Figure 3.11 : Le signal correspondant à la trajectoire de la figure 3.10. (l’image a été réduite).
Dans l’exemple de la figure 3.11, le réglage de tension était de zéro (pas de tension) et la viscosité était à 1 (pas de viscosité), donc le signal est périodique, et son amplitude est constante (enveloppe rectangulaire). La fréquence fondamentale du signal est directement liée au nombre de points de la trajectoire et à la fréquence d’échantillonnage choisie.
Lorsqu’on augmente la tension, la trajectoire se modifie progressivement : la courbe se lisse, et tend vers un cercle, puis vers un point.
Voici (figure 3.12) des extraits du signal généré avec la même trajectoire (figure 3.10), et une tension de 4.




Figure 3.12
Au fur et à mesure de l’application de la tension sur les points de la trajectoire, celle-ci s’arrondit, se lisse. Les petites aspérités disparaissent en premier et le signal produit se rapproche de plus en plus d’une sinusoïde.
La vue en réduction de l’ensemble du signal donne la forme d’enveloppe représentée par le figure 3.13.

Figure 3.13
Le son obtenu est très proche d’un son de corde pincée, le spectre (figure 3.14 et 3.15) se simplifie au cours du temps. Les partiels harmoniques aigus sont les premiers à disparaître.

Figure 3.14 : Portion du spectre au début du signal.

Figure 3.15 : Portion du spectre pris vers la fin du signal.
Les fréquences du fondamental et des harmoniques n’ont pas changé (l’échelle de visualisation n’est pas exactement la même).


Figure 3.16
Ci-dessus (figure 3.16), le phonogramme résultant de la transformée élastique (cf. chapitre Transformée élastique) du son généré par la trajectoire, on voit nettement les harmoniques disparaître au cours du temps (de gauche à droite). L’échelle indique les fréquences. (à droite, image en niveaux de gris, à gauche, image en noir et blanc, tramée par méthode de propagation d’erreur, algorithme de FLOYD-STEINBERG (ROGERS 1988)).
En utilisant de l’inertie, dans l’expérience ci-dessous (figures 3.17, 3.18 et 3.19), l’inertie est réglée à 1, nous obtenons un signal dont la forme évolue périodiquement :

Figure 3.17 : Vue globale



Figure 3.18 : des vues du même signal à des échelles de réduction décroissantes :

Figure 3.19 : Détails du signal
Dans les premières expériences, nous avons simplement généré des sons périodiques, résultats directs de la circulation de point en point le long des trajectoires, en utilisant la projection des points sur l'axe horizontal.
Puis, nous avons appliqué la tension élastique (avec ou sans inertie) à la trajectoire elle-même, à chaque tour de la trajectoire un ou plusieurs cycles de tension : Le résultat est étonnamment proche des résultats obtenus par l'observation de points dans les réseaux de couplages, ce sont des sons proches des cordes pincées, des sons percussifs si l'inertie est faible, et entretenus si l'inertie est grande. Le rôle de l'inertie n'est pas le même que dans les réseaux de couplages. Sans inertie les réseaux de couplages excités par une impulsion se stabilisent sans résonner, alors que les trajectoires évoluent lentement vers un point (le centre de gravité) en se lissant au début, puis en prenant des formes ayant tendance à se rapprocher du cercle, et donnant un son de corde. Avec de l'inertie, les réseaux excités par une impulsion initiale résonnent comme une corde, alors que les trajectoires se contractent puis s'étendent alternativement, en reprenant à chaque cycle de contraction-expansion une position isomorphe à la position initiale (même forme, mais réduite) donnant un son entretenu plus longtemps, soumis à des variations cycliques d'amplitudes de chacun des partiels. C'est-à-dire théoriquement, une variation cyclique du timbre, mais à une vitesse telle que l'oreille la perçoit globalement comme un timbre nouveau, phénomène à rapprocher des modulations de fréquence et d'amplitude tels qu'ils ont été exploités dans la musique électroacoustique tant analogique que numérique.
Nous avons utilisé les couplages élastiques pour réaliser des liens souples dans des interfaces graphiques (par exemple dans les schémas d’organisation temporelle des phonogrammes). Nous les utilisons également pour transformer, analyser ou créer des sons.
Le trajet des flèches des schémas est constitué d'une série de points enregistrés lors du geste de l'utilisateur créant le lien.

Figure 4.1 : Schéma dont les trajets des flèches ne sont pas lissés.
Ces points forment une ligne brisée assez irrégulière (figure 4.1) que les couplages élastiques permettent de lisser (figure 4.2).

Figure 4.2 : Schéma de la figure 4.1 après le lissage par les couplages élastiques.
Puis une fois le lien construit et installé, ses extrémités doivent pouvoir subir des déplacements : par exemple lors du déplacement d'une cellule du schéma (d'un nœud du graphe) connectée par ce lien (figure 4.3).

Figure 4.3 : Nous avons déplacé une cellule du schéma de la figure 4.2.
Pour gérer ces déplacements, deux procédés ont étés mis en œuvre : pendant que l'utilisateur presse le bouton de la souris pour contrôler la position, le premier procédé propage le mouvement de l'extrémité du lien le long du trajet, avec une règle de répartition (ou déperdition du mouvement) mais si la position reste identique, le second procédé applique une règle de tension sur le trajet.
Différentes règles de tension entraînent des comportements rappelant des réactions physiques naturelles, telles l'élasticité, le poids, les torsions, ou artificielles telles la répulsion, les spirales, ou encore ayant un intérêt graphique et ergonomique, telles les styles de trajets (certains angles favorisés) ou encore la détection des cellules (les liens évitent de se superposer aux nœuds).

Figure 4.4
La figure 4.4 illustre le principe de base des couplages élastiques : La tension au point A, relié aux points B et C, est le vecteur AT = AB + AC.
En déplaçant le point A dans le sens de la tension, et en agissant de même pour tous les points connectés, la tension de chacun des points se réduit progressivement (figure 4.5).

Figure 4.5 : De haut en bas sont présentées trois étapes successives d'application des couplages élastiques : la première correspond au tracé original à la souris, la seconde représente le même trajet après quelques cycles de tension, et la dernière après stabilisation.
Nous décrivons maintenant différentes règles que nous avons implémentées.
La règle de tension utilisée pour la figure 4.5 est le déplacement de 1 pixel dans la direction de la tension indépendamment en x et en y :
déplacementunitaire = signe ( tension )
Pour donner un effet de poids, nous ajoutons un vecteur constant orienté vers le bas à la tension.

Figure 4.6 : Règle du poids
En appliquant la règle du poids, le trajet (figuré en 4.5) se déforme jusqu’à cette nouvelle position (figure 4.6).
déplacementpoids = signe(tension) + (0, 1)

Figure 4.7 : Règle de répulsion
En utilisant de la répulsion entre les points nous pouvons visualiser la position des points le long du trajet. La répulsion est produite en utilisant l’opposé du signe de la tension. Cette règle ne fait pas converger les points du trajet vers une position stable, au contraire, les points ont tendance à se repousser indéfiniment.
déplacementrépulsion = - signe(tension)

Figure 4.8 : Règle de torsion

Figure 4.9 : Règle de torsion, même flèche que pour la figure 4.8, mais avec une distance plus courte entre les extrémités de la flèche.
La règle de torsion (figures 4.8 et 4.9) applique une tension unitaire plus un poids (un vecteur de module constant) changeant de direction, d'un huitième de tour, à chaque point.
Une règle arrivant rapidement à la stabilisation est la suivante :
déplacementrapide = tension / 2 + signe (tension)
On ajoute le signe de la tension pour conserver un déplacement tant que la tension n'est pas nulle : Si on applique uniquement la moitié de la tension (sans ajouter le signe de la tension), en calcul entier, les tensions ne se résorbent pas toutes, et des tensions unitaires (dont la moitié entière est nulle) sont conservées tout au long du trajet, résultant en une courbe dépendant de la position initiale. Le résultat stable de la tension rapide est le même que pour la tension unitaire, mais il est atteint plus rapidement.

Figure 4.10 : Règle de détection
Avec la règle de détection (figure 4.10), le trajet évite (ou tente d'éviter) les cellules.
La détection est calculée par un champ de vecteurs déterminé par la position des cellules et ajouté localement à la tension. La valeur des vecteurs du champ est dirigée vers l'extérieur de chaque cellule. Chaque point du plan détermine une clef d'accès dans une surface sensible mémorisant la liste des cellules présentes en ce point, les vecteurs du champ sont ensuite calculés d'après le cadre de chaque cellule.
Toutes ces règles sont calculées localement, mis à part la règle de détection qui fait appel à une représentation des champs des cellules, seules les coordonnées des points du trajet de la flèche sont utilisées et pour un point donné, nous utilisons ses coordonnées et les coordonnées de ses deux points voisins.
Les coordonnées sont notées dans des structures ayant la taille d'un pointeur. Par exemple sur une machine 32 bits, les coordonnées h et v (horizontale, verticale) sont notées chacune sur 16 bits. Ceci permet d'utiliser la place qui est prévue dans les routines de traitement de chaînages pour les références en plaçant directement un point (et non un pointeur vers un point) dans l'espace prévu pour désigner l'élément membre du chaînage. L'union PointPointeur permet d'accéder à un élément soit en tant que point, soit en tant que pointeur.
La structure elastique permet d'accéder directement au premier et au dernier maillon d'un chaînage bidirectionnel.
La structure chaineIter décrit l'état d'un parcours d'un tel chaînage et permet de simplifier l'écriture de boucles parcourant ce type de chaînage, ou de combiner plusieurs parcours simultanément.
La fonction DeplOrigineElastique (donnée ci-dessous) transmet le mouvement de l'origine le long du trajet de la flèche.
Le premier point du trajet est déplacé du mouvement imposé.
Puis le parcours est effectué depuis le second point jusqu'à l'avant dernier point de sorte que chaque point possède un précédent et un suivant.
Le parcours s'arrête également si le mouvement est totalement absorbé.
En chaque point, la tension est calculée, et si le mouvement imposé va dans le sens de la tension, le mouvement est appliqué au point puis décrémenté d'une unité (ou incrémenté si le mouvement était négatif).
La tension est calculée sur la position actuelle des voisins, mais comme le point précédent a déjà été traité, le calcul n'est pas parallèle, mais séquentiel.
void deplOrigineElastique(elastik, mouvrel)
elastique *elastik;
Point mouvrel;
{
register PointPointeur chose;
chose.ptr = elastik->fil.debut->chose;
chose.p.h += mouvrel.h;
chose.p.v += mouvrel.v;
elastik->fil.debut->chose = chose.ptr;
/* transmission du déplacement aux mailles suivantes... */
{
chaineIter mailles;
iterPremier(&mailles, &elastik->fil);
iterSuivant(&mailles); /* passe le premier */
while( (mouvrel.h || mouvrel.v)
&& iterParcours(&mailles)
&& mailles.leMaillon->apres ) /* sauf le dernier */
{
Point tension;
PointPointeur prec, suiv;
prec.ptr = mailles.leMaillon->avant->chose;
suiv.ptr = mailles.leMaillon->apres->chose;
chose.ptr = iterElement(&mailles);
tension.h = prec.p.h + suiv.p.h - (chose.p.h << 1);
tension.v = prec.p.v + suiv.p.v - (chose.p.v << 1);
if(mouvrel.h > 0 && tension.h > 0)
{
chose.p.h += mouvrel.h;
--mouvrel.h;
}
else if(mouvrel.h < 0 && tension.h < 0)
{
chose.p.h += mouvrel.h;
++mouvrel.h;
}
if(mouvrel.v > 0 && tension.v > 0)
{
chose.p.v += mouvrel.v;
--mouvrel.v;
}
else if(mouvrel.v < 0 && tension.v < 0)
{
chose.p.v += mouvrel.v;
++mouvrel.v;
}
iterChangeElement(&mailles, chose.ptr);
iterSuivant(&mailles);
}
}
}
Voici la procédure calculant et appliquant la moitié de la tension :
static void tendre1(elastik)
elastique *elastik;
{
register PointPointeur chose;
chaineIter avance;
iterPremier(&avance, &elastik->fil);
iterSuivant(&avance); /* passe le premier */
while( iterParcours(&avance)
&& avance.leMaillon->apres )
{
Point tension;
PointPointeur aprec, asuiv;
aprec.ptr = avance.leMaillon->avant->chose;
asuiv.ptr = avance.leMaillon->apres->chose;
chose.ptr = iterElement(&avance);
tension.h = aprec.p.h + asuiv.p.h - (chose.p.h << 1);
tension.v = aprec.p.v + asuiv.p.v - (chose.p.v << 1);
/* appliquer 1/2 de la tension.
*/
chose.p.h += (tension.h >> 1);
chose.p.v += (tension.v >> 1);
iterChangeElement(&avance, chose.ptr);
iterSuivant(&avance);
}
}
Le son est le résultat de la perception des variations de pression de l'air (ou du milieu transmettant le son).
L'idée est de simuler cette propagation du son dans un milieu artificiel constitué de points organisés en réseaux, reliés entre-eux par des couplages élastiques.
L'ACROE à Grenoble dirigé par Claude CADOZ effectue des expériences de synthèse par simulation de modèles physiques ou synthèse modale (DJOHARIAN 1993). Synthèses de cordes pincées, frottées, de billes. Un système tel que CORDIS-ANIMA (CADOZ 1993) permet de modéliser des systèmes, de les visualiser, de les écouter, et, par l’intermédiaire de transducteurs gestuels rétroactifs, de les manipuler.
La synthèse modale est également étudiée à l’IRCAM où le système MOSAIC (MORRISON 1993) est développé.
A priori nous voulons pouvoir constituer toutes sortes de formes de réseaux (différents types de maillages) mais nous commençons par les maillages carrés tridimensionnels les plus rapidement programmables, et permettant d'économiser de l'espace mémoire en encodant les liaisons implicitement d'après la position des points dans la mémoire.
Une structure décrivant un réseau contient la taille du réseau (le nombre de points dans chacune des trois dimensions) et deux espaces mémoires : l'espace présent et l'espace futur, contenant les coordonnées de chaque point.
Les deux espaces sont nécessaires pour simuler une évolution parallèle des couplages élastiques. Dans des implantations précédentes, pour les réseaux de couplages et les trajets de flèches, le parallélisme n'était pas important, et nous modifiions les coordonnées des points directement (les points étant traités séquentiellement). Mais pour cette simulation, il parait souhaitable de traiter les points parallèlement pour étudier la propagation des déformations dans le réseau.
Les calculs de tension sont effectués dans l'espace présent, les nouvelles positions mémorisées dans l'espace futur et enfin, une fois que tous les points sont calculés, les pointeurs des deux espaces sont permutés.
En chaque point du réseau, nous effectuons la somme des vecteurs ayant pour origine le point et pour extrémité un point voisin (voisin d'après le maillage et non la distance entre les points) cette somme est la tension en ce point.
tension (p) = S (vi - p) où p est un point, et les v1, ... vn les points voisins.
Le déplacement du point est calculé d'après la tension : Par exemple en appliquant un déplacement d'une unité dans le sens de chaque composante non nulle de la tension.
Cette règle (de déplacement unitaire) conduit à une stabilisation du réseau, quel que soit l'état initial, dans une position de repos unique (ou un ensemble de positions proches du repos, cycliques et de faible amplitude, dépendant du nombre de couplages par point et du fait de la discrétisation de l'espace). Cette position de repos est déterminée uniquement par la position des points fixes du réseau.
Les points fixes sont les extrémités des réseaux à une dimension (droites), les coins des plans, les sommets des volumes.
Quand les points ont des coordonnées mémorisées en nombres flottants, nous pouvons régler un coefficient (entre 0 et 1) appliqué à la tension pour calculer le déplacement :
déplacement = tension (p) * coefficient.
Avec des nombres entiers nous appliquons simplement un décalage sur la tension, c’est-à-dire une division entière par une puissance de 2. La perte d’information avec les nombres entiers est telle que nous sommes obligés finalement d’utiliser une représentation en nombres flottants pour pouvoir exploiter les petites vibrations et être en mesure de les amplifier (ou de les atténuer).
Nous pouvons également introduire une notion d’inertie, en utilisant un coefficient appliqué à la vitesse précédente pour l’ajouter au déplacement.
vitesse (p) = position(p) - passé(p)
(ou le passé est la position précédente).
déplacement = inertie * vitesse (p) + tension (p) * coefficient.

Figure 4.11 : Calcul de la nouvelle position d’un point du réseau
Le point A' est la position passée de A.
A'A = V (la vitesse). V multipliée par l'inertie donne I.
Les points B et C voisins de A permettent de calculer T la tension.
Enfin, la tension T multipliée par un coefficient donne t, et la somme de I et de t donne comme résultat A'', la nouvelle position du point A.
Les règles de tensions que nous avons appliquées jusqu'alors laissent les n dimensions d'espace indépendantes : Le déplacement d'un point parallèlement à un axe n’entraînant aucune modification des coordonnées des points sur les autres axes. De ce fait, la transmission du signal perpendiculairement à une droite donne le même résultat que la transmission parallèle à la droite.
Nous construisons un réseau unidimensionnel, une droite fixée à ses extrémités. Nous excitons le système en imposant un déplacement à l’un des points (par exemple une des extrémités, voir figure 4.12). Le déplacement imposé peut provenir directement d’un signal enregistré ou généré auparavant.

Figure 4.12 : Filtrage du signal par un réseau unidimensionnel
Puis pour chaque échantillon, nous lançons le procédé de tension élastique (une ou plusieurs fois), et nous enregistrons dans un nouveau fichier les déplacements d’un autre point du réseau.
Sans inertie, le système se comporte alors comme une série de filtres passe bas. Avec l’entrée à une extrémité, plus le point de sortie est éloigné, plus les aigus sont filtrés. En traitant un signal harmonique de cette façon, nous pouvons (en sélectionnant correctement la longueur du réseau, la tension et la position d’écoute) extraire le fondamental.
Avec le même réseau que précédemment (§ Filtrage), en ajoutant de l’inertie et en prenant en entrée un signal impulsionnel, nous obtenons la synthèse de sons proches de cordes pincées. La longueur de la corde est équivalente à la longueur du réseau, la tension de la corde au coefficient de tension des couplages élastiques. La résonance du système est liée à l’inertie : avec une inertie nulle, le système ne fait qu’amortir les vibrations, et les vibrations de fréquences élevées sont les premières à disparaître. Avec une inertie proche de 1 (mais inférieure à 1) nous obtenons des résonances de durées variables.

Figure 4.13 : Signal donné par le 25ème point d’une droite de longueur 50, coefficient de tension : 0.1, inertie : 0.99, durée ≠ 50 ms. L’excitation a été donné par le signal impulsionnel de la figure 4.15.

Figure 4.14 : 25ème point d’une droite de longueur 50, coefficient de tension : 0.1, inertie : 0.999, durée ≠ 400 ms.

Figure 4.15 : les 20 premières millisecondes environ, du signal d’impulsion.
Le signal impulsionnel de la figure 4.15 fut dessiné à l’aide de la souris et n’est pas vraiment une impulsion, et le silence n’est pas non plus totalement un silence. Il est impossible d’obtenir physiquement un signal impulsionnel strict : Il faudrait que la durée de l’impulsion soit infiniment proche de zéro. Pratiquement, un signal tel que celui-ci est de nature impulsionnelle.

Figure 4.16 : Détail du signal de la figure 4.14
Dans le signal résultant (figure 4.16), les 20 premières millisecondes sont quasiment identiques dans les deux cas de cette expérience, ensuite le premier résultat s’éteint, et le second continue à osciller. Les premières vibrations semblent apparaître avant l’impulsion, c’est en fait parce que le signal d’entrée n’a pas une amplitude nulle au départ.
Les points fixes peuvent être supprimés en rendant cyclique le réseau de points, par exemple, une droite peut devenir un anneau, un plan deviendrait torique, etc...
Prenons le cas d'un anneau de n points, chaque point i connecté aux points i + 1 modulo n et i - 1 modulo n. Initialisons toutes les positions à zéro (dans une dimension), sauf pour un point contenant une valeur impulsionnelle initiale arbitraire. Puis appliquons itérativement la procédure de tension en observant l'évolution des positions des points : La propagation de l'impulsion est symétrique, et les coordonnées augmentent indéfiniment dans le sens de l'impulsion initiale. Si nous introduisons une seconde valeur initiale (opposée à la première), les tensions se propagent également symétriquement mais cette fois, le système est globalement stable puisque la somme des positions reste nulle. Certains points particuliers peuvent apparaître (suivant le nombre de points n, et la position des impulsions initiales) : les nœuds du système vibratoire, dont la position est toujours nulle, les autres points oscillent, et finissent par se stabiliser (en fonction des paramètres de tension et d'inertie).
Nous avons implanté une règle où les dimensions interagissent : La tension est transformée en déplacement en appliquant une fonction de répartition :
Par exemple :
f () =
Nommons les coefficients de répartition 1/2 et 1/16 respectivement principal et secondaire. Avec un coefficient secondaire à zéro, les dimensions sont indépendantes. Avec des coefficients trop grands, le système est instable et explose rapidement. Ceci est dû à une augmentation de l'énergie à chaque étape du processus. Les résultats obtenus en réduisant les coefficients (pour avoir une déperdition d’énergie) montrent un comportement chaotique du système. Les signaux résultants sont difficilement exploitables.
Le carré de la distance euclidienne est calculé beaucoup plus vite que la distance elle-même lorsque l’on connaît les coordonnées cartésiennes de deux points. Ceci ressort immédiatement de la formule :
![]()
Dans la formule calculant l’effet d’un ressort deux distances apparaissent : la longueur du ressort au repos, et la longueur actuelle du ressort. Dans le calcul des longueurs des ressorts, nous avons substitué la distance par son carré et observé les effet visuels et sonores de cette transformation. Nous voyons immédiatement que les formes des systèmes de ressorts ne sont pas fondamentalement influencées par ce changement. Trois ressorts en triangle vont toujours rester en triangle, et l’effet de couplages élastiques appliqués sur eux les feront tourner, globalement de la même manière.
Le cercle, défini comme étant l’ensemble des points situés à une distance donnée d’un point particulier, garde un aspect circulaire habituel lorsque la distance est définie comme suit :
![]()
Alors qu’avec une métrique quelconque, le cercle prend un aspect différent. Par exemple, lorsque la distance est définie par la somme des valeurs absolues des différences des coordonnées, le cercle prend un aspect de losange. Le comportement des réseaux de ressorts serait alors modifié.
Pour la simulation de ressorts, nous avons typé les liens existants pour la simulation de couplages élastiques, et, dans la fonction de calcul de l’influence des liens sur les nœuds, nous calculons la tension appliquée par le ressort en multipliant la différence entre la longueur actuelle du ressort et sa longueur de repos par un coefficient mémorisé dans la structure représentant le ressort.
Les longueurs actuelles de chacun des ressorts sont calculées avant de traiter les tensions appliquées sur les noeuds.
tension = (longueur_actuelle - longueur_au_repos)
* coefficient_du_ressort
Si la tension est supérieure à 1, la valeur 1 est forcée[50]. Ceci permet d’éviter les explosions. En effet, lorsque la valeur de la tension est supérieure à l’unité, les déplacements des points influencés par cette tension vont provoquer une élongation du ressort plus grande que l’élongation originale, et dans les cycles suivants, les valeurs obtenues croîtront indéfiniment, provoquant l’explosion du système.
La suite du calcul est identique à celui des couplages. Finalement, les couplages sont des ressorts dont la tension est constante, ou plutôt, les ressorts sont des couplages dont la tension varie dynamiquement en fonction de la longueur.
Pour la production de signaux à partir de ces réseaux, les variations de tension des couplages élastiques correspondent à des variations de fréquence des sons obtenus. Les ressorts permettent donc d’introduire une variation de la fréquence.
Voici des exemples de sons produit par des simulations de ressort. Dans ces expériences, nous avons construit le système le plus simple possible : un seul ressort, attaché à une extrémité par un point fixe et à l’autre à un point mobile.

Figure 4.17 : Un réseau avec un ressort et un récepteur.
Dans le schéma de la figure 4.17, Le point fixe maintenant le ressort est figuré par un carré, le point mobile par un cercle, et à droite, l’icône représente un récepteur, chargé d’enregistrer les longueurs successives prises par le ressort au cours de la simulation. La ligne pointillée indique la liaison entre le ressort et le récepteur, elle n’apparaît (en plein) que lorsque l’on déplace le récepteur.
Les longueurs sont directement enregistrées en tant qu’amplitudes instantanées du signal produit.
Lorsque l’on déplace un des points, et que l’on lance la simulation, le point mobile se met à osciller. Nous montrons ci-dessous (figure 4.18) le phonogramme résultant de l’analyse par la transformée élastique du signal produit par une grande déformation du ressort (environ le double de la longueur de repos).

Figure 4.18 : Phonogramme résultant de la transformée élastique du signal produit par le ressort de la figure 4.17
Le phonogramme montre une baisse d’amplitude régulière[51] du début à la fin et au niveau des fréquences, une descente rapide suivie d’une faible remontée.
La chute initiale de fréquence s’explique intuitivement par la diminution progressive des valeurs de tension : la viscosité fait perdre de la vitesse, donc diminue l’amplitude, et entraîne des élongations du ressort de moins en moins grandes. Le temps mis par le ressort pour effectuer un cycle de variation de longueur augmente, et la fréquence baisse. Mais que ce passe-t-il pour que subitement la fréquence remonte ?
Ci-dessous (figure 4.19), un détail du point de rebroussement d’une courbe de fréquence.

Figure 4.19 : L’échelle des fréquences est exprimée en Hertz.
La figure 4.19 représente la transformée élastique d’un son produit par un ressort de coefficient 0.0001, viscosité 0.99999 avec la règle de calcul de la longueur par la distance euclidienne[52]. Les trois lignes correspondent à des harmoniques. Le phénomène, à cette échelle apparaît pratiquement symétrique dans le temps, mais on peut dire la même chose d’un simple signal sinusoïdal.
Le Point de rebroussement correspond au changement de régime d’oscillation.
Lorsque la déformation initiale est suffisamment grande pour que le ressort soit comprimé jusqu’à une longueur nulle, le point mobile est projeté vers le point fixe, et le dépasse. Il est alors repoussé de l’autre coté du point fixe, et le cycle recommence. Ceci correspond à un premier régime d’oscillation[53]. Le second régime apparaît lorsque la déformation initiale est faible. Le cycle du second régime est une oscillation autour de la longueur de repos, sans franchir le point fixe.
En une seule dimension, nous pouvons segmenter la droite en quatre zones séparées par le point fixe et les deux points situés de part et d’autre du point fixe, à la distance correspondant à la longueur de repos (figure 4.20).
attraction repos répulsion point-fixe répulsion repos attraction
------------->+<----------------+---------------->+<------------
Figure 4.20
En deux dimensions, la zone de répulsion forme un disque, et la zone d’attraction un anneau sans borne externe.
Le point de rebroussement observé dans la courbe d’évolution de la fréquence correspond au changement de régime d’oscillation (du premier au second régime), dès que la vitesse n’est plus suffisante pour affronter la répulsion avant le point fixe et passer dans la zone de répulsion opposée au point fixe.
Avec le même système (les mêmes paramètres pour les coefficients des ressorts et la viscosité), nous obtenons des résultats variant selon les conditions initiales : la position donnant un étirement du ressort, et la vitesse initiale du point (en module[54] et en direction) influençant le régime d’oscillation.
Lorsque la déformation initiale du ressort est faible, ou lorsque la viscosité est à 1, la fréquence reste constante.
En appliquant une viscosité différente selon les axes (figure 4.21), par exemple 1 en y et une valeur inférieure à 1 en x, la baisse de fréquence dépend de la direction dans laquelle oscille le ressort :

Figure 4.21 : La fréquence (axe vertical) varie d’environ 2000 à 400Hz, la durée totale est de 4 secondes.
En faisant un zoom sur la partie du signal effectuant la montée (figure 4.22), nous obtenons ceci :

Figure 4.22
Des harmoniques apparaissent (figure 4.22), elles étaient masquées dans l’image précédente par l’amplitude importante du début du signal, et la contrainte de l’échelle des gris limitée à 126 niveaux, elles sont accentuées ici par le fait que les valeurs de gris de cette image sont obtenues directement sans diviser le cumul par la fréquence des résonateurs. Les paramètres du ressort étaient de 1.10-6 pour le coefficient du ressort, et 0.9999 pour la viscosité en x et 1 pour la viscosité en y.
Les courbes précédentes montrent des paliers : la baisse de fréquence n’est pas régulière : elle est nulle quand la direction de l’oscillation est parallèle à l’axe des y, et maximale lorsqu’elle est parallèle à l’axe horizontal.
Dans la simulation, le temps étant discrétisé, la variation de vitesse (supposée continue dans un modèle physique), est ici approximée par une variation par paliers, le calcul est effectué comme si la vitesse restait constante pendant chaque intervalle de temps équivalent à un échantillon. Ceci est valable autant pour la simulation du ressort dont nous analysons le produit, que pour la simulation des couplages élastiques de la transformée qui permet l’analyse elle-même.
Un pas de simulation du mouvement revient à :
• Calculer l’accélération
• Augmenter la vitesse de l’accélération (multipliée par l’unité de temps).
• Augmenter la position de la vitesse (multipliée par l’unité de temps).
Si l’accélération est nulle, le mouvement est calculé correctement.
L’échelle de discrétisation du temps doit donc être choisie assez fine pour que la perte dans la valeur de la vitesse soit faible.
Les graphes de couplages élastiques peuvent produire des sons, mais peuvent également les filtrer, et permettre ainsi de les analyser. Nous exposons ici notre démarche pour la réalisation d'une connexion entre la représentation des sons par les phonogrammes et les capacités des couplages élastiques à produire et analyser les sons. Nous pouvons ainsi utiliser directement les graphes de couplages pour construire les phonogrammes (analyse par transformée élastique), et utiliser les phonogrammes pour commander le déclenchement des résonateurs pour la synthèse.
Nous avons fabriqué deux bancs de 10 oscillateurs, linéaires, formés de 7 points chacun, les extrémités étant fixes (les points fixes sont représentés par des carrés, les points mobiles par des cercles).
Nous avons choisi une règle de tension qui utilise pour chaque point : la position du point, la vitesse du point, et une variable similaire à un indice de frottement, induisant une perte d'énergie (pour se ramener à un système dissipatif).
La règle de couplage est la suivante :
Pour chaque point (traité en parallèle avec les deux variables de position présente et future) :
• accélération = somme des vecteurs formés par le point et chaque voisin, pondérés par la tension des liens.
• diminuer la vitesse du point de la valeur du frottement du point (incrémenter si la vitesse est négative, décrémenter si elle est positive).
• ajouter l'accélération à la vitesse.
• et enfin, ajouter la vitesse à la position.
La procédure calculant cette règle est donnée en annexe.
Chaque lien possède deux valeurs de tensions (une pour chaque sens, mais en fait, dans les expériences suivantes, les valeurs de tension ont toujours été réglées identiques pour tous les liens de chaque résonateur, et identique dans les deux sens). Nous parlerons donc de la tension d'un résonateur.
Dans cette expérience (figures 4.23 à 4.29), les tensions vont de 0.01 à 0.1 (de gauche à droite) augmentant par pas de 0.01, et la variable frottement est réglée à 0.001 pour tous les points.

Figure 4.23
Les symboles en dessous des résonateurs représentent des récepteurs (dont nous avons masqué les liens), ils permettent d'indiquer que l'on veut "écouter" des points et/ou des liens. Chaque récepteur génère un fichier d'échantillons (Nous décrirons l'interface graphique permettant de construire de tels graphes dans paragraphe Interface graphique pour les graphes de couplages élastiques ci-dessous).
Quand on relie un récepteur à un point, le récepteur cumulera à sa valeur de sortie la vitesse de ce point (différence entre sa position présente et future). Quand on relie un récepteur à un lien, c'est le vecteur formé par le lien qui est cumulé. On peut relier autant de points et de liens que l'on veut à chaque récepteur.
En déplaçant un point sur chaque résonateur (le premier point mobile en haut), nous déséquilibrons les résonateurs, et en enregistrant les sons ainsi produits (par les derniers points mobiles en bas), nous pouvons analyser les spectres des différents résonateurs : Les fondamentales valent respectivement : 180, 255, 316, 362, 406, 444, 480, 513, 546, et 576 Hertz environ (avec une fréquence d'échantillonnage réglée à 22050 Hertz).
Tous les spectres obtenus sont constitués de 5 partiels.
Par exemple, le cinquième résonateur vibrant seul donne un spectre contenant les fréquences 406, 787, 1114, 1367, et 1528 Hertz. Les valeurs des fréquences sont approximatives à quelques Hertz près.
Le nombre de partiels doit être en relation avec le nombre de points du résonateur, et leurs amplitudes dépendre du point écouté. Le nombre de partiels dépend des régimes oscillatoires possibles du résonateur, nous verrons apparaître les différents régimes au cours de l'expérience.
Connaissant dorénavant les fréquences propres des résonateurs, qui sont maintenant en position de repos, nous émettons un signal sinusoïdal sur chacun d'eux, à l'aide d’un émetteur (symbole en bas du graphe ci-dessous). Les émetteurs peuvent être connectés à un ensemble de points, et leur rôle est de modifier la position de ces points, avec la valeur des échantillons provenant d'un fichier. Ils permettent ainsi d'agiter le système avec un signal extérieur.
Les résonateurs dont un régime oscillatoire possède une fréquence correspondant à la fréquence du signal excitateur oscillent avec la plus grande amplitude. Sur le schéma ci-dessous, nous voyons nettement le cinquième résonateur réagir à sa fréquence fondamentale, en prenant un régime oscillatoire possédant un seul ventre, le point central, les point fixes correspondant aux nœuds.

Figure 4.24
Tous les résonateurs sont soumis au même signal sinusoïdal à 406.5 Hertz. Les résonateurs 1 et 2 ont une amplitude plus forte que la moyenne, ils possèdent un partiel de fréquence proche. Remarquons également les résonateurs à gauche du cinquième (les 3 et 4) qui montrent un léger ventre (leur fréquence propre n'est pas très éloignée, les filtres que constituent ces résonateurs ne sont peut-être pas extrêmement sélectifs).

Figure 4.25
Réponse au 786 Hertz : le second partiel du cinquième résonateur, nous observons un nœud (de vibration) au point central qui paraît immobile, et les deux ventres sont constitués de deux points chacun.

Figure 4.26
Réponse au 1115.4 Hertz : Le troisième partiel du résonateur 5, avec deux nœuds de vibration, et le deuxième partiel du résonateur 10, avec un nœud central. Pendant l’animation, les nœuds de vibration ne bougent pratiquement pas.

Figure 4.27
Réponse au 1368.6 Hertz : le résonateur 5 est dans son quatrième régime oscillatoire. Le dernier partiel du résonateur 4 : 1364 Hertz, est proche de cette fréquence, mais l'amplitude est moins forte.

Figure 4.28
Réponse au 1528 Hertz : nous voyons nettement le dernier régime oscillatoire du cinquième résonateur. L'amplitude est plus faible que pour les autres régimes, cela est dû à deux causes combinées : l'amplitude du signal excitateur est plus faible, et l'amplitude de cette fréquence dans le spectre du signal de résonance était déjà plus faible.

Figure 4.29
Ci-dessus, un nouveau banc de 10 résonateurs, avec des tensions variant de 0,11 à 0,20, et la réponse à un son composé de deux sinus à 650 et 750 hertz.
Les fondamentales des résonateurs sont :
604, 630, 655, 681, 705, 728, 750, 769, 794 et 814.
Les résonateurs 3 et 7 qui ont les fondamentales les plus proches ont pris leur régime fondamental avec la plus grande amplitude.
La hauteur du résonateur (la distance entre les points) n'influence pas sa (ou ses) fréquences propres.
Avec les valeurs des fréquences obtenues en regard des réglages de tensions, nous avons déterminé la formule donnant la tension à appliquer pour obtenir une fréquence particulière :
C'est une simple parabole, ayant cette forme, pour tous les partiels :
tension =
où f est la fréquence souhaitée, Fe est la fréquence d'échantillonnage, et k une valeur, spécifique de chaque régime d'oscillation.
Dans le cas de cette expérience, les valeurs de k sont approximativement (valeurs moyennes sur les résultats d'analyse des sons produits par les 20 oscillateurs ci-dessus) :
k k.Fe2 avec Fe=22050 Hertz
fondamental : 0,0068 3 308 790,66
2nd partiel : 0,0256 12 480 561,88
3ème " 0,0520 25 292 299,92
4ème " 0,0791 38 472 792,01
5ème " 0,0947 48 366 230,17
Un fait remarquable est que les partiels ne sont pas harmoniques.
Par exemple pour la valeur de tension 0,11 le fondamental est à 604 Hertz et le 2nd partiel est à 1170 (ce qui fait moins d'une octave, mais plus de onze demi-tons).
Nous pouvons maintenant construire automatiquement des systèmes de résonateurs adaptés aux fréquences spécifiques des phonogrammes. Nous pensons détecter simplement les résonateurs excités en faisant la somme des valeurs absolues (ou des carrés) des amplitudes des ventres des régimes fondamentaux, sur chaque tranche d'échantillons correspondant à une colonne de pixels dans le phonogramme.
Nous devons également analyser des systèmes vibratoires plus simples, faire varier le nombre de points et les règles de couplage, pour savoir si la mise en œuvre d'un tel système d'analyse sera moins coûteuse, en temps de calcul, que la transformée de Fourier, qui, quand elle est effectuée pour toutes les fréquences d'un phonogramme, s'avère excessivement lente.
Quand à la synthèse, nous pourrons mettre en vibration des résonateurs appariés aux résonateurs écoutés (de mêmes caractéristiques) avec un lien unidirectionnel, pour éviter les bruits d'attaque. En effet, quand on excite un résonateur avec le son qu'il a lui-même produit, le son produit n'est plus un son percussif, comme quand on déséquilibre le système artificiellement, mais un son avec une attaque plus douce et qui peut être entretenue, donnant la même différence que celle existant entre le son produit par les cordes pincées et celui des cordes frottées.
En attaquant au contraire les résonateurs productifs directement, nous devrions obtenir quelque chose similaire aux sons que produisent les Steel bands (Orchestres populaires de percussions faites avec des moyens précaires, boîtes de conserves, fonds de tonneaux martelés, etc... ) Utilisant une succession de sons percussifs très rapprochés et de faible amplitude, pour simuler les sons entretenus, et utilisant la multitude de fréquences des différentes percussions pour reproduire le spectre des instruments classiques, voir, la sonorité d'un orchestre complet.
La génération de trajectoires, au sens expliqué dans le chapitre précédent à partir d’un réseau de couplages élastiques peut être vue de plusieurs façons : par exemple, la simple conversion d’un réseau circulaire (c'est-à-dire un réseau où les points sont reliés entre eux pour former un cycle) dans le format de données des trajectoires, ou encore, la génération d’une trajectoire dont l’exécution produira le même son que le son produit par un ou plusieurs points du réseau.
La première solution ne semble pas très intéressante, d’une part parce qu’elle ne pourrait pas s’appliquer à tous les réseaux (les réseaux ne sont pas circulaires a priori), et d’autre part, le nombre de points d’une trajectoire (lié à la fréquence) est beaucoup plus élevé en général que le nombre de points d’un réseau.
La deuxième solution est plus intéressante du point de vue de l’exploration graphique des sons. Reconstituer une trajectoire à partir des caractéristiques du réseau (les points, les liaisons, les paramètres des couplages), nous semblait impossible. Nous avons exploité directement les mouvements des points pendant la simulation pour générer des trajectoires.
Le signal produit par une trajectoire n’est qu’une projection sur une dimension de la position du mobile. Pour reconstituer une trajectoire intéressante, c'est-à-dire à deux dimensions, et non une trajectoire linéaire, il nous fallait une seconde dimension. Nous avons utilisé la vitesse instantanée des points comme seconde dimension.
La trajectoire ci-dessous est construite dans l’espace position/vitesse (ou espace des phases) à partir du déplacement d’un nœud couplé par un ressort à un nœud fixe.
La position est l’abscisse du nœud (en abscisse également dans la trajectoire), la vitesse enregistrée est la différence entre deux positions successives au cours de la simulation (représentée en ordonnée). Des intersections peuvent apparaître dans les trajectoires car elles ne sont qu’une projection bidimensionnelle des trajectoires de l’espace des phases qui possède quatre dimensions.

Figure 4.30
La trajectoire (figure 4.30) débute à l’extérieur et son amplitude diminue à cause de la viscosité.
Sans viscosité, la trajectoire est fermée ou ne perd pas d’amplitude comme dans les exemples suivants (figures 4.31 et 4.32) :

Figure 4.31 Figure 4.32
Suivant les vitesses initiales, les trajectoires obtenues avec des systèmes équivalents sont très variables :

Figure 4.33 Figure 4.34

Figure 4.35 Figure 4.36
En augmentant la viscosité la trajectoire semble s’enrouler autour d’un point :

Figure 4.37 Figure 4.38
Toutes les trajectoires ont été générées pour une période choisie arbitrairement de 1000 échantillons.
Une trajectoire est constituée d’une suite de points reliés deux à deux par des couplages élastiques. Chaque point est relié au suivant et au précédent, et le dernier point est relié au premier pour former un cycle. Ces liaisons sont représentées de deux façons : Par des structures et des chaînages comme dans les couplage élastiques utilisés dans la partie graphique, et par un réseau à maillage linéaire en mode torique. La conversion vers un réseau élastique est donc triviale. Le seul problème est le nombre de points des trajectoires, beaucoup plus important que celui des réseaux. Cette conversion est techniquement possible mais ne présente pas d’intérêt particulier.
Le but de l'interface est de permettre la construction rapide de graphes : des points, reliés par des liens orientés, des émetteurs et des récepteurs, reliés aux points et aux liens. Pour limiter les manipulations avec la souris nous avons choisi d'interpréter les coups de souris en fonction de leurs caractéristiques : la forme, la taille, la position et l'instant de départ, sans avoir à sélectionner un outil particulier à chaque type d'action.
Nous distinguons les coups de souris formant une boucle, des autres, ouverts : les boucles ont leurs points extrêmes proches (valeur absolue des différences des coordonnées inférieure à un seuil).
Quand un clic débute dans une surface vide, nous enregistrons la liste des positions du curseur tant que le bouton reste appuyé (procédure mise au point pour la création des schémas de couplages). Puis nous calculons le cadre de cette trace (le plus petit rectangle aux côtés parallèles aux axes englobant entièrement la trace). Si le cadre est petit (hauteur et largeur inférieures à une taille donnée), nous créons un point, le point sera mobile si la trace forme une boucle (comme les cercles représentant les points mobiles), sinon le point sera fixe. Si le cadre est plus grand (environ de la taille des émetteurs et récepteurs), nous créons un émetteur pour les boucles et sinon un récepteur.
Si la trace est très dense (gribouillage, mesuré en fonction du rapport entre la longueur de la trace et le périmètre du cadre de la trace), nous effaçons les éléments dont le cadre est entièrement inclus dans le cadre de la trace.
Nous pouvons ainsi créer et détruire les points, de différents types, en utilisant un seul (l'unique) bouton de la souris. Maintenant, pour relier les points entre eux, il suffit de commencer la trace à l'intérieur du cadre d'un point, mais cette action peut avoir plusieurs interprétations :
Si la trace commence par un mouvement vers le bas, nous débutons le processus de liaisons des points, qui aboutit si le bouton est relâché avec le curseur dans le cadre d'un point connectable au point initial (ou sur une poignée (cf. ci-après) d'un lien, dans le cas où on relie un récepteur à un lien), et qui est interrompu si le bouton est relâché en dehors de tout point. Les points et les liens montrent leur sélection respectivement en inversant leur cadre et en augmentant la taille des poignées, ceci pour donner un feed-back à l'utilisateur lors de l'établissement d'une connexion.
Si la trace commence par un mouvement vers le haut, le point est déplacé (comme si on devait le décrocher), et suit les mouvements du curseur. Si ces mouvements sont trop brusques, le point est agité, secoué (mesure du rapport entre le nombre de changements de direction du curseur et la longueur courante de la trace), les liens de ce point sont alors détruits.
Enfin, si la trace commençant sur un point reste immobile un certain temps, sans mouvements ni vers le bas, ni vers le haut, le processus de couplage élastique est appliqué au graphe complet.
Pour faciliter encore la construction des graphes, nous relions automatiquement le point en cours de création au point créé précédemment si l'intervalle de temps entre les créations est réduit (en dessous d'une seconde environ). Ceci permet de créer des chaînes en cliquant une seule fois par point, et n'entrave pas la construction d'autres formes de graphes.
Lorsqu'un point est effacé (gribouillé), tous ses liens sont supprimés. Pour effacer, nous avons également donné la possibilité de cliquer sur un point en tenant la touche majuscule (équivalent d'un second bouton hypothétique), ceci permet en particulier d'avoir une commande pour effacer un lien particulier. Les liens sont désignés par leurs poignées. Les poignées sont visualisées par deux petits disques sur le trajet du lien, l'un est au centre du trajet, et l'autre marque le premier quart du trajet, leurs positions dissymétriques permettent de visualiser le sens du lien (significatif dans le cas de tensions distinctes selon le sens). Idéalement, les poignées devrait être placées symétriquement dans le cas où les tensions sont égales (ce qui n'est pas encore respecté). Les liens dont une des valeurs de tension est nulle voient leur trajet interrompu à la poignée située du côté du point ne subissant pas d'influence (sauf pendant l'animation, où pour accélérer l'affichage, nous limitons les calculs en utilisant une autre procédure).
Il reste toutefois à améliorer la façon dont les valeurs numériques sont saisies et affectées aux points et aux liens. Pour l'instant, une fenêtre indépendante, (non modale), affiche ces valeurs qui sont recopiées au moment de la création d'un élément, ou lors de la pression de la touche de validation (les valeurs sont recopiées dans le point sélectionné). La sélection est toujours le dernier point créé, déplacé ou désigné par le début d'une procédure de liaison. La touche de tabulation permet également de changer la sélection. Il devrait être possible de sélectionner des ensembles de points et de liens, pour leur réattribuer globalement de nouvelles valeurs.
L'utilisation de la transformée de Fourier pour l'analyse des sons en vue de produire des phonogrammes s'avère inexploitable à cause du temps de calcul. Nous décrivons ici les expériences et mises au point effectuées pour la réalisation d'un banc de résonateurs à couplages élastiques permettant de produire des phonogrammes à partir de sons échantillonnés.
Des physiciens du siècle dernier ont réalisé des appareils, constitués de résonnateurs (sic) de fréquences différentes pour analyser la composition des sons complexes (cf. Extrait sur les phénomènes physiques en acoustique, étude expérimentale du timbre des sons, en annexe).
Nous avons pensé utiliser la propriété physique du son qu’est la réfraction des rayons sonores pour bâtir un appareil permettant la décomposition spectrale immédiate des sons. En effet, on peut construire des lentilles convergeantes (en collodion empli d’hydrogène) pour concentrer les ondes sonores. Pourquoi ne pas construire un prisme sonore ? Les prismes de verre décomposent les rayons lumineux à cause de la différence de vitesse de propagation des différentes longueurs d’ondes, induisant une variation des angles de réfraction. Pour le son, le phénomène est similaire.
Le problème, est que les indices de réfraction, pour les ondes sonores, calculés entre des milieux tels que l’air et le verre, prennent des valeurs telles que le phénomène de réfraction disparaît presque totalement au profit de la réflexion. D’autre part, pour mener des expériences de ce type, un laboratoire spécialisé serait nécessaire. Ces éléments et aussi le manque de données sur les différentes vitesses de propagation du son (et des ultrasons) dans divers milieux nous ont fait abandonner cette piste.
Nous nous sommes donc orientés vers une simulation de résonateurs basés sur les couplages élastiques.
Voici la formule que nous avons testée en premier, elle est directement issue des règles de couplages des réseaux de couplages décrits dans le chapitre précédent, mais elle est simplifiée pour optimiser les calculs et convenir à une forme unique de résonateurs (les liens de couplage sont implicites).
accélération = (amplitude - 2 * position) * tension
vitesse += accélération
position += vitesse
si vitesse < 0
vitesse += frottement
sinon
vitesse -= frottement
si position > 0
cumul += position
sinon
cumul -= position
• amplitude est la valeur de l’amplitude instantanée provenant du signal à analyser.
• position, vitesse, tension et cumul sont des valeurs propres à chaque résonateur, le cumul est initialisé à 0 à chaque fenêtre du signal.
• frottement est une variable globale pour tous les résonateurs. Elle est contrôlable dans l’interface.
• Et enfin accélération est une variable locale temporaire.
Cette séquence est appliquée pour chaque échantillon provenant du signal à analyser (valeur de l'amplitude), et pour chaque résonateur.
Cette formule décrit le passage d'un instant t à l'instant t+1, par exemple la ligne :
position += vitesse
Est une simplification de :
position += vitesse * 1
où 1 représente l'unité de temps, ceci est l'intégration de la vitesse par rapport au temps. De même la vitesse est calculée par l'intégration de l'accélération par rapport au temps.
Les résonateurs sont constitués de trois points dans un espace à une dimension, Le point central (celui dont on calcule et conserve la position et la vitesse) est relié d'une part à un point dont la position est directement donnée par l'amplitude instantanée du signal, et d'autre part à un point fixé à l'origine.
la valeur de l'accélération est donnée par la somme des vecteurs partant du point central :
(amplitude - position) + (0 - position)
Puis la tension est appliquée par une multiplication par un coefficient de tension compris entre 0 et 1.
Les valeurs de position, vitesse et cumul sont conservées, pour chaque résonateur d'une itération à l'autre.
C'est la valeur du cumul qui est utilisée pour donner la valeur de gris d'un point de l'image résultant de l'analyse : Chaque ligne de l'image correspond à un résonateur dont la tension est réglée sur la fréquence correspondant à la fréquence de la ligne du sonogramme. Et pour la dimension horizontale, l'utilisateur spécifie un pas d'analyse en millisecondes par pixel. En fonction de la fréquence d'échantillonnage, nous déterminons le nombre d'échantillons par pixel. À chaque nouvelle colonne de pixels produite (par la transformation des valeurs des cumuls en niveaux de gris), nous réinitialisons les valeurs des cumuls à zéro.
Pour effectuer les tests, nous dessinons un sonogramme, nous générons le fichier du son correspondant par synthèse additive, puis nous analysons le son : Nous devons obtenir, comme résultat d'analyse, une image qui soit la plus proche possible de l'image initiale.
Les images obtenues par analyse avec cette règle ressemblent aux images initiales, la réponse en fréquence parait satisfaisante, mais elles sont floues, et brouillées par des bandes horizontales : les résonateurs résonnent trop longtemps.
C'est donc la partie de la formule qui gère la déperdition d'énergie qu'il faut modifier.
Les sons produits par la résonance propre[55] de tels systèmes ont une enveloppe[56] triangulaire (décroissance linéaire de l'amplitude).
S'il n'y a pas de perte d'énergie, l'enveloppe est rectangulaire (amplitude constante).
En présence d’une augmentation d'énergie, les sons sont rarement exploitables, car cette augmentation de l’énergie entraîne l’explosion, les points oscillants sont éjectés de plus en plus loin de l'origine.
Les systèmes les plus intéressants sont donc ceux qui dissipent l'énergie, et la dissipation est exprimée dans notre règle par une modification de la vitesse.
si vitesse < 0
vitesse += frottement
sinon
vitesse -= frottement
Ce que nous avons baptisé frottement est une force constante en module et toujours orientée dans le sens opposé à la vitesse.
Le résultat est une amplitude décroissant linéairement (s'il n'y a pas d'apport extérieur d'énergie), donc une enveloppe triangulaire. La vitesse est diminuée d'une constante à chaque unité de temps. Ce frottement est une accélération (dérivée de la vitesse).
Un autre moyen simple de réduire la vitesse est de lui appliquer un coefficient : la multiplier par une valeur comprise entre 0 et 1, à chaque unité de temps. Appelons ce coefficient la viscosité.
vitesse *= viscosité
Toujours sans autre apport énergétique qu'un déséquilibre initial, notre point subit une résistance à l'avancement suivant une progression géométrique. L'amplitude résultante décroît de moins en moins rapidement, donnant une enveloppe courbe, avec l'axe du temps en asymptote.
Le son produit par cette résonance propre est perçu comme ayant un aspect plus naturel que les sons ayant une enveloppe triangulaire. Son enveloppe ressemble plus aux enveloppes obtenues par des oscillateurs physiques (cordes pincées).
Un autre avantage de cette forme est que le réglage du coefficient est moins dépendant de l'amplitude initiale que ne l'est le réglage de la constante frottement. En effet, si nous voulons obtenir une durée de résonance particulière (ou d'un ordre de grandeur déterminé) pour une amplitude donnée, nous pouvons dans les deux cas trouver une valeur de viscosité ou de frottement. Mais si ensuite, nous faisons varier l'amplitude, le frottement devra varier beaucoup plus que la viscosité pour retrouver la même durée de résonance.
Le résultat des transformations obtenues par cette règle est considérablement amélioré. Les images ne présentent plus les lignes horizontales (dues au résonances perturbantes). Elles sont beaucoup plus proches des images initiales. En enregistrant de la voix, et en resynthétisant, après cette transformation, la parole est tout à fait compréhensible, le timbre de la voix également (on reconnaît le locuteur). La voix est toutefois transformée, ceci peut être dû aux battements produits par la somme de fréquences proches les unes des autres : Les résonateurs ayant une fréquence proche de celle contenue dans le signal vibrent, avec une amplitude s'amoindrissant avec la distance, mais leur signal doit perturber le résultat.
Les images résultant d'une analyse montrent quelques caractéristiques communes, que nous avons pu exploiter pour limiter la quantité de calculs nécessaire à leur production.
• Les sons couvrent rarement tout le spectre, on voit des zones denses et des zones vides.
• Les variations de valeurs présentent une certaine continuité.
• Autour d'un partiel, les résonateurs proches présentent une activité corrélée d'une part à la proximité en fréquence, et d'autre part, à l'amplitude de ce partiel.
• L'image résultante contient beaucoup moins d’informations que celle calculée par le banc de résonateurs. En effets, nos 2047 résonateurs produisent 2047 signaux amplitude/temps, avec une précision importante (calcul en double précision sur 12 octets), alors que l'image, finalement, ne représente que la somme des valeurs absolues des amplitudes sur une certaine durée (la durée correspondant à un pixel), et réduite à une valeur entière sur 7 bits.
Pour éviter les calculs inutiles, nous endormons des résonateurs qui n'ont pas produit pendant un certain temps (une durée équivalent à un nombre de pixels déterminé dans le programme). Mais les résonateurs doivent pouvoir se réveiller si le son analysé contient à nouveau leur fréquence.
Nous avons donc deux types de résonateurs : les insomniaques, un résonateur sur 16 répartis régulièrement sur tout le spectre, restent toujours éveillés et les autres, capables d'être endormis ou réveillés (figure 1.10).
Quand un résonateur insomniaque produit une valeur (non nulle), il réveille tous ses voisins (8 au dessus et 7 en dessous).
Ce procédé permet d'une part de rester sensible à toute la gamme de fréquences, et d'autre part, de concentrer les calculs uniquement sur les zones de fréquences présentes dans le signal[57].
L'analyse d'un son simple (sinus) est dorénavant jusqu’à 16 fois plus rapide que l'analyse d'un son complexe (avec de nombreux partiels).
Pour bien contrôler l'activité des résonateurs, nous utilisons deux seuils distincts sur les valeurs des cumuls ramenés à des valeurs de gris de l'image : le premier seuil est le seuil d'activité : au dessous de ce seuil pendant un certain temps (4 pas d'analyse actuellement) le résonateur s'endort. Le second seuil est celui à partir duquel les valeurs sont réellement intégrées à l'image.
La valeur de la tension est limitée, et en fonction des fréquences auxquelles le résonateur doit être sensible, la valeur de tension obtenue peut dépasser ces limites. En effet si la tension est trop forte, l’accélération devient telle que la position s’écarte de plus en plus de la position d’origine, alternativement positive et négative. Ce phénomène est dû à un sous-échantillonnage du mouvement de l’oscillateur. Pour résoudre ce problème, et obtenir des résonateurs sensibles à des fréquences aiguës, nous devons décomposer le mouvement de notre résonateur en plusieurs périodes à l’intérieur de l’intervalle de temps correspondant à un échantillon du signal.
Nous nommons cycle le nombre de périodes à effectuer pour un échantillon.
L’algorithme devient finalement le suivant :
Pour chaque période du cycle :
accélération = amplitude
accélération -= position
accélération -= position
accélération *= tension
vitesse += accélération
position += vitesse
fin
vitesse *= viscosité
si position > 0
cumul += position
sinon
cumul -= position
La règle de déperdition d’énergie (viscosité) peut n’être appliquée qu’une seule fois.
En augmentant la valeur du cycle, la tension peut être diminuée, et les résonateurs deviennent sensibles à une nouvelle gamme de fréquences.
Nous avons besoin de calculer les valeurs des cycles et des tensions des résonateurs en fonction des fréquences cibles.
Nous avons établi dans le chapitre précédent la relation
tension =
Où Fe est la fréquence d’échantillonnage.
Ceci reste valable quand la valeur du cycle est 1. Doubler le cycle est équivalent à multiplier par deux la fréquence d’échantillonnage.
La valeur limite de la tension est de 1. Nous calculons la fréquence maximale obtenue avec une valeur de tension < 1, par exemple 0.9.
tensionMax = 0.9
frequenceMax =
La valeur de k est obtenue par moyenne sur un ensemble d’expériences préliminaires où l’on connaît les valeurs des tensions et où l’on analyse les fréquences propres des résonateurs. La fréquence d’échantillonnage lors des expériences n’est pas nécessairement la même que la fréquence d’échantillonnage du signal à analyser.
La valeur du cycle est donnée par :
cycle = (frequenceCible / frequenceMax) + 1
calculé en entier
et la tension par :
tension = (frequenceCible/cycle)2 / (k * Fe2)
Il s’agit de transformer les valeurs obtenues dans le cumul de chaque résonateur, pour chaque fenêtre d’analyse (une fenêtre correspondant à la durée d’un pixel) en une valeur de gris pour un segment de phonogramme.
Les valeurs gris varient de 0 (absence de son) à 126 (amplitude maximale).
Le domaine des valeurs prises par les cumuls n’étant pas connu a priori, nous l’évaluons expérimentalement en agitant les résonateurs avec un signal aléatoire avant le traitement des échantillons à analyser.
Beaucoup de facteurs entrent en jeu dans le domaine des valeurs de cumul :
• Le contenu du signal lui-même, un bruit blanc ne donnera pas la même énergie qu’un son pur.
• La longueur de la fenêtre d’analyse.
• Le facteur de viscosité.
• La fréquence des partiels des signaux.
Dans notre première approche, un coefficient est déterminé d’après les résultats obtenus lors de l’agitation aléatoire préliminaire. En divisant le cumul maximal pour obtenir la valeur de gris maximale. Puis, le coefficient est réadapté, si nécessaire, pendant l’analyse. Ceci présente l’inconvénient majeur de changer la signification des valeurs de gris en cours d’analyse. Nous avons donc fourni la possibilité dans l’interface de régler un coefficient supplémentaire, permettant de forcer un diviseur de ce coefficient.
L’analyse de différents sons fournissait alors des images dont la forme correspondait au contenu spectral. Mais les amplitudes, c’est-à-dire les valeurs de gris de l’image, tout en étant cohérentes globalement, semblaient mal équilibrées par rapport aux fréquences. Les sons aigus avaient des valeurs de gris très fortes (sombres) et les sons grave des valeurs de gris très faibles. Les sons reconstitués par la synthèse additive du phonogramme résultant semblaient pourtant très proches des sons initiaux.
Nous avons donc cherché si une loi existait entre les valeurs obtenues et les fréquences des partiels. Pour cela, nous avons constitué des phonogrammes contenant des segments horizontaux (partiels de fréquence constante) de valeur constante (amplitude constante). Puis nous avons synthétisé le signal correspondant, et analysé ce signal par la transformée élastique.
Voici des exemples de résultat :
Avec un son harmonique :
fréquence niveau de gris
880.0 50
440.0 25
220.0 12
Avec un son inharmonique :
fréquence niveau de gris
839.654 24
984.207 29
1427.5 43
1884.96 58
Il apparaît clairement le rapport suivant : les niveaux de gris obtenus sont directement proportionnels aux fréquences. Dans le second exemple, le rapport fréquence/niveau de gris est environ 34. Nous devons donc diviser les valeurs des cumuls par la fréquence avant de produire les niveaux de gris. Les résultats obtenus après l’implémentation confirment ce point. Nous avons maintenant un équilibre entre les amplitudes relatives des différentes fréquences.
Nous devons vérifier à présent que pour une fréquence donnée, avec différentes amplitudes, le résultat donne bien les niveaux correspondants.

Figure 5.1
Pour cette vérification, nous construisons une image telle que celle présentée ci-dessus (grossissement X 2), contenant des segments horizontaux dont la valeur baisse régulièrement. Les trois premiers segments ont une valeur de 120 et les suivants baissent de 10 en 10 jusqu’à 30.
Puis nous synthétisons le son correspondant à l’image initiale, et nous appliquons la transformée élastique sur le résultat.

Figure 5.2
Ci-dessus (figure 5.2), le résultat de la transformée élastique du son synthétisé d’après l’image initiale (grossissement X 2). Les niveaux obtenus sont en rapport linéaire avec les niveaux de l’image initiale.
L’image initiale est nette, les segments ont une épaisseur de 1 pixel (sauf le premier segment d’épaisseur 3), la synthèse correspondante donnera donc des signaux sinusoïdaux purs.
Par contre, l’image résultant de l’analyse est floue, non pas dans la direction horizontale (temporelle) mais dans la direction verticale (fréquencielle). La fréquence du signal était de 2000Hz environ, la fréquence d’échantillonnage de 22000Hz et le pas de déplacement de la fenêtre de 20 millisecondes. Le flou vertical est lié à la mise en résonance des résonateurs par des fréquences proches de leur fréquence propre.
Figure 5.3
Ci-dessus (figure 5.3), le signal amplitude/temps correspondant à l’image initiale, et ci-dessous, le signal amplitude temps produit par synthèse du résultat de la transformée. Dans l’image du haut, nous observons une différence nette de l’enveloppe du premier segment par rapport aux suivants : l’épaisseur du segment provoque l’addition de fréquences proches induisant ainsi un battement. Dans l’image du bas, tous les segments ont une épaisseur supérieure à 1, et les battements sont beaucoup plus importants : ils modifient sensiblement l’amplitude.
Figure 5.4
Voici, pour comparer, un détail du second segment du son provenant de l’image initiale :

Figure 5.5
L’enveloppe est très régulière. Et, ci-dessous, le détail correspondant dans le son transformé :

Figure 5.6
Les battements provoquent des modulations d’amplitude.
Actuellement, seuls les réseaux élastiques et les réseaux à maillages cubiques sont utilisés pour la synthèse.
Les bancs de résonateurs sont une version simplifiée des réseaux élastiques, de manière à optimiser le procédé de transformée élastique. Les résonateurs sont dans une table, et le nombre de points mobiles par résonateur est fixé à un. Un point fictif fixé à l’origine et un point mobile fictif mû par le signal d’entrée sont intégrés directement dans la formule du calcul de l’accélération de l’unique point mobile.
Nous pourrions produire un signal en effectuant la somme des positions instantanées des points mobiles des résonateurs. Mais cela nécessite soit une source d’énergie externe, soit une déformation initiale du banc de résonateurs pour qu’une oscillation se produise.
La source d’énergie permettant d’exciter le banc de résonateurs pourrait être un flux MIDI. Mais le temps de calcul nécessaire à la simulation de la résonance est beaucoup trop long[58], par rapport au débit temps réel du flux MIDI. Toutefois, les flux MIDI peuvent être conservés dans des fichiers (fichiers MIDI) et dans ce cas, être traités en temps différé. Les produits de cette opération serait des signaux échantillonnés.
Le procédé d’analyse (transformée élastique) peut rapidement être transformé en filtre. Il suffit de constituer le signal formé par la somme des valeurs instantanées des positions de chaque résonateur. Ceci serait intéressant pour savoir ce que notre banc de résonateurs entend. L’expérience reste à réaliser.
Cette conversion serait intéressante, mais a priori délicate : la conversion d’un signal en un résonateur ou un réseau élastique capable de le générer. L’avantage immédiat d’une telle représentation serait sa compacité, mais les bénéfices viendraient surtout du moyen d’obtenir des sons de la même famille en modifiant les caractéristiques du résonateur résultant.
Tous les sons peuvent être représentés (avec plus ou moins de fidélité) par leur image dans l’espace temps/fréquence des phonogrammes. Mais seul, certains sons peuvent être générés par un réseau élastique excité par une impulsion initiale. Ces sons ont les caractéristiques suivantes : L’enveloppe d’amplitude décroît au cours du temps, les modulations de fréquence décroissent également, et, suivant la matière des objets percutés, les partiels harmoniques aigus voient leur amplitude augmenter ou diminuer. D’autres caractéristiques nous échappent probablement, mais ce sont les principales.
Nous avons pensé à des processus évolutifs, guidés par des mécanismes de feed-back pour d’une part augmenter la fiabilité du système actuel d’analyse par transformée élastique, et d’autre part pour tenter la génération de modèles de résonateurs à partir de sons échantillonnés.

Figure 5.7
Dans ce schéma (figure 5.7), nous montrons deux cycles possibles, à partir d’une image existant sous la forme de phonogramme, soit le passage par les modules de synthèse externes, soit le passage par la synthèse additive interne. La première offrirait la possibilité de faire varier les timbres des modules externes, et d’utiliser la modulation de fréquence par exemple. Ceci permettant éventuellement d’obtenir des modèles élastiques de tels timbres. Il est en effet possible d’utiliser une modification d’une méthode d’analyse du son pour obtenir la synthèse de familles de timbres (LANSKY, STEIGLITZ 1981)
La seconde possibilité est préférable du point de vue de l’implémentation. Toutefois, la mise en œuvre d’un tel système demanderait un temps de développement hors de portée dans ce cadre.
Le contrôle s’effectuerait à partir du calcul du delta séparant le phonogramme initial et le phonogramme résultant de l’analyse du signal produit par les résonateurs. Le module de contrôle interviendrait alors sur l’évolution des résonateurs.
Ceci est à rapprocher des expériences faites sur l’utilisation de techniques d’évolution génétique pour réaliser le paramétrage de système utilisant la synthèse par modulation de fréquence (HORNER 1993).
Les trajectoires et les réseaux de couplages permettent de créer des fichiers de sons échantillonnés. Ces derniers peuvent être filtrés par les réseaux de couplages, analysés par la transformée élastique pour être intégrés dans des phonogrammes. Les phonogrammes sont une représentation graphique des sons et des séquences musicales permettant une vision tant locale, microscopique, que globale, macroscopique, grâce au possibilités du zoom. Ils établissent un lien entre la lutherie, la microstructure, et la composition, voire l’orchestration, la macrostructure.
Ces possibilités graphiques de l’atelier sont complétées par des applications dont la vocation est algorithmique. La production de ces générateurs et séquenceurs étant intégrable dans les phonogrammes, ou directement utilisable en temps réel, ou encore combinable avec l’exécution temps réel des phonogrammes. Nous présentons Métronome, le cœur de ces applications, dans le chapitre suivant.
L’activité de composition musicale est très proche de l’activité de programmation, les compositeurs comme les programmeurs manipulent des abstractions, conçoivent des structures, établissent des relations entre ces structures, et produisent généralement un canevas décrivant le déroulement futur d’une succession d’événements. Dans (ENGLERT 1981), Giuseppe ENGLERT conclue : Mon but est de synthétiser quelque chose d’entièrement artificiel mais profondément cohérent. Le langage musical est pourtant loin des langages de programmation et les domaines musical et informatique semblent a priori distants : on associe l’informatique aux sciences exactes et la musique à l’art. Pourtant la liaison entre la physique et la musique date de Pythagore et les liens entre les mathématiques et la musique sont nombreux : Par exemple la musique de Y. XENAKIS, les systèmes d’analyses et de composition d’André RIOTTE, la musique fractale d’Horacio VAGGIONE, etc...
Nous présentons tout d’abord le cœur des applications génératrices de flux MIDI en temps réel. Puis nous verrons différents exemples d’applications basées sur ce noyau modèle. En particulier l’application Métro3 développée en collaboration avec Giuseppe ENGLERT (ENGLERT 1993), un séquenceur algorithmique interactif.
Avant tout, nous voulons situer ce module dans son contexte, et pour cela, nous devons décrire brièvement l’infrastructure des applications telles que nous les concevons pour les intégrer au système.
Le système hôte[59] est structuré en différentes couches, comprenant des drivers (modules de bas niveau) et des managers (modules de plus haut niveau). Par exemple, la couche graphique de base, nommée QuickDraw, permet toutes les opérations graphiques courantes (tracé de droites, de rectangles, etc....). Sur cette couche, s’appuie le gestionnaire de fenêtres (WindowManager) qui lui-même sert de support au gestionnaire de dialogues (DialogManager) (cf : figure 6.9).
Une application standard fait appel au gestionnaire de fenêtres pour ouvrir une fenêtre, puis utilise des routines de QuickDraw pour en tracer le contenu.
Le programme principal, comme sous X Window ou encore sous Windows, n’est qu’une boucle infinie faisant appel à une fonction pour savoir si un événement s’est produit, puis réagit le cas échéant suivant le type d’événement, entre autres :
• Retracer le contenu d’une fenêtre
• Réagir à un déplacement du curseur de la souris
• Réagir à un clic de la souris
• Être prévenu d’une prise ou d’une perte de contrôle par l’application (dans le cas de plusieurs applications lancées simultanément).
• Être prévenu d’un changement de l’activité d’une fenêtre (la fenêtre passe sous une autre fenêtre, ou au contraire, devient la fenêtre active).
• Effectuer la fermeture d’une fenêtre.
Pour gérer de façon transparente ces événements du système, nous avons utilisé un squelette d’application nommé TransSkel (DUBOIS 1986) auquel nous avons adjoint des fonctionnalités[60]. Ce premier squelette d’application permet, lors de la création d’une fenêtre, de lui adjoindre les références aux fonctions qui seront automatiquement appelées lors d’un événement la concernant.
Une fonction différente traite chaque type d’événement (voir la liste ci-dessus). Ceci permet de gérer indépendamment, dans une même application, différents types de documents ainsi que de multiples fenêtres de chaque type, tout en gardant une certaine indépendance vis à vis du système hôte.
Nous avons enrichi ce squelette d’une librairie de fonctions utiles à la gestion de documents associés aux fenêtres. Les documents sont maintenus sous deux formes possibles : sous une forme volatile, modifiable, dans des structures de données en mémoire, et sous une forme plus stable, figée dans un fichier.
Un module de cette bibliothèque tel que le module Enregistreur, décrit les comportements standards des documents dans leurs relations avec les fenêtres de visualisation. Lors de la création d’une fenêtre, un document vierge est créé en mémoire, sans être associé à un fichier. Lors de l’ouverture d’un fichier, l’enregistreur lit ce fichier, et reconstruit en mémoire une structure identique à celle qui avait été sauvegardée. Lors de la fermeture d’une fenêtre, si le document a été modifié en mémoire, l’enregistreur propose la sauvegarde avant la fermeture, l’oubli des modifications, ou encore l’annulation de la commande. Évidemment, l’enregistreur ne connaît pas la structure interne du document, car il doit être utilisable pour tout type de document, et n’implémenter que les réflexes attendus dans une ergonomie standard. L’enregistreur connaît les pointeurs vers les fonctions à appeler pour la lecture et pour l’écriture de la structure de donnée associée à une fenêtre. Il doit simplement être renseigné lors d’une modification apportée à un document, et il gère les appels à toutes les routines standard des dialogues, d’ouverture, de création et de fermeture des fichiers.
Cette bibliothèque, la Boîte à fenêtres, s’appuie également sur une autre bibliothèque, la Boîte à outils, qui elle est écrite en C pur, mis à part un appel à la fonction d’allocation et de libération de mémoire du système.
La boîte à outils contient un ensemble de modules permettant une gestion pratique de listes monodirectionelles, de doubles chaînages (listes bilatères, bidirectionnelles), de parcours de chaînages[61], de piles, de cycles (ou listes circulaires), d’associations clef-valeur (ou espaces d’adressages virtuels), de dictionnaires, d’ensembles, de bijections, de graphes, et d’éléments que nous appelons déclencheurs et surfaces sensibles. Les déclencheurs permettent d’associer des données et des fonctions, et les surfaces sensibles permettent d’associer des listes ordonnées de déclencheurs à des points d’un plan[62].
Chaque module est constitué d’une description de structures et de fonctions de manipulation de ces structures. A priori, les couches utilisant ces modules n’ont pas à en connaître l’implémentation (les champs des structures par exemple). Cette encapsulation est évidemment à rapprocher de celle des langages à objets (KRIEF 1990) (GOLDBERG, ROBSON 1989) (LESBROS 1989), mais n’intègre pas de notion d’héritage, ni de calcul dynamique de fonctions. La simple encapsulation des données, et la description de différents types de collections homogènes suffit à résoudre la plupart des problèmes rencontrés sans avoir à subir une doctrine de programmation tyrannique.
Des entorses à l’encapsulation peuvent être faites, en connaissance de cause (ou plutôt d’effet), pour optimiser des traitements intensifs, ou simplement pour adjoindre un traitement particulier dans une couche de niveau supérieur. Ceci n’est fait que si la généralisation de cette action paraît dénuée d’intérêt[63].
Dans la plupart des cas, un nouveau traitement peut être généralisé, et vient enrichir la bibliothèque. La fréquence d’ajout de nouvelle fonctionnalité dans un module diminue au cours de son utilisation : la bibliothèque se stabilise. D’autre part, pour les éléments de base, l’implémentation originale n’a jamais été remise en question : les listes possèdent toujours un champ car et un champ cdr.
Le module d’allocation de mémoire a été particulièrement conçu pour l’allocation et la libération intensive de blocs de mémoire dont la taille n’excède pas 64 octets. Tous les autres modules de la boîte à outil, ainsi que tous les modules externes gérant des structures de données font accès à ce module.
Notre boîte à outils est strictement portable.
Dans cette section nous présentons un système permettant de visualiser les structures de données allouées dynamiquement par les programmes écrits en langage C, ainsi que les chaînages entre ces structures. Ce système est un outil de développement et d’observation complémentaire de la boîte à outils et de la boîte à fenêtres.
Notre système n'implique aucune modification du programme qui doit être observé. Aucune description des structures de données à visualiser n'est nécessaire. Le système redéfinit uniquement la fonction d'allocation dynamique et la fonction de libération associée[64].
Enfin, la simplicité de son principe de fonctionnement doit permettre un portage rapide sous d'autres environnements que celui de son implémentation actuelle sur Macintosh.

Figure 6.1 : Représentation par notre système d’une arborescence binaire : les structures de données allouées pour les arbres de pondération des tirages aléatoires (cf. § Arbres d’appels de fonction pseudo-aléatoire).

Figure 6.2 : L’arbre d’appels de fonction pseudo-aléatoire dont les structures internes sont visualisées par la figure 6.1.
Notre système se base sur les données suivantes : la fonction d'allocation, telle que malloc par exemple, reçoit la taille (en octets) du bloc mémoire à allouer, et délivre une adresse en retour :
void *malloc(long size);
La fonction de libération reçoit l'adresse d'un bloc précédemment alloué et doit rendre disponible ce bloc pour une allocation ultérieure éventuelle[65] :
void free(void *ptr);
Aucune information concernant le type des données dans les structures allouées n'est fournie au système de visualisation.
Nous associons à l'adresse de chaque bloc alloué une structure portant l’information sur sa représentation graphique (la couleur et la position) et sur l'objet représenté, sa taille et son adresse.
typedef struct rep2D
{
RGBColor couleurFond, couleurCadre;
Rect cadre;
long taille;
void *objet;
} rep2D;
L'association entre les objets et leur représentation est effectuée dans un arbre binaire (structure assoc [66]de la boîte à outils) permettant une recherche dichotomique basée sur les bits formant l'adresse de l'objet : connaissant l'adresse d'un objet on obtient (au bout de 32 indirections au maximum[67]) sa représentation graphique. Connaissant une représentation, l'accès à l'objet est direct. L'arbre d'association permet également d'énumérer tous les couples (objet, représentation). Le second appel de la fonction récursive de parcours de l’arbre est remplacé par une affectation des paramètres (avec les valeurs des arguments) suivie d’un branchement au début de la fonction, ceci étant directement inspiré du système d’interprétation itératif des fonctions récursives décrit par Patrick GREUSSAY (GREUSSAY 1977).
L’information graphique pourrait se limiter à un point donnant la position de la représentation, de même, l’information concernant l'objet pourrait ne décrire que sa taille, puisque d'une part, la couleur et la taille du cadre sont calculées à partir de la taille de l'objet (cf. § Représentation graphique des blocs de mémoire ci-dessous), et d'autre part, chaque fois que l'on manipule une représentation, nous avons obtenu l'adresse de celle-ci à partir de l'adresse de l'objet qui est alors connue. Nous avons mémorisé la couleur et le cadre dans la structure pour optimiser la vitesse d'affichage.
La structure de représentation graphique minimale (occupant 64 bits) pourrait être :
typedef struct rep2Dminimale
{
Point position;
long taille;
} rep2Dminimale;
Quand nous affichons un objet, nous affichons également les liens partant vers d'autres objets. Heureusement, tous les pointeurs ont la même taille, ainsi nous pouvons scruter la structure en se déplaçant de x octets en x octets[68], à la recherche d'une adresse que l'on a déjà associée à une représentation.
Seuls les pointeurs vers des structures allouées par notre système sont visualisés[69]. Il est peu probable d'autre part de confondre des données brutes avec des pointeurs[70].
Chaque bloc alloué est représenté par un rectangle affiché initialement[71] dans une position aléatoire à l'intérieur de la partie visible de la fenêtre de visualisation. La largeur du rectangle est fixe, et la hauteur est variable selon la taille du bloc et limitée à un maximum. Sur les écrans en couleur, le rectangle est rempli avec une couleur liée à la taille, et détouré par un cadre plus sombre. Notre système est indépendant des structures de données visualisées et de leur format, la couleur et la taille des rectangles aident toutefois au repérage des types des structures[72] allouées par le programme à visualiser.
Les pointeurs contenus dans une structure et désignant une autre structure sont représentés par des flèches[73]. Le point d'origine de la flèche, renforcé par un ovale, est calculé proportionnellement à l'offset du pointeur dans la structure de départ, et le point d'arrivée est le milieu du sommet du rectangle représentant la structure désignée.

Figure 6.3 : Un exemple de visualisation des structures allouées par le programme de dessin de schémas (figure 6.4). Le rectangle de droite (blanc) represente le schéma, il pointe vers une des trois cellules (gris sombre). à gauche , la structure représentant la flèche (figurée par le rectangle plus clair d’où partent trois flèches) pointe vers le début de son trajet, et vers les cellules de départ et d’arrivée. La cellule représentée à gauche pointe vers la cellule du centre car elle est englobée par celle-ci. La cellule centrale pointe vers une chaîne de caractères (en bas à gauche).
Les pointes des flèches sont formées d'un triangle orienté selon une des huit directions[74] possibles en fonction du trajet de la flèche.

Figure 6.4 : Le schéma dont on a visualisé les structures internes figure 6.3.
A des intervalles réguliers définis par l’utilisateur, par exemple toutes les secondes, si le système n'est pas occupé[75], la visualisation des liens entre les structures est mise à jour. Cette mise à jour est lancée par la fonction de traitement des événements systèmes associés à la fenêtre.
Les liens sont également mis à jour lors d'une allocation ou d'une libération[76].
Le placement aléatoire des représentations des blocs aboutit rapidement à un fouillis inextricable ! Pour lutter contre le désordre, nous offrons d'abord la possibilité de déplacer (avec la souris) les rectangles représentant les blocs (cf § Manipulation des représentations). Puis nous permettons aux flèches représentant les pointeurs d'effectuer une traction sur les rectangles représentant les structures, comme si les flèches étaient des élastiques, cherchant en permanence à minimiser leur longueur.
Mais si toutes les structures d'une liste chaînée (ou de tout autre graphe) étaient ainsi soumises aux forces élastiques, elles s'effondreraient les unes sur les autres. Pour éviter l'effondrement, certaines structures sont fixées à la fenêtre et résistent aux couplages élastiques : Nous fixons les structures ayant moins de deux voisines, ainsi que les structures n'ayant soit aucune flèche partante, soit aucune flèche incidente.

Figure 6.5 : Visualisation d’une liste chaînée de quatre structures. Les éléments n’ont pas été déplacés manuellement : la position est déterminée au hasard, et les tensions élastiques ont déplacé les doublets. Le rectangle du bas représente un pointeur nul. Nous allons appliquer la fonction reverse sur la liste et extraire quelques étapes.

Figure 6.6 : Après le premier changement.

Figure 6.7 : deux éléments sont traités.

Figure 6.8 : La liste est renversée complètement.
Pour effectuer un pas de calcul, nous parcourons l'ensemble des couples (objet, représentation), et pour chaque couple nous calculons l'ensemble des liens partants de cet objet et l'ensemble des liens incidents. Le calcul des liens partant est proportionnel à la taille de l'objet, alors que le calcul des liens incidents est proportionnel au produit du nombre d'objets par leur taille. Lorsque l'objet est considéré mobile (s'il possède au moins un lien partant et au moins un lien incident), nous calculons la somme des vecteurs formés par les liens (en considérant l'objet observé comme origine des vecteurs). Cette somme est divisée par le nombre de liens, et, dans chacune des dimensions (horizontale et verticale), si la valeur absolue est non nulle, un déplacement de la moitié de cette tension est appliqué à l'objet[77].
Le calcul de la tension élastique est désactivable, de manière à permettre éventuellement de contrôler manuellement la place des éléments.
Pour manipuler les représentations à la souris, nous calculons différents sous-ensembles à partir de la structure dans laquelle l’utilisateur clique :
• Le nœud lui-même
• L’ensemble des nœuds connexes (liens partants et incidents)
• L’ensemble des fils (nœuds connexes par les liens partants uniquement).
• L’ensemble des feuilles des fils (les nœuds terminaux).
A ces différents sous-ensembles, nous pouvons appliquer le déplacement ou l’effacement.
L’effacement consiste à transférer la représentation graphique d’un objet dans un second arbre d’association qui n’est pas visualisé. Nous pouvons réafficher l’ensemble des représentations par l’opération inverse (la position des représentations étant conservée ou recréée dynamiquement, au choix de l’utilisateur).
Nous pouvons également[78] effacer toutes les représentations sauf celle désignée, puis, réafficher progressivement les représentations des fils (de premier degré) des structures désignées. Ceci s’avère très pratique pour l’observation sélective d’un sous-ensemble d’objets dès que le nombre des représentations grandit.
Enfin, nous avons ajouté un champ dans la structure des représentations pour mémoriser un numéro d’ordre de création (équivalent à une date). Ce champ nous permet d’avoir une visualisation chronologique des allocations de mémoire.
à partir d’un nœud quelconque, nous pouvons calculer l’ensemble des feuilles accessibles par les liens partants. Les feuilles sont parmi les éléments ne subissant pas la force élastique, et constituent des points d’accroche. En itérant sur toutes les représentations visualisées, et en appliquant un déplacement (x, y) (par exemple (1, 3)) à chaque feuille atteinte par chaque représentation, les feuilles de la fin d’une liste subissent une translation totale plus importante que celles du début de la liste. Ceci a pour effet d’ordonner graphiquement la liste. Les racines des arbres ne subissent pas de translation, et les feuilles de niveau n subissent n fois la translation. Les arborescences sont elles aussi ordonnées, mais les branches gauche et droite des arbres binaires restent superposées. Ceci permet toutefois le repérage rapide des racines.
Ce système de visualisation possède indubitablement un intérêt pédagogique : la matérialisation des structures et leur mise à jour concrétise immédiatement les manipulations des structures paraissant terriblement abstraites lorqu'elles ne sont vues que sous leur forme littérale.
Nos choix arbitraires, concernant la forme de représentation, ont surtout été guidés par nos habitudes personnelles dans la schématisation les structures et les chaînages.
Notre boîte à fenêtres gère les documents et inclue TransSkel ainsi que TransEdit (DUBOIS 1986) (un module spécialisé dans la gestion des documents textuels). Nous avons adjoint à cela un module permettant la gestion des interfaces non modales pour la saisie de paramètres : Descriptions de Contrôles.
Les boîtes de dialogue non modales sont nécessaires à l’affichage et à la saisie de valeurs numériques ou de textes, de drapeaux ou encore d’alternatives, par l’intermédiaire d’affichages statiques, de champs de saisie, de champs associés à des ascenseurs, de cases à cocher et de boutons de radio (sélection disjonctive exclusive d’alternatives). Ces dialogues et leurs contrôles, sont créés dans un éditeur de ressources, puis, habituellement, la mise en œuvre s’effectue par des appels à des fonctions du système (DialogManager, ResourceManager), pour charger les ressources, les afficher, obtenir ou modifier le contenu des champs, convertir les champs numériques, etc...
Notre module permet une gestion simplifiée de toutes ces opérations : en effet, il nous suffit, pour lier une variable à un champ de saisie, d’appeler depuis une routine d’initialisation, une fonction correspondant au type de contrôle souhaité avec en paramètre un identificateur du dialogue et du contrôle, et l’adresse de la variable à lier. Éventuellement, nous pouvons fournir un pointeur vers une fonction à appeler en cas de modification par l’utilisateur de la valeur du contrôle. Dès lors, toute l’interface est gérée : si l’utilisateur modifie le champ, la variable est mise à jour, et inversement, nous disposons d’une unique fonction (quelque soit le type de variable) pour mettre à jour l’affichage concernant une variable donnée.
Les boîtes de dialogue peuvent également contenir des boutons que l’on associe à des fonctions.
Nous n’avons pas utilisé de générateurs d’interfaces, car ceux-ci produisaient un code redondant et spécifique du système. En outre, la personnalisation du code produit était à refaire à chaque modification des contrôles. Les générateurs actuels, tel VisualC++[79], sont plus souples, mais le code produit est très important[80].
Finalement, pour construire une application multifenêtre, multidocument, il nous suffit de copier le modèle de programme principal, de changer les noms des fonctions associées aux événements de fenêtre, et de lecture et écriture de documents, et enfin de connecter les paramètres globaux aux contrôles. Notre squelette est prêt à être spécialisé.

Figure 6.9
Ce schéma (figure 6.9) résume les différents niveaux décrits ci-dessus. Il n’est pas exhaustif, mais donne les relations principales. Par exemple, l’application peut directement faire appel à des routines de QuickDraw ou à différents modules du système non figurés ici, mais nous avons tenté de limiter les appels aux éléments spécifiques, en encapsulant ces appels dans des bibliothèques qui seront en principe les seules à être modifiées lors d’un éventuel portage.
Le module Métronome n’est pas sous forme de bibliothèque, mais c’est également un squelette à recopier et à modifier.
Il permet principalement la gestion des entrées et sorties MIDI.
Son principe est le suivant :
• Pour la réception :
Lors de la réception d’un message MIDI, le message est décodé, et une sélection est appliquée suivant le type du message et l’intérêt que l’on porte à ce type de message dans l’application. Par exemple une application réalisant un enregistrement du flux MIDI conservera dans une liste la totalité des événements reçus. Une application réagissant aux hauteurs des notes ignorera tous les messages concernant les changements de timbre, etc.
La réception du message est faite sous interruption, et certaines précautions sont à prendre dans l’écriture de la fonction de réception. Par exemple l’impossibilité de faire appel à des routines graphiques ou à des routines allouant de la mémoire.
• Pour l’émission :
Une fonction nommée Métronome est appelée par interruption (avec les mêmes contraintes que précédemment). Elle déploie l’algorithme de production du flux MIDI pour une petite période de temps. Cette période de temps est déterminée par la fonction Métronome elle-même, en effet la valeur de retour de la fonction (un entier long), correspond au nombre de millisecondes séparant la terminaison de l’appel courant d’avec l’appel suivant de la fonction Métronome.
Dans la fonction Métronome, des événements MIDI (structures décrivant des messages MIDI) sont préparés pour couvrir la période à venir.
Nous nous appuyons sur le système MIDIShare (ORLAREY 1989) (FOBER 1995) qui permet la gestion des messages MIDI sous la forme d’événements. Ce système permet en outre la gestion différée des événements et des appels de fonction. On peut, par exemple demander l’exécution de telle fonction, avec tels paramètres, à telle date. Le temps dans ce système est compté en nombre entier de millisecondes, avec un repère global à toutes les applications utilisant ce système.
Un autre avantage de ce système est la connectivité des applications l’utilisant : chaque application peut émettre les messages MIDI vers toutes les autres. Une application (msConnect, développée par le GRAME) permet de connecter les applications entre elles ou avec les entrées/sorties matérielles.
Ceci nous permet, d’utiliser un ensemble d’applications effectuant des générations ou des filtrages de flux MIDI, et de connecter par exemple la sortie de Métro3 sur l’entrée de Phonogramme, pour enregistrer sous forme de phonogramme une séquence musicale élaborée dans le séquenceur algorithmique.
Comme pour la conversion inverse (depuis les phonogrammes vers la norme MIDI), nous proposons deux méthodes : une en temps réel (l’enregistrement) et l’autre en temps différé, à partir d’un fichier MIDI. Cette fois, la conversion temps réel peut être plus longue que celle en temps différé. La conversion est immédiate, en effet, chaque note reçue ou lue est transformée en un segment du phonogramme, ou, plus exactement, en un coup de pinceau appliqué dans le phonogramme. Cela permet par exemple de donner une épaisseur à chaque trait, ou encore d’ajouter automatiquement des harmoniques aux notes provenant du flux MIDI en activant le pinceau à harmoniques.
Une amélioration envisagée mais non implémentée serait de lier les messages MIDI de changement de timbre (program change) au changement de pinceau, et de permettre d’utiliser les pinceaux à timbres lors de cette opération.
Les modules de traitement MIDI reçoivent un flux MIDI entrant, l’interprètent, et réémettent un flux MIDI transformé. L’interprétation peut être simple ou sophistiquée, suivant le type de transformation effectuée. Un exemple simple est le changement des numéros de canaux des messages, ou encore la génération d’un écho ou encore la transposition des notes du flux. Un exemple sophistiqué est l’interprétation des structures rythmiques et/ou harmoniques du flux entrant, associée au paramétrage d’un générateur rythmique et mélodique tel que le module Alpha présenté dans le paragraphe Le module Alpha.
Les modules de traitement MIDI peuvent être matériels ou logiciels, nous n’avons cependant développé que des modules logiciels.
Les traitements effectués dans l’application Métro3 ne le sont pas au niveau des flux MIDI, mais directement sur les séquences numériques représentant les mélodies ou patterns mélodiques. Nous avons développé le séquenceur algorithmique interactif Métro3 en collaboration avec Giuseppe ENGLERT (ENGLERT 1993).
Nous décrivons à présent les algorithmes que nous avons développé pour générer automatiquement les rythmes et la dynamique des patterns mélodiques.
L’unité indivisible du temps est spécifiée en un nombre entier de millisecondes et nommée le tempo. Les tempi de chaque voix sont indépendants et varient entre 60 et 500 millisecondes par pulsation.
Nous étudierons le procédé pour une seule voix, sachant qu’il doit être réitéré pour chacune d’elles et que les paramètres de l’algorithme sont propres à chaque voix.
Les unités de temps sont regroupées en cellules rythmiques appelées mesures. Le nombre d’unités par mesure varie de 1 à 24.
La mesure sera décomposée en sections de longueurs variables dont la somme des longueurs doit être égale au nombre d’unités par mesure. Chaque section représentera un événement sonore, une note dont la hauteur est déterminée par la séquence en cours d’exécution.
La méthode de décomposition utilisée est très simple mais elle garantit le respect de la durée des mesures et fournit des cellules rythmiques intéressantes :
• Pour diviser une longueur, nous choisissons une valeur aléatoire entière comprise entre 1 et la longueur - 1, cette valeur donne la longueur d’une première section, la seconde section aura pour longueur la longueur totale moins la longueur de la première section. La longueur totale est ainsi divisée en deux parties égales ou inégales ; puis, nous décomposons récursivement chaque section avec le même procédé.
• L’algorithme se termine dans deux cas : soit la longueur à décomposer est unitaire, soit une profondeur de décomposition maximale, déterminée par un paramètre est atteinte.
Le paramètre de profondeur est accessible dans l’interface, et varie de 0 à 6.

Figure 6.10
Par exemple (figure 6.10), dans une mesure de 9 unités décomposée jusqu’à la profondeur 4, nous observons que les durées des sections sont toutes unitaires. En choisissant d’autres points de décomposition, comme dans la figure ci-dessous, ou en limitant la décomposition à une profondeur moindre, des cellules rythmiques diverses sont formées. à la profondeur deux, la décomposition est 1 3 2 3 alors que dans la figure suivante on obtient 2 5 1 1.

Figure 6.11
Avec une profondeur nulle, les mesures ne sont pas décomposées, et toutes les notes ont la durée d’une mesure. Avec une profondeur trop importante (en fonction de la durée de la mesure) la décomposition est complète et toutes les notes ont une durée unitaire. Les valeurs intermédiaires de la profondeur offrent une grande variété de possibilités. Le réglage de ses paramètres en temps réel au cours de l’exécution est simple.
JONES (JONES 1981) utilise un système proche de celui-ci : une grammaire avec deux règles de générations :
A -> AA
A -> a
Associée à des probabilités d’application des règles (grammaire stochastique), pour générer un arbre binaire. La racine de l’arbre représentant la durée totale à décomposer, et les nœuds fils chacun la moitié de la durée du nœud père. L’inconvénient est que les durées exprimables sont toutes des puissances de deux, elles sont adaptées aux mesures à 4/4 (cf. Structures des pages) par exemple mais pour d’autres décompositions, il faudrait adapter la grammaire.
La dynamique peut être générée de deux façons dans le séquenceur : soit en utilisant une répartition des pourcentages de chance d’obtenir un silence, une note faible, une intensité moyenne ou une note forte : l’accentuation dynamique aléatoire. Soit en utilisant un algorithme de calcul basé sur une décomposition binaire : l’accentuation dynamique arborescente.
Trois limites sont accessibles pour former la répartition des pourcentages respectifs de chacune des quatre catégories d’amplitude. Chaque limite varie de 0 à 99 mais la première est inférieure ou égale à la seconde qui est inférieure ou égale à la troisième. Dans l’interface, les valeurs sont contraintes par ses règles.
Pour sélectionner une catégorie, nous prenons une valeur aléatoire entre 0 et 99. La position de la valeur entre les limites détermine une catégorie. Ensuite, la valeur réelle de l’amplitude est choisie aléatoirement entre des limites fixées selon la catégorie.
Le principe de l’accentuation dynamique arborescente est le suivant : nous partons de la racine avec une valeur donnée i et nous formons deux branches auxquelles nous attribuons respectivement les valeurs i*2 et i+1.

Figure 6.12
Par exemple en partant de la valeur 2, nous obtenons l’arborescence suivante :

Figure 6.13
Une infinité de sous-arbres sont équivalents, par exemple :
2 + 1 + 1 = 2 * 2, ou encore 2 * 2 + 1 + 1 = 2 + 1 * 2.
Ce qui nous intéresse, c’est la succession des valeurs obtenues à une profondeur donnée, par exemple à la profondeur 2, nous avons la séquence 8 5 6 4, en faisant correspondre des intensités à ces valeurs, nous retrouvons une relation avec l’importance rythmique relative des quatre temps d’une mesure à 4/4. Le premier temps est le plus fort, le second est relativement faible, le troisième temps est le second en importance et le dernier est le plus faible. Par construction, l’étage suivant possède la même structure et peut s’appliquer sur les 8 croches d’une mesure 4/4 pour en calculer l’intensité ou la force relative.
Le procédé peut également être inversé pour syncoper le résultat.
Ou encore être appliqué en dehors des temps, en suivant la décomposition récursive des durées, décrite dans le paragraphe précédent.
Ce paragraphe[81] présente quelques notions élémentaires d’harmonie nécessaires à la compréhension du paragraphe suivant portant sur la composition algorithmique. Nous utilisons la représentation graphique de la gamme et des accords que nous a transmis André RIOTTE[82].
Divisons l'octave en douze parties égales (le demi-ton).

Figure 6.14 : la gamme chromatique
Cette horloge (figure 6.14) représente la gamme chromatique[83], allant de demi-ton en demi-ton. Il n'y a évidemment qu'une seule gamme chromatique, identique quelque soit la note de départ. Par contre, en sautant une note sur deux, c'est-à-dire en allant de ton en ton, nous pouvons former deux gammes par ton distinctes et complémentaires.

Figure 6.15 : la gamme par ton
Ci-dessus (figure 6.15), l'hexagone de la gamme par ton, il est exactement similaire à la figure que l'on obtient en allant de 10 en 10.
Douze est divisible par 3, le résultat est 4, ainsi, en allant maintenant de trois en trois demi-tons, nous formons un carré.

Figure 6.16
Nous pouvons former ainsi trois carrés distincts, chacun de 2 façons : en allant de trois en trois ou de neuf en neuf.

Figure 6.17
Tout ceci est très régulier : maintenant nous avons un des quatre triangles équilatéraux possibles (figure 6.17), en avançant de 4 en 4 ou de 8 en 8. Mais la régularité change, lorsque le pas est de 7 ou de 5 :

Figure 6.18
Nous obtenons une figure (figure 6.18), unique, qui passe par toutes les notes de la gamme chromatique, mais dans un ordre différent.

Figure 6.19
De 6 en 6, nous avons 6 diamètres, simplement.
La gamme majeure peut être formée en allant de 7 en 7, mais en s'arrêtant dès que l'on a obtenu les sept notes.

Figure 6.20 : la gamme majeure.
Sur la figure 6.20, nous avons numéroté l'ordre d'apparition des notes de la gamme : fa, do, sol, ré, la, mi, si. En comparant cette horloge à un clavier de piano, nous retrouvons les mêmes espaces entre les notes : un ton entre deux notes consécutives, sauf entre mi et fa et si et do.
En continuant à tourner, de 7 en 7 après le si, on trouverait les notes fa dièse, do#, ré#, etc... dans le même ordre. Et en tournant à l'envers, comme si on cherchait la note précédant le fa, on trouverait, si bémol, mib, lab, etc... dans l'ordre inverse.

Figure 6.21 : les degrés de la gamme
Construire une gamme majeure, c'est simplement prendre sept notes consécutives dans la suite :
... solb réb lab mib sib fa do sol ré la mi si fa# do# sol# ré# la# mi#...
Où toutes les notes sont espacées de 7 demi-tons, puis les remettre dans l'ordre suivant leur hauteur.
En commençant par le fa, on obtient la gamme de do majeur (la note suivante dans la série). En commençant par le do, on obtient la gamme de sol majeur, qui inclue le fa#, etc... On peut construire ainsi une "infinité" de gammes, quand les dièses sont épuisés, on utilise des doubles dièses, de même pour les bémols.

Figure 6.22
Il est important de remarquer que tous les noms des notes apparaissent une seule fois, voilà pourquoi, en construisant la gamme de fa majeur, nous dénommons sib, la note entre si et la et non la#, puisque le la naturel est déjà dans la gamme.
Dans l'horloge ci-dessus (figure 6.21), nous avons numéroté en chiffres romains (comme il est d'usage) les degrés de la gamme. Chaque degré porte un nom. Cette abstraction permet de raisonner sur les notes et les harmonies, sans être obligé de tenir compte de la tonalité réelle dans laquelle on se trouve.
I - tonique
II - sus-tonique
III - médiante
IV - sous-dominante
V - dominante
VI - sus-dominante
VII - note sensible[84]
Jusqu'à présent, nous n’avons mentionné que la gamme majeure, l'harmonie utilise également les gammes mineures. Majeur et mineur sont des modes, comme on peut en former des multitudes, en sélectionnant des points dans cette horloge. Il existe plusieurs modes mineurs, nous ne décrivons ici que le mode mineur harmonique qui nous permettra de construire des accords.
La gamme harmonique mineure est construite en utilisant le même schéma que pour le mode majeur, mais la numérotation des degrés débute à neuf heures au lieu de midi.

Figure 6.23
Les carrés indiquant les notes appartenant au mode n'ont pas changé, sauf le degré VII, la sensible, montée d'un demi-ton pour être juste avant la tonique.
Chaque ton majeur possède ainsi son ton relatif mineur, dont la tonique est une tierce[85] au dessous (de la tonique du ton majeur).
Par exemple, la mineur est le relatif de do majeur, seule la sensible, sol est modifiée par un dièse. Le passage d'un ton à un autre est favorisé par le nombre de notes communes aux deux tons. Comme il y a six notes communes entre un ton et son relatif, ces modulations[86] sont simples.
Les intervalles entres les notes sont nommés en fonction du nombre de notes consécutives formant l'espace entre les notes (extrémités comprises). Par exemple entre mi et sol, il y a une tierce, car on compte trois notes consécutives de mi à sol : mi, fa, sol.
Les noms sont : unisson (pour une note), seconde pour l'intervalle formé par deux notes consécutives, puis tierce, quarte, quinte, sixte, septième, octave. Les intervalles plus grands ont des noms régulièrement formés : neuvième, dixième, etc...
L'ordre des dièses : fa, do, sol, ré, la, mi, si, obtenu précédemment en comptant par 7 demi-tons est formé d'une succession de quintes.
Les intervalles sont ensuite qualifiés pour rendre compte des différences en nombre de demi-tons. Par exemple, la seconde do-ré comporte un ton alors que la seconde do-ré# comporte trois demi-tons, la première est majeure et la deuxième est augmentée.

La table ci-dessus donne la correspondance pour chaque nom d'intervalle, entre les qualificatifs et le nombre de demi-tons.
Pour lire les accords sur la figure 6.24, il suffit de choisir un degré de départ, puis de suivre les lignes (dans le sens des aiguilles). Les lignes ont été tracées en sautant un degré sur deux, c'est-à-dire, en allant de tierce en tierce.

Figure 6.24 : Tous les accords du mode majeur.
Les accords de trois sons sont formés d'une note fondamentale (celle sur laquelle on construit l'accord), d'une tierce et d'une quinte (par rapport à la fondamentale). Le quatrième son est la septième, etc...
On peut remarquer que les accords de trois sons (deux lignes consécutives) sont de trois types différents : on trouve le premier type, accord parfait majeur, sur les degrés I, IV, et V (tierce majeure et quinte juste), le second type, accord parfait mineur, sur les degrés II, III, et VI, et enfin le troisième type, rencontré uniquement sur le degré VII est l'accord de quinte diminuée (c'est le seul formé de deux segments courts (deux tierces mineures), tous les autres sont formés d'un segment de chaque longueur).

Figure 6.25
Observons maintenant (figure 6.25), les accords à trois sons du mode mineur :
Degré I, accord parfait mineur ; degré II, accord de quinte diminuée ; sur le degré III, nous avons un nouveau type d'accord, de quinte augmentée, formant le triangle équilatéral. Le degré quatre est mineur, le V et le VI sont majeurs ; et sur le septième degré, se forme à nouveau l'accord de quinte diminuée, de plus, si on ajoute le quatrième son, cela forme un carré (composé uniquement de tierces mineures).
Comment voulez-vous faire de la musique avec des formes si biscornues ?

Figure 6.26 : Cette table donne pour chaque intervalle, la valeur en demi-tons correspondante suivant le degré sur lequel il est construit. Par exemple, si on bâtit une quinte sur le degré VII, la valeur 6 indique que c'est une quinte diminuée.
La première ligne indique donc les distances dans ce mode entre les notes consécutives. Les cases de la seconde ligne sont calculées en additionnant la valeur de la case supérieure et de sa voisine : il faut deux secondes consécutives pour former une tierce. Il existe de nombreuses façons de construire cette table, puisque toutes les valeurs peuvent se déduire de la première ligne. C'est simplement un point de vue sur le mode, différent de l'horloge et des segments.

Figure 6.27 : La table représentant le mode mineur.
En isolant les lignes correspondant à la tierce et à la quinte, nous voyons nettement les différents types d'accords de 3 sons.
3-7 accord parfait mineur[87] sur I et IV
3-6 accord de quinte diminuée sur II et VII
4-8 quinte augmentée sur III
4-7 accord parfait majeur sur les degrés V et VI.
En ajoutant un son dans l'accord (la 7ème), les degrés se distinguent davantage, par exemple les degrés V et VI portant des accords parfaits majeurs se distinguent maintenant par la septième qui est mineure pour le cinquième degré et majeure pour le degré VI. Par ailleurs, en regardant la table du mode majeur, on voit que le degré V porte le même accord de quatre sons 4-7-10.
Cet accord 4-7-10 n’apparaît que sur le degré V, mais dans les deux modes, il a donc une grande force tonale, et une faible force modale.
L'accord 3-6-9 n'apparaît que sur le degré VII du mode mineur. Il a donc une grande force modale. Mais sa forme carrée lui permet d'appartenir à quatre tonalités différentes, sa force tonale est donc moindre.
Toutes ces similitudes, oppositions, unicités ou au contraire multiplicités contribuent ou fondent les éléments de langages musicaux. Je trouve toujours étonnant les ressources inépuisables enfouies, contenues dans la simplicité des éléments de base.
Jusqu'ici, nous n’avons qu’à peine entrebâillé la première page d'un traité d'harmonie, ceci n'est qu'une première partie statique de l'harmonie, mais il existe des énergies, du mouvement, des dynamiques à découvrir. L'harmonie est la science de l'enchaînement des accords. Avant de pouvoir décrire leurs enchaînements, nous devons encore mieux connaître leur structure.
Ce que nous avons vu, des accords, et des notes, n'est qu'un reflet. Les horloges enroulent les notes de façon à superposer toutes les notes de même nom, et d'ignorer les octaves. Ceci permet de visualiser directement les opérations en arithmétique modulo 12. Mais les notes réelles doivent être déployées sur plusieurs octaves.
L'harmonie traditionnelle est écrite à quatre voix, les voix extrêmes : basse et soprano, encadrant les voix intermédiaires : ténor et contralto.

Figure 6.28
Comme décrit sur la figure 6.28 ci-dessus[88] (à gauche), chaque voix peut chanter dans un ambitus particulier, c'est-à-dire dans certaines limites. L'échelle est en demi-tons, les traits de repères, tous les douze demi-tons, indiquent les do, (graves en bas et aigus en haut). Ils sont repérés par leur écriture traditionnelle en pentagramme à droite.
La partie droite de la figure montre douze façons de former le même accord parfait majeur do-mi-sol (douze positions de l'accord), en respectant les ambitus des différentes voix, et en conservant la note fondamentale (do) à la basse, ce que l'on nomme l'état fondamental de l'accord. Lorsqu'une autre note que la note fondamentale est jouée par la basse, l'accord est dit renversé. Pour un accord de trois sons, on distingue deux renversements, à quatre sons, il y a un état fondamental et trois renversements.
Les six premières positions doublent la note fondamentale (il y a trois notes pour quatre voix, il est donc nécessaire qu'au moins une note soit doublée). Les trois positions suivantes doublent la tierce, et les trois dernières doublent la quinte. La position de l'accord étant connue, c'est-à-dire quelle note est doublée, et quel est leur ordre d'apparition, les notes sont placées en respectant l'ambitus des différentes voix, et en essayant de répartir les notes dans l'étendue (la même position do-mi-do-sol, peut être répartie de différentes façons, sur des octaves différentes).
Les renversements forment de nouvelles combinaisons d'intervalles.
Par exemple, l'accord parfait majeur que je note 3-7, est renversé une première fois en ajoutant 12 à la note de basse 0 (pour monter d'une octave), puis en recalculant les écarts à partir de la tierce. 7-3 = 4, 12-3 = 9, ce qui donne l'accord 4-9, formé d'une tierce majeure et d'une sixte majeure.
Le second renversement s'obtient de la même façon : 9-4 = 5, 12-4 = 8, ce qui donne 5-8, un accord formé d'une quarte juste et d'une sixte mineure.
Si on renverse encore l'accord 5-8, 8-5 = 3, 12-5 = 7, on obtient à nouveau l'état fondamental 3-7.

Figure 6.29
La figure 6.29 donne tous les accords de neuvième majeurs et mineurs ainsi que tous leurs renversements. Les accords sont notés en nombre de demi-tons depuis la note la plus basse, pour chaque note composant l’accord, et placés dans la grille. Par exemple l’accord 11-3-6-9 est dans la grande case repérée ligne 11 colonne 3 et sur le point de cette case repéré ligne 6 colonne 9. Les symboles indiquent les renversements.
Nous présentons maintenant plusieurs modules de composition algorithmique indépendants utilisant les définitions que nous venons de voir. Le premier module nommé Intervalle est basé sur les intervalles harmoniques[89] et le réglage de la possibilité ou non d'enchaîner ces intervalles.
Les différents modules peuvent être exécutés simultanément, et éventuellement connectés les uns aux autres. Certains modules sont des générateurs et produisent un flux de notes MIDI, d'autres sont des filtres, qui transforment un flux, d'autres encore modifient leur façon de générer en fonction de ce qu'ils reçoivent. Tous travaillent en temps réel.
Ce module fonctionne dans le mode chromatique, a priori, toutes les notes peuvent être générées (il n'y a pas de sélection de note par le choix d’une gamme ou d’un mode).
Trois voix sont générées. Nous commencerons par décrire les deux premières voix, qui sont indépendantes de la troisième.
Le but du contrôle des intervalles harmoniques est de contraindre la formation mélodique.
Le déroulement global du programme est géré par des interruptions provoqués par une horloge. Une variable globale tempo contient un nombre de millisecondes séparant chaque appel de la fonction nommée Métronome. Cette variable tempo est réglable par l'utilisateur. Dans la fonction Métronome, l'émission d'une note pour chacune des deux premières voix est déclenchée simultanément.
La hauteur des notes est mémorisée dans deux variables (statiques) hauteur1 et hauteur2. Ces variables sont initialisées respectivement à 60 et 64. Ces valeurs correspondent à des hauteurs MIDI (en nombre de demi-tons, le 60 correspondant au do du milieu du clavier). L'intervalle harmonique entre les notes est calculé par la simple différence entre les hauteurs.
intervalle = hauteur2 - hauteur1
Au départ, l'intervalle est de 4 (64 - 60), ce qui correspond à une tierce majeure.
Une table de 12 par 12 cellules, contrôlable dans l'interface utilisateur, indique les successions d'intervalles autorisées (cellule à 1) ou interdites (cellule à 0). Par exemple, la cellule (4, 7) (ligne 4, colonne 7) contient le drapeau indiquant si une tierce majeure peut être suivie d'une quinte juste.
Les intervalles harmoniques générés sont bornés entre 0 et 11 demi-tons. La moyenne des hauteurs des notes est comprise en les notes 50 et 70.
Voici maintenant comment se déroule un pas de l'algorithme (un appel de la fonction Métronome) :
• On tire un intervalle cible au hasard (entre 0 et 11 inclus).
• Si la succession de l'intervalle actuel à l'intervalle cible n'est pas autorisée, les deux notes sont conservées identiques, sont jouées, et le pas est terminé. La répétition du même intervalle est ainsi considérée comme étant toujours autorisée, et la diagonale principale de la table est insignifiante.
• Sinon, deux boucles successives vont permettre d'amener l'intervalle actuel à égalité avec l'intervalle cible :
• Tant que l'intervalle entre hauteur1 et hauteur2 est inférieur à l'intervalle cible : "augmenter l'intervalle"
• On tire une note au hasard entre 50 et 70, et on la compare à la moyenne de hauteur1 et hauteur2.
• Si la valeur tirée est inférieure à la moyenne, on baisse la hauteur1 d'un demi-ton
• Sinon, on monte la hauteur2 d'un demi-ton.
Dans les deux cas, l'intervalle entre hauteur1 et hauteur2 augmente (on a toujours hauteur1 ≤ hauteur2).
• fin de tant que.
• Tant que l'intervalle entre hauteur1 et hauteur2 est supérieur à l'intervalle cible : "diminuer l'intervalle"
• On tire une note au hasard entre 50 et 70, et on la compare à la moyenne de hauteur1 et hauteur2.
• Si la valeur tirée est inférieure à la moyenne, on monte la hauteur1 d'un demi-ton
• Sinon, on baisse la hauteur2 d'un demi-ton.
Dans les deux cas, l'intervalle entre hauteur1 et hauteur2 diminue (on a toujours hauteur1 ≤ hauteur2, puisque hauteur2 - hauteur1 > au choix de l'intervalle entre 0 et 11).
• fin de tant que.
• à ce niveau, l'intervalle entre hauteur1 et hauteur2 a évolué, de demi-ton en demi-ton, appliqué sur l'une ou l'autre des deux hauteurs, selon que, globalement les voix étaient plutôt aiguës ou graves.
• Les hauteurs ainsi obtenues sont émises.
Les valeurs 50 et 70 sont arbitraires, et peuvent être lues limite grave et limite aiguë respectivement. Le choix effectué, pour augmenter l'intervalle entre descendre la note basse ou monter la note haute, influe sur la ligne mélodique globale. De façon à garder les lignes mélodiques dans l'ambitus, mais sans avoir à donner une règle stricte qui aboutirait à des répétitions, nous faisons la moyenne des notes et nous tirons une note au hasard dans l'ambitus. Si la note tirée est plus haute (que la moyenne des deux notes), nous faisons monter la ligne mélodique, si elle est plus basse , nous faisons descendre la mélodie. De cette façon, l'évolution de la mélodie n'est pas immuable, et les chances de monter (respectivement de descendre) sont moindres si les notes actuelles sont déjà hautes (respectivement graves). Toutefois, malgré l'absence d'inertie dans le mouvement mélodique, les notes suivantes étant obtenues en modifiant pas à pas les notes présentes, les intervalles mélodiques générés sont minimisés malgré le respect du but à réaliser qu'est l'intervalle harmonique cible.
Les deux premières voix étant gérées par ce processus évolutif, mais essentiellement linéaire (sans retour en arrière, sans répétition de motifs dans le temps), nous avons utilisé une méthode totalement différente pour générer la troisième voix. Cette fois, nous utiliserons un processus combinant la création et la répétition. D'autre part, l'intensité des deux premières voix était constante (réglée à une valeur moyenne). Les intensités des notes de la troisième voix seront générées de la même façon que leur hauteur, ceci introduisant une dynamique et un rapport étroit entre les hauteurs et les nuances.
Pour être en mesure de répéter des séquences, nous devons les mémoriser. Nous formons alors en mémoire une table de la longueur maximale des séquences, la première ligne de la table contenant les hauteurs des notes, la seconde contenant leurs intensités.
La troisième voix sera deux fois plus rapide que les deux premières (deux notes dans le temps indiqué par la variable tempo).
La table est lue pas à pas, depuis l'indice 0 jusqu'à une limite contenue dans une variable. Quand la limite est atteinte, la variable indice est remise à zéro. À chaque pas une note est émise, avec l'intensité et la hauteur lues dans la table.
De cette façon, si la limite ne varie pas, nous obtenons une séquence cyclique, strictement répétitive.
Mais une variable, contrôlée dans l'interface utilisateur, permet d'agir sur le cycle : la valeur de cette variable peut couvrir l'intervalle de 0 à 100.
Pour que cette valeur corresponde à un pourcentage de chance de changement, à chaque pas du cycle (avant chaque note), nous tirons aléatoirement une valeur entre 0 et 100. Si cette valeur est inférieure au pourcentage souhaité, alors nous exécutons les modifications :
• En premier lieu la modification de la limite de l'indice, donnant le nombre de notes de la séquence.
• Si la limite vaut 3 elle est portée à douze.
• Puis la limite est affectée par une valeur aléatoire comprise entre 3 et la valeur courante de la limite (étant fixée à six au départ, elle est donc toujours comprise entre 3 et 12).
La répétition de ces modifications font tendre progressivement la valeur de la limite vers 3, puis la première instruction la ramène vers une plus grande valeur. Cette progression peut toutefois être brutale. Le hasard peut également conserver indéfiniment la même valeur...
• Ensuite, toutes les valeurs de la table dans les cellules indéxées de zéro à la nouvelle limite sont simplement remplacées par de nouvelles valeurs prises aléatoirement entre des limites fixées. Pour les hauteurs entre 50 et 70 (le même ambitus que pour les deux premières voix), et pour les intensités entre 50 (mezzo forte) et 100 (forte). 127 étant fortissimo et 1 quasiment le silence.
Si le pourcentage de changement est réglé à zéro, nous obtenons une séquence parfaitement répétitive. S'il est réglé à 100, les valeurs de la table sont modifiées à chaque fois, donnant une séquence totalement aléatoire, renouvelée en permanence. Une valeur intermédiaire donnera des séquences répétées quelquefois puis remplacées par d'autres séquences. Le changement de séquence s’effectuant à un moment quelconque du cycle.
Le caractère aléatoire de la troisième voix est contrecarré par les répétitions. À l'écoute, cette troisième voix parait finalement être la première : Elle est deux fois plus rapide que les autres, et plus "répétitive", elle parait être accompagnée par les accords des deux premières voix. Ceci peut être accentué ou atténué par le choix des timbres et un réglage externe de la balance entre les voix. Les répétitions dépendent évidemment des réglages du pourcentage de changement, mais aussi de la table d'autorisation des successions d'intervalles : si la majorité des successions sont interdites, les deux voix se répètent souvent.
Un algorithme si simple ne peut fournir directement la matière à une œuvre, mais il fait partie d'un ensemble de modules, et doit être vu comme un élément intervenant pendant certaines périodes au sein d'une structure de niveau d'organisation supérieur. Les périodes générées par ce module sont globalement uniformes, il n'y a pas ici de développement dramatique.
Le module Module est nommé ainsi car il génère des modulations, c'est-à-dire, des changement progressifs de tonalité et de mode, au travers de la génération d'une série d'accords.
Le principe est le suivant : À chaque appel de la fonction Métronome[90], l’accord généré précédemment est joué, puis analysé pour former la liste des tonalités auxquelles il peut appartenir. Un choix aléatoire est effectué pour sélectionner une de ces tonalités. Et enfin, un nouvel accord est reconstruit dans la tonalité choisie. Les tonalités analysées sont au nombre de 24 (12 tons majeurs et 12 tons mineurs harmoniques).
Une variable : tempo contrôle le nombre de millisecondes entre chaque appel de la fonction Métronome. la valeur minimale de tempo est 50 millisecondes.
La vélocité est la vitesse de frappe de la touche sur le clavier, elle doit être transmise dans le message MIDI commandant l’émission d’une note. Nous faisons varier la vélocité entre 30 et 127. Les limites extrêmes étant 1 et 127.
La valeur initiale de vélocité est de 64.
Puis, à chaque accord la vélocité est modifiée par la séquence suivante :
velocite += aleatoire(-10, 10);
if(velocite < 40)
velocite = 100;
else if(velocite > 117)
velocite = 50;
La valeur de la variable vélocité est comprise entre 40 et 117, mais au moment de l’émission, la valeur de vélocité est modifiée par l’ajout d’une valeur aléatoire comprise entre -10 et +10.
L’émission de l’accord généré à l’appel précédent de Métronome est écrite comme suit :
for(k = 0; k < 5; k++)
{
if(accord[k])
{
emettreNote(
/* date */ MidiGetTime() + aleatoire(0, 300),
/* canal */ k,
/* hauteur */ accord[k],
/* vélocite */ velocite + aleatoire(-10, 10),
/* durée */ tempo + aleatoire(0, 200) );
}
}
L’accord est contenu dans une table de 5 entrées. Une entrée nulle correspond à un silence, une valeur non nulle à un numéro de demi-ton dans le format MIDI.
MidiGetTime est une primitive de MIDIShare donnant le numéro de la milliseconde courante. L’ajout d’une valeur aléatoire (entre 0 et 300) à la date de l’attaque de la note permet d’obtenir des retards des notes d’un accord sur l’autre.
Les notes de l’accord ont globalement la même intensité (vélocité), mais des variations sont introduites par l’ajout de la valeur aléatoire entre -10 et 10.
Enfin, la durée de la note en millisecondes est calculée par la somme de la valeur du tempo et d’une prolongation aléatoire d’un cinquième de seconde au maximum.
La fonction EmettreNote construit un événement MIDIShare qui sera placé dans une liste d’attente triée par date d’émission, et émis à terme.
La phase suivante est l’analyse des tons possibles. Le plus simple et le plus direct est de parcourir les 24 tonalités et dans chaque tonalité, vérifier si toutes les notes de l’accord sont présentes. Ou plus exactement éliminer les tonalités pour lesquelles au moins une note de l’accord est absente.
Ce n’est évidemment pas une simulation de l’oreille humaine, ni une méthode subtile, mais le nombre de notes à traiter dans le temps imparti se prête à cette écriture combinatoire.
Dans le code suivant, la table tons est de 2 * 12 entrées. La variable t représente un ton de 0 à 11 (0 étant do), la variable m le mode (0 majeur, 1 mineur), la variable k le numéro de la note dans l’accord.
La variable dt est la note de l’accord rabattue sur la première octave par l’opération modulo 12, et la variable d est le degré de la gamme (de 0 à 6).
for(t = 0; t < 12; t++)
{
for(m = 0; m < 2; m++)
{
tons[m][t] = 1;
for(k = 0; tons[m][t] && k < 5; k++)
{
if(accord[k])
{
int dt = accord[k] % 12;
int d;
for(d = 0; d < 7; d++)
{
if((t+Gamme[m][d])%12== dt)
{
break;
}
}
if(d == 7)
{
tons[m][t] = 0;
}
}
}
}
}
La phase suivante est le choix d’une des tonalités. Une première boucle dénombre les tonalités possibles (nb). Puis un nombre est tiré aléatoirement (choix) pour déterminer la tonalité parmi les possibles.
{
int nb = 0;
int choix;
for(t = 0; t < 12; t++)
{
for(m = 0; m < 2; m++)
{
if(tons[m][t]) nb++;
}
}
choix = aleatoire(1, nb);
for(t = 0; choix && t < 12; t++)
{
for(m = 0; choix && m < 2; m++)
{
if(tons[m][t])
{
choix--;
if(!choix)
{
tonique = t;
mode = m;
}
}
}
}
}
Enfin, la dernière phase est la construction de l’accord suivant.
Le degré de la fondamentale de l’accord (degre) est choisi aléatoirement. Ensuite les notes de l’accord sont prises parmi les notes suivantes en allant de deux degrés en deux degrés. La formule (degre + 2 * aleatoire(0, 4)) % 7 donne aléatoirement un degré appartenant à l’accord de 5 sons formé de tierce en tierce à partir de degre.
Les notes de l’accord ainsi généré ne sont pas ordonnées, et ne prennent en compte les notes de l’accord précédent qu’au travers de l’interprétation de la tonalité de celui-ci.
degre = aleatoire(0, 6);
for(k = 0; k < 5; k++)
{
int octave = aleatoire(3, 5);
if(aleatoire(0, 100) > 40)
{
accord[k] =
tonique
+ octave * 12
+ Gamme[mode]
[(degre + 2*aleatoire(0, 4)) % 7];
}
else
{
accord[k] = 0;
}
}
Dans 40% des cas, la note est remplacée par un silence.
Une voie supplémentaire a été introduite, pour jouer des notes prises dans la tonalité et le mode courant. Une seconde fonction Métronome exécute le code suivant :
octave = aleatoire(4,7);
hauteur =
tonique
+ octave * 12
+ Gamme[mode][aleatoire(0, 6)];
emettreNote(
/* date */ MidiGetTime(),
/* canal */ 5,
/* hauteur */ hauteur,
/* vélocité */ aleatoire(50, 127),
/* durée */ tempo / 2
);
Le tempo de cette seconde fonction Métronome est réglé au cinquième de la première, en conservant malgré tout la même limite inférieure de 50 millisecondes. La durée des notes de cette voix est la moitié du temps séparant les attaques. La vélocité est aléatoire et la hauteur est aléatoire également, mais dans le mode et la tonalité sélectionnée par la première fonction Métronome. Cette mélodie anticipe donc l’interprétation qui sera confirmée par l’audition de l’accord suivant.
L’interface permet d’activer ou de désactiver indépendamment les deux fonctions Métronome.

Figure 6.30
Ci-dessus (figure 6.30), un extrait de ce que produit Module, reproduit dans un phonogramme. Les traits sont plus allongés à droite de l’image à cause d’une variation du tempo au cours de l’exécution.
Ci-dessous (figure 6.31) un autre extrait du produit de Module, transcrit en fichier MIDI et importé dans un éditeur de partition. Les canaux sont retranscrits individuellement sur chaque portée. La première portée est en clé de sol les suivantes en clé de fa.


Figure 6.31
Le module dénommé Pouzzolane est basé sur un algorithme de génération de lignes mélodiques associé à un système de mémorisation influencé par le temps.
Le principe de cet algorithme est fondé sur l’idée suivante : On se remémore fréquemment des éléments récents que l’on oublie également plus souvent. À l’inverse, les souvenirs plus anciens interviennent moins fréquemment, mais sont conservés plus longtemps que les précédents.
Nous associons au module générateur de mélodies une banque de mémoires mélodiques et rythmiques[91] dont l’accès aléatoire est pondéré de façon à atteindre les différents registres avec une probabilité variable (cf. § Arbres d’appels de fonction pseudo-aléatoire).
L’application utilisant cet algorithme, Pouzzolane, génère huit voix en temps réel et peut être paramétré pendant l’exécution.

Figure 6.32 : Fenêtre de contrôle de Pouzzolane
Les contrôles externes du programme Pouzzolane (figure 6.24) sont au nombre de huit :
• Un drapeau contrôlant la marche et l’arrêt du système (case marche). En fait, ce booléen contrôle l’émission du flux MIDI mais le calcul de l’algorithme ne s’arrête qu’à la terminaison de l’exécution du programme.
• Un drapeau contrôlant le mode de répartition des voix sur les canaux MIDI : en mode poly,[92] un canal par voix, et sinon toutes les voix sont émises sur le même canal (case poly).
• Une valeur exprimée en millisecondes donnant la pulsation de base, nommée tempo. Cette valeur est la valeur de retour de la fonction Métronome, elle est bornée à gauche par la limite arbitraire de 30 millisecondes. En effet, si le tempo prenait une valeur inférieure au temps nécessaire au traitement des interactions avec l’utilisateur, plus aucun contrôle ne serait possible.
• Cinq variables enfin, expriment des pourcentages permettant de contrôler les chances d’occurrence d’événements divers :
• La création, ou recomposition de la mélodie d’une voix.
• La mémorisation, ou copie de la mélodie d’une voix dans la banque de mélodies.
• Le rappel, ou remplacement de la mélodie d’une voix par une mélodie de la banque de mélodies.
• L’occurrence d’un silence.
• Le changement de longueur de la mélodie[93] d’une voix.
La mémoire principale (figure 6.33), qui est lue pour l’exécution, est une table de mélodies indexées par voix et par note. À chaque entrée on obtient un degré (de 0 à 6), une octave (un numéro d’octave) et une durée (en nombre de pulsations).

Figure 6.33 : mémoire principale
À chaque voix, on associe également une longueur, c'est-à-dire un nombre supérieur ou égal à 2 et inférieur ou égal à la longueur maximale, qui détermine le nombre de notes réellement jouées.
La mémoire secondaire (figure 6.34), ou banque de mémoires mélodiques, sur laquelle porte le principe du système, est constituée d’une table indexée par voix et par âge probable, chaque entrée fournissant une table de mélodie.

Figure 6.34
La probabilité d’accès est plus grande pour la partie récente (en haut sur le schéma) dans les indices faibles, et moins grande pour la partie ancienne de la banque dans les indices forts.
Le nombre de mémoires est actuellement fixé à 30, le nombre de voix à huit et la longueur maximale des mélodie à 12 notes. Cela représente environ 17K octets pour la banque.
Au départ, la mémoire principale est initialisée par un appel à la fonction de composition d’une mélodie pour chaque voix. Puis, la mélodie de la première voix est reproduite dans toute la banque secondaire.
À chaque battement du tempo, c’est-à-dire à chaque appel de la fonction Métronome, et pour chaque voix indépendamment, nous effectuons les étapes suivantes :
• Création
• Mémorisation
• Rappel
• Émission
L’exécution de chaque étape est conditionnelle.
• Création : La variable contenant le pourcentage de création est comparée à une valeur aléatoire comprise entre 0 et 100. Si cette valeur est inférieure à la valeur de la variable, alors la mémoire principale de cette voix est recomposée, pour sa longueur maximale, mais sa longueur actuelle n’est pas modifiée.
• Mémorisation : Ensuite, en utilisant le même principe de comparaison de la variable de pourcentage avec un tirage aléatoire, on détermine si une mémorisation intervient. Dans ce cas : la mémoire principale de cette voix est recopiée dans une mémoire de la banque dont la valeur de l’indice est calculé comme suit :
indice = aléatoire(0,
aléatoire(0,
aléatoire(0, nombre de mémoires)))