Chargement...
 
[Voir/Cacher menus de gauche]
[Voir/Cacher menus de droite]

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.

Image

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.

Image



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) :
# 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 :
Image


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 :
# 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 :

Image
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 :
# 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) :
# Picks a random scene in the set of active scenes
def randscene(ev):
    pickedscene=sample(ACTIVESCENES,1)[0]
    switch_scene(pickedscene)
    return ev

notenote
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 :
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.

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 :
> $ 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 :
> $ 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 :
#!/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 !

Image

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 :

Image



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.
Le contenu de cette page est licencié sous les termes licence.

Documentation [Afficher / Cacher]

Connexion
[Afficher / Cacher]

tongo


Mégaphone [Afficher / Cacher]

dlb, 22:15, sam. 05 Dec 2020: Très bel édito, merci !
r1, 22:02, sam. 05 Dec 2020: Mais qu'il est beau, cet édito !
allany, 11:23, sam. 05 Dec 2020: Rien de démago, c'est l'édito ! [Lien]
calixtus06, 09:54, jeu. 03 Dec 2020: Bonjour et bienvenue à 2lafru ! :-)
olinuxx, 15:14, mar. 01 Dec 2020: Bonjour et bienvenue à Soso et gegeweb cool
calixtus06, 11:21, lun. 30 Nov 2020: Bonjour et bienvenue à n0n3m ! :-)
calixtus06, 07:29, dim. 29 Nov 2020: Bonjour et bienvenue à Iluvatar ! :-)
olinuxx, 12:35, sam. 28 Nov 2020: Nouvelles du mois de novembre pour LibraZiK : [Lien]
olinuxx, 12:34, sam. 28 Nov 2020: Bonjour et bienvenue à diogene et à klopkloc cool
olinuxx, 19:45, mer. 25 Nov 2020: Bonjour et bienvenue à endymion93 cool
calixtus06, 07:13, mar. 24 Nov 2020: Bonjour et bienvenue à Noxanera ! :-)
sub26nico, 10:40, lun. 23 Nov 2020: Ardour 6.5 est disponible, le bogue d'export a été corrigé