Chargement...
 
Skip to main content
Script mididings pour Seq64 dans Carla
Cette page présente les étapes à suivre pour mettre en place un script Mididings dans une configuration de boucles MIDI avec Sequencer64, Carla et un synthétiseur virtuel (ici Fluidsynth), le tout sous LibraZik.





Introduction


Dans une configuration de séquenceur en looping (live ou non), le logiciel propriétaire Ableton Live a une fonctionnalité appelée Random Follow expliquée par exemple dans cette vidéo Image , et qui consiste à préparer plusieurs boucles pour la même séquence que le logiciel va choisir aléatoirement, résultant en une suite aléatoire de ces boucles. Ceci peut donner par exemple de la variété dans une séquence de percussions, avec quelques coups supplémentaires de caisse ou de charleston, ou dans une ligne de basse, pour éviter que ce soit trop répétitif et devienne lassant.

Mon looper libre de prédilection, Sequencer64, ne présente pas cette fonction. Je n'ai pas trouvé non plus de greffon LV2 qui fasse ceci (il existe par contre PSI Random MIDI pour remplacer une note par une autre note choisie aléatoirement dans une certaine bande). Je me suis donc tourné vers Mididings pour randomiser les séquences.



Organisation de la session


Pour ce tuto j'utilise Ray Session et Carla, mais c'est bien sûr transposable sur d'autres outils.
Seq64 est lancé depuis Ray Session, et des synthétiseurs virtuels tels que Fluidsynth ou Helm sont lancés dans Carla en tant que greffons lv2.

Desktop Carla Ray Seq64

En temps normal, chaque séquence de Seq64 peut être connectée à un synthétiseur virtuel pour produire un son (sur l'image ci-dessus par exemple la trompette, le piano et les percus sont jouées par des greffons Fluidsynth hébergés dans Carla).
Pour ce tuto, l'idée est donc de créer plusieurs séquences dans Seq64, qui seront jouées (aléatoirement donc) par le même synthétiseur.

Seq64 Basse



Le script mididings


Idée et réflexions préalables


Je me suis donc tourné vers Mididings, qui permet de recevoir des signaux MIDI, de les traiter et de renvoyer un signal différent - ou de lancer une application externe, ou n'importe quelle autre action possible en utilisant les scripts de configuration en Python. J'ai donc imaginé router les 4 séquences de Seq64 vers mididings, qui choisirait aléatoirement quelle séquence laisser ressortir vers le synthétiseur.
Le script aurait donc un nombre maximal d'entrées MIDI pour les séquences (constante NPORTS dans la suite). Chaque séquence serait envoyée sur une Scène Image différente, et une seule de ces scènes serait renvoyée vers l'unique sortie MIDI du script.
Il reste à identifier un déclencheur pour que Mididings sache à quel moment choisir la scène à activer. Il y a sans doute de meilleures options, mais j'ai choisi d'utiliser le contrôle CC#119 que je n'utilise autrement pas. Une séquence de "contrôle" démarrant avec un signal CC#119 déclencherait le changement de scène de Mididings.


Entrées et sorties


Le début du fichier de configuration mididings définit les entrées et sorties du script. Ici, la fonction buildportsarray() utilise une boucle entre 0 et np (=NPORTS) crée une série (array) ["ctrl_in", "in_0", "in_1", .. , "in_4"], et le bloc config() utilise cette série pour créer les ports d'entrée ("ctrl_in" est là pour recevoir le signal de déclencheur) :
Copy to clipboard
# The maximum number of input ports (in addition to ctrl_in) NPORTS=5 # Build an array of input ports after the ctrl input def buildportsarray(np): portsarray=["ctrl_in"] for p in xrange(0,np): portsarray.append("in_%d" %p) # %d dans le string pour concaténer "in_" avec la valeur de p return portsarray # Define input and output ports config( #backend='jack-rt', client_name = 'mdd-RandomFollowSeq', in_ports = buildportsarray(NPORTS), out_ports = [ 'out', ] )

Dans Carla, les entrées et sorties de ce script ressemblent donc à ceci :
Mididings Carla


Préparer les scènes


On passe ensuite à la création des scènes, qui doit dépendre aussi du nombre d'entrées NPORTS utilisées au-dessus :
Copy to clipboard
# Returns a dictionnary of Scenes, one per input port minus the control (first) port def routing_scenes(ports): return dict( (p, Scene("Port %d" % (p+1), PortFilter(p+1) >> Port(1) )) for p in range(1, ports+1) )



Fonctions pour sélectionner une scène aléatoire


Pour sélectionner aléatoirement une scène, on veut d'abord être sûr de ne sélectionner que les scènes qui sont effectivement connectées à une séquence ; et qui reçoivent effectivement un signal. Comme le son ne commence pas forcément au tout début d'une séquence, j'ai décidé d'utiliser aussi le contrôle CC#119 en tout premier signal de chaque séquence - ci-dessous la ligne de basse, avec un CC119 à une vélocité de 64 dès le début :

Bass1 Cc119
Dès qu'une des entrées du script mididings détecte un signal CC119, la scène correspondante sera détectée comme active et ajoutée au set ACTIVESCENES :
Copy to clipboard
# Global variable for the scenes that are active, i.e. the ports on which there is a midi signal ACTIVESCENES=set() ACTIVESCENES.add(1) # Activate scenes only once a CC119 is detected def activatescene(ev): newscene=ev.port-1 if 1 <= newscene <= NPORTS+1: if newscene not in ACTIVESCENES: ACTIVESCENES.add(newscene) print("activated scene %d" %newscene + " for port %d" %ev.port)

Le paramètre de la fonction activatescene() est ev, qui est l'événement MIDI détecté (voir plus bas) et qui inclut tous les paramètres d'un signal MIDI (NoteOn, NoteOff, Control, Port, etc. comme listés ici Image ), et la scène activée aura le numéro ev.port-1 (puisque l'input in_0 est sur le port d'entrée 1 mais correspond à la scène 0 !).
Nous sommes maintenant prêts à choisir aléatoirement une de ces scènes actives (la fonction sample() choisit aléatoirement un élément d'un set) :
Copy to clipboard
# Picks a random scene in the set of active scenes def randscene(ev): pickedscene=sample(ACTIVESCENES,1)[0] switch_scene(pickedscene) return ev

 note
La fonction sample() nécessite d'importer la bibliothèque random, et la fonction switch_scene() vient de la bibliothèque mididings.engine, Image qui doivent donc être importées en début de script :
Copy to clipboard
from mididings.engine import switch_scene from random import sample



Le cœur du script


Enfin, le cœur d'un script mididings est définie par la fonction run(), qui va ici d'abord créer les scènes grâce à la fonction routing_scenes() définie plus haut, puis effectivement filtrer le signal MIDI entre entrées et sortie dans la section control.

Copy to clipboard
run( # Create scenes for each port scenes=routing_scenes(NPORTS), control = [ # activate a scene once CC119 is detected CtrlFilter(119) >> Call(activatescene), # Call random scene when the control port detects a CC119 PortFilter(0) >> CtrlFilter(119) >> Call(randscene) ] )

Les 2 lignes de control vont être actives en parallèle Image , mais chaque ligne définit des commandes en série.
La première ligne va donc détecter un signal CC#119 sur n'importe quelle entrée, et appeler la fonction activatescene() en y passant l'événement MIDI pour paramètre d'entrée comme expliqué plus haut.
La deuxième ligne va détecter un signal sur le port 0 ( ctrl_in ), vérifier si c'est un CC#119, et si oui, déclencher le choix aléatoire d'une scène ! Grâce à ce système, la séquence de contrôle peut avoir une longueur différente de celle des séquences, pour par exemple déclencher le choix aléatoire toutes les 2 mesures alors que chaque séquence n'en fait qu'une seule - et donc chaque séquence sera jouée 2 fois de suite avant de changer aléatoirement.



Intégration dans Carla et Ray Session


Lancer le script dans le terminal et tester dans Carla


Pour tester, le moyen le plus simple est de lancer mididings avec ce script en ligne de commande et de vérifier les changements de scènes :
Copy to clipboard
> $ mididings -R -f mididings_randomFollowSeq.py switching to scene 1: Port 2

En même temps, lancer aseqdump permet de vérifier le signal entrant et le signal sortant :
Copy to clipboard
> $ aseqdump Waiting for data at port 131:0. Press Ctrl+C to end. Source Event Ch Data 0:1 Port subscribed 129:0 -> 131:0 0:1 Port subscribed 130:0 -> 131:0 130:0 Control change 0, controller 119, value 64 130:0 Note on 0, note 45, velocity 100 130:0 Note off 0, note 45, velocity 64 130:0 Note on 0, note 43, velocity 100 130:0 Note off 0, note 43, velocity 64 130:0 Note on 0, note 41, velocity 100 130:0 Note off 0, note 41, velocity 64 130:0 Note on 0, note 40, velocity 100 130:0 Note off 0, note 40, velocity 64 130:0 Control change 0, controller 119, value 64 130:0 Note on 0, note 45, velocity 100 130:0 Note off 0, note 45, velocity 64

Si tout va bien, il devrait y avoir un message switching to scene X: Port Y chaque fois que ctrl_in reçoit un CC#119 ! (même si c'est la même scène plusieurs fois de suite !)


Intégrer à Ray Session


Pour rendre tout ça un peu plus facile à utiliser dans une session Ray, plutôt que de lancer le script dans un terminal, j'ai écrit un petit script batch qui lance mididings. Il a fallu ajouter une possibilité de détecter un SIGTERM pour que mididings s'arrête lorsqu'on appuie sur Stop dans Ray-Session :
Copy to clipboard
#!/bin/bash _term() { echo "Caught SIGTERM!" kill -TERM "$child" 2>/dev/null # Kills the child process if it is still running } trap _term SIGTERM # if the shell receives SIGTEM, the function _term is a trap handler before exiting # ending the command with & will background it into the shell's job control system mididings -R -f /home/zig/Software/mididings/mididings_randomFollowSeq.py & child=$! # The child signal's PID wait "$child" # waits for the job to finish, or for a signal

Alors pour expliquer ça rapidement (la logique n'est pas de moi mais je ne retrouve plus le post de forum qui m'a aidé, j'espère que ce que j'explique est correct !), la commande mididings est lancée avec & pour "sortir" de ce script, et le PID de mididings est enregistré dans la variable child.
Grâce à la ligne wait "$child", si $child s'arrête, ce script s'arrêtera.
Grâce à la ligne trap _term SIGTERM, la fonction _term sera appelée si le script reçoit le signal SIGTERM - par exemple si Ray Session l'arrête - et tuera le processus $child c'est-à-dire mididings !

RaySession Stop

Il ne reste qu'à lancer ce script bash grâce au bouton Exécutable dans Ray Session, et de l'enregistrer comme application par un clic droit et "Save as Application Template".



Détails à l'utilisation


J'ai mis en place ce script en pensant avoir par exemple une séquence de contrôle de 2 ou 4 mesures et des séquences d'instruments d'une ou 2 mesures, mais il est bien sûr aussi possible d'envoyer directement une des séquences sur ctrl_in en même temps que sur in_0 pour que la sélection aléatoire soit synchrone avec la longueur de la séquence 1.
Une petite image pour les connexions entre Seq64, mididings, le synthétiseur et jack mixer :

Connexions Carla



Liens et commentaires






[+]

Collaborateur(s) de cette page: olinuxx et zigmhount .
Page dernièrement modifiée le Samedi 23 mai 2020 16:20:16 par olinuxx.