Flot Rythmique

Cette réalisation consiste à élaborer une librairie pour SuperCollider capable de produire des rythmes variés et cohérents.


Rhythmic distribution demonstration on SuperCollider from Sébastien Clara on Vimeo.

Un flot de rythme

Genèse

Mon apprentissage de l’informatique musicale débuta en troisième année de licence. Durant cette année, j’effectuai un échange inter-universitaire avec la faculté de Guanajuato au Mexique. Lors d’un exercice rythmique, nous étudiâmes le premier mouvement de La vision de l’amen, Amen de la création d’Olivier Messiaen. L’exercice consistait à découvrir le processus générateur du rythme et de l’extrapoler dans une composition personnelle. Pour clôturer cet exercice notre professeur, Roberto Morales, nous conseilla d’élaborer une bibliothèque capable de nous générer du rythme. Je me promis de la réaliser, mais la suite de mes études ne m’en donna pas l’occasion.

Toutefois, durant mon master 2 lors de la conception d’un projet personnel, j’imaginai une installation interactive. Celle-ci devait être autonome et générer de la musique. Ainsi, devant la problématique de produire du rythme varié et cohérent sur une longue période, la création d’une librairie dédiée réémergea.

Principe

Pour cette réalisation, j’ai utilisé un outil de construction rythmique de SuperCollider. Cet outil est une variation du processus rythmique imaginée par Mikael Larson. Cet objet produit des listes de durées que nous pouvons exploiter, par exemple, avec la classe Pattern de SuperCollider. Effectivement, cette classe utilise des listes et des flux pour alimenter un synthétiseur ou un effet. L’usage pour construire un rythme est :

[durée, [rythme], nombre d'exemplaire ].convertRhythm.

  • L’argument durée correspond à la durée globale du rythme. Il s’évalue en seconde.
  • L’argument rythme, nous permet de fixer notre rythme. Par exemple, pour rythme suivant [2, 1, 4], la première durée (2) est deux fois plus longue que la deuxième et elle est deux fois plus court que la troisième durée. Cela nous donne des proportions de durée qui seront évaluées par rapport à la durée globale du rythme.
  • L’argument nombre d’exemplaire, assure le nombre d’exemplaire du rythme à produire. Il est facultatif et il est égale à 1 par défaut.
  • Cette commande nous retourne une liste de durées.

Par exemple, l’exécution de [3, [1, 2, 1] ].convertRhythm nous retournera [0.75, 1.5, 0.75], de même que [3, [2, 4, 2] ].convertRhythm. Les durées du rythme sont proportionnées à la durée globale du rythme. Dans ces deux exemples, elle est identique et égale à trois secondes. C’est cette durée qui conditionnera les durées rythmiques. Dans ces deux exemples, la durée globale et les proportions rythmiques sont identiques, de fait, les résultats sont identiques.

Cependant, l’écriture musicale traditionnelle attribue les durées rythmiques par un nombre de pulsation par minute. Par conséquence, pour synchroniser notre flot rythmique avec des musiciens, nous devons convertir la pulsation par minute en durée d’une mesure. Pour ce faire, nous convertissons les pulsations par minute en pulsations par seconde et nous divisons le nombre de pulsation par mesure avec cette conversion. Cela donne la formule suivante :

pulsation par mesure / ( tempo / 60 )

Effectuons un cas pratique. Notre tempo est de 80 à la noire. Nous désirons connaître la durée d’une mesure pour un tempo binaire à quatre pulsations par mesure et un tempo ternaire à trois pulsations par mesure.

Tempo
80 à la noire
80 à la noire
Pulsation par mesure
3
4
Durée d’une mesure
3 / ( 80 / 60 ) = 2.25 secondes
4 / ( 80 / 60 ) = 3 secondes

Ainsi, nous pouvons coordonner musique acoustique et musique électronique. Cependant, la musique jouera un rôle « métronomique ». Cette problématique est récurrente pour certains compositeurs ou musiciens et différentes recherches ont vu jour. Néanmoins, ce rapport n’a pas vocation à explorer ce champ. Toutefois, la maîtrise du temps, nous permet aussi de synchroniser toutes nos voix électroniques asynchrones. Effectivement, nous pouvons contraindre notre polyrythmie à débuter et à se terminer au même moment. L’exemple suivant nous le montre de manière éloquente.

Voix 1

3 s

3 s

3 s

3 s

Voix 2

4 s

4 s

4 s

Voix 3

12 s

Ces principes généraux structures nos besoins. Effectivement, notre librairie de flot rythmique nécessite comme paramètres la durée d’une mesure et le nombre de mesure désiré. Toutefois, pour le moment nous n’avons pas évoqué les modes de distribution de nos rythmes. Effectivement, ce point nous permettra de répondre à notre exigence initiale, à savoir, produire des rythmes variés et cohérents. De plus, il sera le troisième paramètre de notre bibliothèque de flot rythmique.

Nous devrons élaborer notre bibliothèque afin qu’elle puisse s’augmenter sans que cela remette en cause les réalisations précédentes utilisant ce service. Ainsi, nous avons créé sept modes de distribution rythmique. Ce nombre de mode n’est pas figé puisque la structure de la librairie permettra d’ajouter par la suite d’autre mode de distribution. Nous distinguons trois types de mode de distribution. Le premier type utilise des rythmes binaires et/ou ternaires. Le deuxième type s’appuie sur des distributions stochastiques. Et le dernier type développe des processus spécifiques. Voici en détail nos différents modes de distribution :

  • Mode 1 : rythme hybride entre binaire et ternaire.
  • Mode 2 : rythme plutôt binaire.
  • Mode 3 : rythme plutôt ternaire.
  • Mode 4 : rythme issu d’une distribution brownienne.
  • Mode 5 : rythme issu d’une distribution eulérienne (fonction beta).
  • Mode 6 : contamination d’un rythme binaire par une distribution de Poisson.
  • Mode 7 : processus rythmique inspiré par le premier mouvement de La vision de l’amen: Amen de la création d’Olivier Messiaen.

Toutefois, ces modes ont été construits pour répondre à une problématique, celle de générer des rythmes pour une installation interactive. Les trois arguments nous permettent, de choisir une identité rythmique, le nombre de mesure et le temps d’une mesure. Le nombre de mesure nous sert à sélectionner entre un rythme récurent, une mesure en boucle, ou un flot rythmique. Le temps d’une mesure donne la densité rythmique, plus le temps d’une mesure est court, plus le rythme est dense. Cependant, cette gestion rythmique peine à s’accorder avec d’autres intervenants, entre la gestion de la densité rythmique et de la durée globale d’une phrase musicale.

Ce questionnement me conduisit à poursuivre le développement de cette bibliothèque. De plus, sa structure versatile nous autorise sa diversification tout en gardant une compatibilité avec son fonctionnement antérieur. Ainsi, nous avons ajouté trois nouveaux dictionnaires. Ceux-ci sont utilisés par un nouveau mode de distribution. Il nécessite, en plus, deux nouveaux arguments pour ces distributions, la densité rythmique et le nombre de division du rythme par mesure. Ces nouveaux paramètres nous aident à gérer la densité rythmique par mesure, mais aussi à définir l’identité du rythme. Avec cette nouvelle fonctionnalité, il est très facile de varier la densité rythmique sur un nombre de mesure donnée.

Réalisation

La bibliothèque se décompose en trois couches. La première est composée de dictionnaires. En effet, certains modes de distribution utilisent un dictionnaire pour générer du rythme. La deuxième couche de cette librairie permet de développer les différents modes. Enfin, la dernière partie structure nos rythmes. Cette dernière couche gère nos différents générateurs rythmiques par l’utilisation de deux méthodes. Ces trois couches sont indépendantes, mais elles réclament les précédentes pour fonctionner, hormis les modes de distribution n’utilisant pas de dictionnaire pour produire du rythme.

Dépendance des trois couches entre elles

La couche d’organisation des modes gère nos deux familles de distribution. Chaque famille possède sa méthode d’appel et donc son propre concept de distribution. La méthode parFlot est notre construction initiale. Elle nécessite trois arguments pour produire du rythme. Elle est composée comme cela :

FluxRythmique.parFlot(modeDistribution, nombreMesure, dureeMesure)

  • modeDistribution est un nombre entier entre 1 à 7. Il permet de sélectionner un mode de distribution.
  • nombreMesure est un nombre entier. Il détermine la taille de notre rythme. Ainsi, un faible nombre de mesure engendre un rythme répétitif.
  • DureeMesure est un nombre flottant. Il correspond à la durée d’une mesure en seconde. Toutefois, ce paramètre nous servait à gérer la densité rythmique. Effectivement, plus la durée est courte, plus le rythme est dense.

Cette méthode test le choix du mode, puis exécute la distribution suivant le nombre de mesure et la durée d’une mesure.

Diagramme de la méthode parFlot

La tâche, formatage de la sélection du diagramme de flux de données, reconditionne notre choix : Elle calcule le modulo de sept de notre choix. Elle arrondit notre choix pour qu’il devienne un entier. Et elle force le type pour que celui-ci soit un entier. Le code de ce reconditionnement est le suivant : (choixRythme % 7).round.asInteger. Alors, la tâche, distribution d’un rythme, peut appeler le mode de distribution autant de fois que le paramètre du nombre de mesure le stipule. Voici son code :

switch ( (choixRythme % 7).round.asInteger,
0, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode0(dureeMesure)}) },
1, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode1(dureeMesure)}) },
2, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode2(dureeMesure)}) },
3, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode3(dureeMesure)}) },
4, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode4(dureeMesure)}) },
5, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode5(dureeMesure)}) },
6, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode6(dureeMesure)}) },
7, { nombreMesure.do({rythme = rythme ++ DistributionRythmique.mode7(dureeMesure)}) }
);

Chaque mode possède son moyen de distribution propre. Cependant les trois premiers modes utilisent le même principe pour produire du rythme. Toutefois, ils s’appuient sur des dictionnaires rythmique différents. Un dictionnaire comprend toutes les cellules basiques d’un mode rythmique. Le début du dictionnaire du mode 2 est ainsi : [ [4,4], [4,2,2], [4,3,1], etc. L’algorithme du mode choisit de manière aléatoire une cellule et permute les éléments de la cellule aussi de manière aléatoire. Le mode 2 et 3 utilisent le même algorithmique. Ils tirent aléatoirement deux cellules. Si le dernier élément de la première cellule est un entier ainsi que le premier élément de la seconde cellule, l’algorithme lie les deux cellules.

*mode2 { arg temps = 3;
var tabA, tabB;
tabA = Dictionnaire.deux[1][rrand(0, Dictionnaire.deux[0])];
tabA = tabA.permute( rrand(0, tabA.size-1.factorial) );
tabB = Dictionnaire.deux[1][rrand(0, Dictionnaire.deux[0])];
tabB = tabB.permute( rrand(0, tabB.size-1.factorial) );
if( (tabA.last.size == 0) && (tabB.first.size == 0),
{
tabA.putLast(tabA.last + tabB.first);
tabB.removeAt(0);
});
^[temps, tabA ++ tabB].convertRhythm;
}

Notre seconde famille de distribution découle des mêmes principes que la première famille, mais elle s’en distingue. Cette seconde famille utilise la méthode parMesure. Elle nécessite cinq arguments pour générer du rythme. Son usage est le suivant :

FluxRythmique.parMesure(choixRythmique, densite, pulseMesure, nombreMesure, dureeMesure)

  • choixRythmique peut être de deux types. Soit il est un nombre entier de 1 à 3 et il indique un dictionnaire. Soit il fournit un tableau qui sera utilisé comme un dictionnaire.
  • densite est un nombre flottant entre 0 et 1. Il correspond au poids de la densité rythmique désirée.
  • pulseMesure est un nombre entier. Il indique le nombre des plus courtes divisions du rythme par mesure, par exemple 8 peut correspondre à la croche.
  • nombreMesure est un nombre entier. Il détermine la taille de notre rythme. Ainsi, un faible nombre de mesure à pour effet de produire un rythme répétitif.
  • DureeMesure est un nombre flottant. Il correspond à la durée d’une mesure en seconde.

La première tâche pour cette méthode est déterminée le type du premier argument. En effet, celui-ci peut indiquer un dictionnaire de la librairie par un nombre entier entre 1 et 3, ou fournir un dictionnaire. Le type du dictionnaire doit être un tableau dont chaque cellule nous indique une proportion de durée rythmique. Ce tableau nous permet d’utiliser la fonction de création rythmique, convertRhythm, inspirée par Mikael Larson. Grâce à ce dictionnaire et suivant les paramètres de la méthode, le processus nous compose une liste de durée, interprétée par SuperCollider en rythme. De plus, nous avons décidé, toutes les deux mesures, de lier les mesures entre elles. Ainsi, nous avons l’opportunité de construire des phrases rythmiques de deux mesures.

Diagramme de la méthode parMesure

Le code de sélection d’un dictionnaire test le type du paramètre de notre choix.

if( choixRythme.isInteger, {
bal = switch (choixRythme)
{1} { DistributionRythmique.uneMesure(Dictionnaire.hybride[1], densite, pulseMesure) }
{2} { DistributionRythmique.uneMesure(Dictionnaire.binaire[1], densite, pulseMesure) }
{3} { DistributionRythmique.uneMesure(Dictionnaire.ternaire[1], densite, pulseMesure) };
},{
bal = DistributionRythmique.uneMesure(choixRythme, densite, pulseMesure)
});

Pour lier les mesures entre elles, un index compte les mesures et lorsque le résultat du modulo de deux sur cet index est égale à un, nous lions la nouvelle mesure au reste du rythme.

if( index % 2 == 1, {
bal = [dureeMesure, bal].convertRhythm;
rythme.putLast(rythme.last + bal.first);
bal.removeAt(0);
rythme = rythme.add(bal);
},{
rythme = rythme.add([dureeMesure, bal].convertRhythm);
});

L’utilisation de différents modes de distribution répond à nos besoins initiaux. Effectivement, chaque mode produit un rythme propre à son algorithme ou à son dictionnaire. De fait, cette librairie produit des rythmes variés, elle possède dix modes de distribution et elle est cohérente grâce à l’utilisation d’un processus ou d’un dictionnaire spécifique.

Sébastien Clara – Avril 2012