• 0238494791
  • spgoo.ecpy@gmail.com

(PK – YS)

Dans le contexte de nos développements effectués avec les collègues du LLL et du LEO, nous sommes amenés à produire des musiques d’accompagnement sur nos plateformes ( Serious Games, Site de Vote …). Pour ce faire, nous avons plusieurs choix possibles prendre une musique existante ou en produire. Nous avons opté pour l’emploi de scamp pour deux raisons, produire ce que l’on veut sans droit d’auteur et pouvoir ensuite créer des mélodies à partir de fonctions mathématiques complexes.

Des outils utilisant python pour générer de la musique, scamp est, à ma connaissance, le plus élaboré. Il est actuellement développé par un musicien, Marc EvanStein. Voir sa chaîne Youtube.

Pour commencer, il faut suivre ces explications afin de s’assurer que tout fonctionne bien.

Voici le code minimum pour faire jouer un instrument.

from scamp import *

session = Session()
clarinet = session.new_part("clarinet")
clarinet.play_note(60, 0.8, 2.0)
from scamp import *
session = Session()
clarinet = session.new_part("clarinet")
oboe = session.new_part("oboe")
# instrument.play_note(note_midi, volume, durée)
# -------------------------------
clarinet.play_note(60, 0.8, 1.0)
oboe.play_note(80, 0.8, 1.0)
clarinet.play_note(65, 0.8, 1.0)
oboe.play_note(60, 0.8, 1.0)
from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
# ------------------------
brass.play_note(40, 1.0, 0.25)
brass.play_note(43, 1.0, 0.25)
brass.play_note(47, 1.0, 0.25)
brass.play_note(55, 1.0, 0.25)
brass.play_note(52, 1.0, 0.75)
brass.play_note(54, 1.0, 0.5)
brass.play_note(52, 1.0, 0.25)
brass.play_note(50, 1.0, 0.25)
wait(0.25)
brass.play_note(50, 1.0, 0.25)
wait(0.75)

En ajoutant une fonction.

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
# ------------------------
def beat_it():
    brass.play_note(40, 1.0, 0.25)
    brass.play_note(43, 1.0, 0.25)
    brass.play_note(47, 1.0, 0.25)
    brass.play_note(55, 1.0, 0.25)
    brass.play_note(52, 1.0, 0.75)
    brass.play_note(54, 1.0, 0.5)
    brass.play_note(52, 1.0, 0.25)
    brass.play_note(50, 1.0, 0.25)
    wait(0.25)
    brass.play_note(50, 1.0, 0.25)
    wait(0.25)

beat_it()
brass.play_note(40, 1.0, 2.25)
beat_it()

Complexifions un peu …

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
# ------------------------
def beat_it_1():
    brass.play_note(40, 1.0, 0.25)
    brass.play_note(43, 1.0, 0.25)
    brass.play_note(47, 1.0, 0.25)
    brass.play_note(55, 1.0, 0.25)
    brass.play_note(52, 1.0, 0.75)

def beat_it_2():
    brass.play_note(54, 1.0, 0.5)
    brass.play_note(52, 1.0, 0.25)
    brass.play_note(50, 1.0, 0.25)
    wait(0.25)
    brass.play_note(50, 1.0, 0.25)
    wait(0.25)
    
def beat_it():
    beat_it_1()
    beat_it_2()

beat_it_2()
brass.play_note(40, 1.0, 2.25)
beat_it()
beat_it_2()
brass.play_note(52, 1.0, 2.25)

Complexifions …

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
def beat_it_1(instr):
    instr.play_note(40, 1.0, 0.25)
    instr.play_note(43, 1.0, 0.25)
    instr.play_note(47, 1.0, 0.25)
    instr.play_note(55, 1.0, 0.25)
    instr.play_note(52, 1.0, 0.75)

def beat_it_2(instr):
    instr.play_note(54, 1.0, 0.5)
    instr.play_note(52, 1.0, 0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    
def beat_it(instr):
    beat_it_1(instr)
    beat_it_2(instr)
    
# def top_part():
#     brass.play_note(54, 1.0, 0.5)
#     brass.play_note(52, 1.0, 0.25)
#     brass.play_note(50, 1.0, 0.25)

beat_it_2(trumpet)
brass.play_note(40, 1.0, 2.25)
beat_it(brass)
beat_it_2(trumpet)
brass.play_note(52, 1.0, 2.25)

Complexifions …

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
def beat_it_1(instr):
    instr.play_note(40, 1.0, 0.25)
    instr.play_note(43, 1.0, 0.25)
    instr.play_note(47, 1.0, 0.25)
    instr.play_note(55, 1.0, 0.25)
    instr.play_note(52, 1.0, 0.75)

def beat_it_2(instr):
    instr.play_note(54, 1.0, 0.5)
    instr.play_note(52, 1.0, 0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    
def beat_it(instr):
    beat_it_1(instr)
    beat_it_2(instr)
    
def top_part(instr):
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 1.75)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 1.5)
    instr.play_note(71, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(74, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25, "staccato")
    instr.play_note(74, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25, "staccato") 

beat_it_2(trumpet)
brass.play_note(40, 1.0, 2.25)
beat_it(brass)
top_part(trumpet)
beat_it_2(trumpet)
beat_it(brass)
brass.play_note(52, 1.0, 2.25)

Pour pouvoir faire jouer deux partitions en même temps, il faut utiliser la fonction fork de l’objet session.

Exemple

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
def beat_it_1(instr):
    instr.play_note(40, 1.0, 0.25)
    instr.play_note(43, 1.0, 0.25)
    instr.play_note(47, 1.0, 0.25)
    instr.play_note(55, 1.0, 0.25)
    instr.play_note(52, 1.0, 0.75)

def beat_it_2(instr):
    instr.play_note(54, 1.0, 0.5)
    instr.play_note(52, 1.0, 0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    instr.play_note(50, 1.0, 0.25)
    wait(0.25)
    
def beat_it(instr):
    beat_it_1(instr)
    beat_it_2(instr)
    
def top_part(instr):
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 1.75)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 1.5)
    instr.play_note(71, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(71, 1.0, 0.25)
    instr.play_note(74, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25, "staccato")
    instr.play_note(74, 1.0, 0.5)
    instr.play_note(71, 1.0, 0.25, "staccato") 

beat_it_2(trumpet)
brass.play_note(40, 1.0, 2.25)
session.fork(beat_it, args[brass])
session.fork(top_part, args=[trumpet])
session.wait_for_children_to_finish()
beat_it_2(trumpet)
beat_it(brass)
brass.play_note(52, 1.0, 2.25)

Exemple

from scamp import Session, wait
session = Session()
brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
def beat_it_1(instr):
    instr.play_note(40, 1.0, 0.25)
    instr.play_note(43, 1.0, 0.25)
    instr.play_note(47, 1.0, 0.25)
    instr.play_note(55, 1.0, 0.25)
    instr.play_note(52, 1.0, 0.75)

def beat_it_2(
        instr,
        n=1,
        transpo=0,
    ):
    for _ in range(n):
        instr.play_note(54 + transpo, 1.0, 0.5)
        instr.play_note(52 + transpo, 1.0, 0.25)
        instr.play_note(50 + transpo, 1.0, 0.25)
        wait(0.25)
        instr.play_note(50 + transpo, 1.0, 0.25)
        wait(0.25)
    
def beat_it(instr):
    beat_it_1(instr)
    beat_it_2(instr)
    
def top_part(
        instr,
        transpo=0,
        vol=1, # volume
        dt1=0.25,
        dt2=0.5,
        dt3=1.5,
        ):
    instr.play_note(71 + transpo, 1.0, dt1)
    instr.play_note(71 + transpo, 1.0, dt3)
    instr.play_note(71 + transpo, 1.0, dt1)
    instr.play_note(71 + transpo, 1.0, dt3)
    instr.play_note(71 + transpo, 1.0, dt2)
    instr.play_note(71 + transpo, 1.0, dt1)
    instr.play_note(71 + transpo, 1.0, dt1)
    instr.play_note(71 + transpo, 1.0, dt1)
    instr.play_note(74 + transpo, 1.0, dt2)
    instr.play_note(71 + transpo, 1.0, dt1, "staccato")
    instr.play_note(74 + transpo, 1.0, dt2)
    instr.play_note(71 + transpo, 1.0, dt1, "staccato") 

beat_it_2(trumpet)
brass.play_note(40, 1.0, 2.25)
session.fork(beat_it, args=[brass])
session.fork(top_part, args=[trumpet, -12])
session.wait_for_children_to_finish()
# -------------------------------------
session.fork(top_part, args=[brass])
session.fork(beat_it, args=[trumpet])
session.wait_for_children_to_finish()
# -------------------------------------
session.fork(beat_it_2, args=[trumpet,3, 12])
session.fork(beat_it, args=[brass])
session.wait_for_children_to_finish()
# -------------------------------------
brass.play_note(52, 1.0, 2.25)

Le tempo global définie dans la session peut être modifié pour un instrument donné à l’aide de current_clock.

Exemple

from scamp import Session, wait, current_clock
session = Session()
brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
def beat_it_1(
        instr,
        n=1,
        tempo=60,
        transpo=0,
    ):
    instr.play_note(40 + transpo, 1.0, 0.25)
    instr.play_note(43 + transpo, 1.0, 0.25)
    instr.play_note(47 + transpo, 1.0, 0.25)
    instr.play_note(55 + transpo, 1.0, 0.25)
    instr.play_note(52 + transpo, 1.0, 0.75)

def beat_it_2(
        instr,
        n=1,
        tempo=60,
        transpo=0,
    ):
    current_clock().tempo=tempo
    for _ in range(n):
        instr.play_note(54 + transpo, 1.0, 0.5)
        instr.play_note(52 + transpo, 1.0, 0.25)
        instr.play_note(50 + transpo, 1.0, 0.25)
        wait(0.25)
        instr.play_note(50 + transpo, 1.0, 0.25)
        wait(0.25)
    
def beat_it(
        instr,
        n=1,
        tempo=60,
        transpo=0,
    ):
    current_clock().tempo=tempo
    beat_it_1(
        instr,
        n=n,
        tempo=tempo,
        transpo=transpo,
        )
    beat_it_2(
        instr,
        n=n,
        tempo=tempo,
        transpo=transpo,
        )
    
def top_part(
        instr,
        n=1,
        tempo=60,
        transpo=0,
        vol=1, # volume
        dt1=0.25,
        dt2=0.5,
        dt3=1.5,
    ):
    current_clock().tempo=tempo
    for _ in range(n):
        instr.play_note(71 + transpo, 1.0, dt1)
        instr.play_note(71 + transpo, 1.0, dt3)
        instr.play_note(71 + transpo, 1.0, dt1)
        instr.play_note(71 + transpo, 1.0, dt3)
        instr.play_note(71 + transpo, 1.0, dt2)
        instr.play_note(71 + transpo, 1.0, dt1)
        instr.play_note(71 + transpo, 1.0, dt1)
        instr.play_note(71 + transpo, 1.0, dt1)
        instr.play_note(74 + transpo, 1.0, dt2)
        instr.play_note(71 + transpo, 1.0, dt1, "staccato")
        instr.play_note(74 + transpo, 1.0, dt2)
        instr.play_note(71 + transpo, 1.0, dt1, "staccato") 

# main part
# ------------------------------------
beat_it_2(trumpet, n=2)
brass.play_note(40, 1.0, 2.25)
session.fork(beat_it, args=[brass,2,120])
session.fork(top_part, args=[trumpet,1,80,-12])
session.wait_for_children_to_finish()
# -------------------------------------
brass.play_note(47, 1.0, 0.5)
brass.play_note(40, 1.0, 2.25)
# -------------------------------------
session.fork(top_part, args=[brass,3,80])
session.fork(beat_it, args=[trumpet,4])
session.wait_for_children_to_finish()
# -------------------------------------
brass.play_note(40, 1.0, 2.25)
# -------------------------------------
session.fork(beat_it_2, args=[trumpet,3,120, 12])
session.fork(beat_it, args=[brass,3,120])
session.wait_for_children_to_finish()
# -------------------------------------
brass.play_note(52, 1.0, 2.25)

En modifiant uniquement la main part. Avec la fonction wait_for_childre_to_finish, il est possible de faire jouer ensemble plusieurs instruments qui s’attendent avant de passer à l’étape suivante.

while True:
    tempo=random.choice([90,120])
    session.fork(top_part, args=[trumpet,1,tempo])
    n = random.choice([1,2])
    tempo=random.choice([90,120])
    beat_it(brass,n, tempo)
    session.wait_for_children_to_finish()

Autre exemple

# main part
# ------------------------------------
while True:
    beat_it_2(trumpet, n=2)
    brass.play_note(40, 1.0, 2.25)
    session.fork(beat_it, args=[brass,2,80])
    session.fork(top_part, args=[trumpet,1,120,12])
    session.wait_for_children_to_finish()

Tester l’exemple précédent en désindendant la dernière ligne …

Génération de musique aléatoire

Exemple 1

from scamp import Session, wait, current_clock
import random

session = Session()

brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
# ------------------------
Lpitch = [60,70,70,80,78]
Ldure = [0.25, 0.5, 0.75]

while True:
    p = random.random()
    if p < 0.7:
        trumpet.play_note(random.choice(Lpitch), random.uniform(0.4, 0.9), 0.25)
    elif p < 0.9:
        brass.play_note(random.choice(Lpitch), random.uniform(0.4, 0.9), random.choice(Ldure))
    else:
        wait(random.choice(Ldure))

Exemple 2

from scamp import Session, wait, current_clock
import random

session = Session()

brass = session.new_part("brass")
trumpet = session.new_part("trumpet")
clarinet = session.new_part("clarinet")
# ------------------------
Lpitch0 = [60,67,72,77]
Ldure = [0.25, 0.5, 0.75]


while True:
    i0 = random.choice([0,2])
    Lpitch = Lpitch0[i0:]
    for _ in range(4):
        p = random.random()
        if p < 0.5:
            brass.play_note(random.choice(Lpitch), random.uniform(0.4, 0.9), 0.25)
        elif p < 0.75:
            trumpet.play_note(random.choice(Lpitch), random.uniform(0.4, 0.9), random.choice(Ldure))
        else:
            if p < 0.9:
                clarinet.play_note(random.choice(Lpitch), 1, 0.25)
                clarinet.play_note(random.choice(Lpitch)+4, 1, random.choice(Ldure))
            elif p < 0.95:
                clarinet.play_note(random.choice(Lpitch)+5, 1, random.choice(Ldure))
                clarinet.play_note(random.choice(Lpitch), 1, 0.25)
            else:
                clarinet.play_note(random.choice(Lpitch), 1, random.choice(Ldure))       

Musique composée aléatoire

Génération de partitions

Simple visualisation du fichier

Le script suivant permet de générer une partition pour un morceau à deux voix. Les explications sont données en commentaires.

from scamp import Session, wait, current_clock
import random
session = Session()
session.fast_forward_to_beat(100) # Avancement rapide du commencement du morceau.
#---------------------------------------
# Définition des instruments
#---------------------------------------
trumpet = session.new_part("trumpet")
brass = session.new_part("brass")
#---------------------------------------
# Définition d'une ligne de basse
#---------------------------------------
Lpitch_bass = [58, 57, 56, 55, 54, 51, 53, 51, 48, 45]*2 + [46, 47, 48, 49, 50, 53, 56, 55, 52, 53, 55]
#---------------------------------------
# Défintion de motifs pouvant être joués sur la note de basse
#---------------------------------------
LLpattern = [
                [20,15, 20],
                [None, 12, None, 15,None,20],
                [12, None, 15,None,20, None],
                [None, 12, 14, 15],
                [None, 15, 9, 12],
                [12,15,12,15,17,12,17,12,15],
                [12,9,12,9,12,9,12,9,15],
                [19, 17, 16],
            ]
#---------------------------------------
# Définition de la fonction de la basse
#---------------------------------------
def bass_part(instr):
    for pitch in Lpitch_bass:
        p = random.random()
        if p < 0.5:
            instr.play_note(pitch, 1, 1)
        elif p < 0.75:
            instr.play_note(pitch, 1, 0.5)
            wait(0.5)
        else:
            instr.play_note(pitch, 1, 0.5)
            instr.play_note(pitch-5, 1, 0.5)
#---------------------------------------
# Définition du solo
#---------------------------------------
def solo_part(instr):
    for pitch_bass in Lpitch_bass:
        Lpattern = random.choice(LLpattern)
        nLpattern  = len(Lpattern)
        dure = 1/nLpattern
        for interval in Lpattern:
            if interval is None:
                wait(dure)
            else:
                instr.play_note(pitch_bass + interval, 1, dure)
#---------------------------------------
# Lancement du script
#---------------------------------------            
session.start_transcribing() # Début de convertion en partition
session.fork(solo_part, args=[trumpet])
session.fork(bass_part, args=[brass])
session.wait_for_children_to_finish()
session.stop_transcribing().to_score().show() # Fin de conversion en partition et affichage
            

Export d’un fichier xml

Voici enfin un morceau plus complexe. Scamp génère un fichier xml et il est possible de faire jouer le tout dans MuseScore.

from scamp import Session, wait, current_clock
import random
session = Session()

session.fast_forward_to_beat(1000)


trumpet = session.new_part("trumpet")
trombone = session.new_part("trombone")
clarinet = session.new_part("clarinet")
alto_sax = session.new_part("alto_sax")
brass = session.new_part("brass")
brass2 = session.new_part("brass")
brass3 = session.new_part("brass")

# ------------------------

Lpitch_bass = [(4,9), (5,2), (4,7)]*2 + [(5,0), (4,7), (4,4)] 

LLpattern = [
                [12],
                [12,17],
                [12,19],
                [12,17,19],
                [12,14,19],
                [12,9,17],
                [12,17,12, 17],
                [19,17,19, 19],
                [10,12,14, 17],
                [17,14,12, 10],
                #[None, 12, None, 15,None,20],
                #[12, None, 15,None,20, None],
                #[None, 12, 14, 15],
                #[None, 15, 9, 12],
                #[12,15,12,15,17,12,17,12,15],
                #[12,9,12,9,12,9,12,9,15],
                #[19, 17, 16],
            ]

def bass_part(instr, transpo=0):
    for pitch in Lpitch_bass:
        if type(pitch) is tuple:
            pitch = pitch[0]*12 + pitch[1]
        Lpattern = random.choice(LLpattern[:3])
        nLpattern  = len(Lpattern)
        dure = 1/nLpattern
        for interval in Lpattern:
            if interval is None:
                wait(dure)
            else:
                instr.play_note(pitch + interval +transpo, 1, dure)

            
        
def solo_part(instr, transpo=0):
    for pitch in Lpitch_bass:
        if type(pitch) is tuple:
            pitch = pitch[0]*12 + pitch[1]
        Lpattern = random.choice(LLpattern[1:])
        nLpattern  = len(Lpattern)
        dure = 1/nLpattern
        for interval in Lpattern:
            if interval is None:
                wait(dure)
            else:
                instr.play_note(pitch + interval + transpo, 1, dure)
                
session.start_transcribing()
for _ in range(8):
    instr,transpo =  random.choice([(trumpet,0), (trombone, -7)])
    session.fork(solo_part, args=[instr, transpo])
    instr,transpo =  random.choice([(clarinet,0), (alto_sax, -7)])
    session.fork(solo_part, args=[instr, transpo])
    instr,transpo =  random.choice([(brass,-12), (brass2, -7)])
    session.fork(bass_part, args=[instr, transpo])
    session.fork(bass_part, args=[brass3])
    session.wait_for_children_to_finish()
session.stop_transcribing().to_score().export_music_xml("test.xml")
            

Randzik

Voici un code plus complet qui permet de générer des morceaux qui commencent à devenir intéressants:

from scamp import Session, wait, current_clock
from random import randint, choice, random, sample, shuffle, choices, seed
from itertools import cycle
import numpy as np
session = Session(tempo=60)

session.fast_forward_to_beat(1000)

seed(40)


# ------------------------
Lmajeur = [0,2,4,5,7,9,11]
V0 = np.array(Lmajeur)
LL = []
for k in range(2,10):
    LL.append(list(k*12+V0))  
Vmajeur0 = np.append(Lmajeur, LL)
# ------------------------
Lmineur = [0,2,3,5,7,8,10]
V0 = np.array(Lmineur)
LL = []
for k in range(2,10):
    LL.append(list(k*12+V0)) 
Vmineur0 = np.append(Lmineur, LL)


def get_pitch_in_tonality(pitch):
    return Vgamme[np.argmin(np.abs(Vgamme-pitch))]
    

def do_part(
        instr,
        pitch=None,
        transpo=0,
        LT_pattern=None,
        ):
    pitch = pitch[0]*12 + pitch[1]
    for T in LT_pattern:
        if len(T) == 2:
            n = 1
        else:
            n = T[2]
        for _ in range(n):
            if type(T[0]) is tuple:
                L = T[0]
            else:
                L = [T[0]]
            for x in L:
                if x is None:
                    wait(T[1])
                else:
                    pitch2 = get_pitch_in_tonality(pitch + x + transpo)
                    instr.play_note(pitch2, 1, T[1])


k=5
Dinst = dict()

def get_Icycle(
    LT,
    n=3
    ):
    return   cycle(choices(LT,k=n))


bass = session.new_part("Tuba")
Dinst[bass]={
            "transpo":-12,
            }

bariton_sax = session.new_part("Bariton sax")
Dinst[bariton_sax]={
            "transpo":0,
            }


trombone = session.new_part("trombone")
Dinst[trombone]={
            "transpo":0,
            }

alto =  session.new_part("alto sax")
Dinst[alto]={
            "transpo":0,
            }

soprano =  session.new_part("soprano sax")
Dinst[soprano]={
            "transpo":12,
            }


clarinet = session.new_part("clarinet")
Dinst[clarinet]={
            "transpo":12,
            }

cors =  session.new_part("French Horns")
Dinst[cors]={
            "transpo":12,
            }

trumpet = session.new_part("trumpet")
Dinst[trumpet]={
            "transpo":12,
            }

flute = session.new_part("Pan Flute")
Dinst[flute]={
            "transpo":24,
            }

violon = session.new_part("Violin")
Dinst[violon]={
            "transpo":12,
            }


Dvoix = dict()
Dvoix[0] = {
            "Linst":[bass],
            "Icycle":get_Icycle([
                                    ((0,),1),
                                    ((0,0),1/2),
                                    ((0,),1/2,(0,0),1/4),
                                    ],
                                    5),
            }
Dvoix[1] = {
            "Linst":[bariton_sax, ],
            "Icycle":get_Icycle([
                                    ((4,),1),
                                    ((0,4),1/2),
                                    ],
                                6),
            }
Dvoix[2] = {
            "Linst":[trombone,cors, alto, ],
            "Icycle":get_Icycle([
                                    ((7,),1),
                                    ((0,7),1/2),
                                    ((9,7),1/2),
                                    ],
                                7),
            }
Dvoix[3] = {
            "Linst":[trumpet, violon,soprano],
            "Icycle":get_Icycle([
                                    ((0,),1),
                                    ((0,2),1/2),
                                    ((4,),1),
                                    ((0,4),1/2),
                                    ((0,2,4),1/3),
                                    ((0,2,4,7),1/4),
                                    ],
                                10),
            }
Dvoix[4] = {
            "Linst":[flute, clarinet],
            "Icycle":get_Icycle([
                                    ((0,),1),
                                    ((0,4),1/2),
                                    ((7,),1),
                                    ((7,10),1/2),
                                    ((7,10,4),1/3),
                                    ((7,2,4,7),1/4),
                                    ],
                                10),
            }

Ln_inst=[3]
cycle_n_inst = cycle([4,5,6])
Li_pattern_inst = list(range(len(Dinst)))
Linst = list(Dinst.keys())
session.start_transcribing()
LTv0 = [(0,"M"),(1,"M"),(2,"M"),(1,"M"),(0,"M"),(-1,"M")]
LTv0 += reversed(LTv0)
LTv = []
for _ in range(3):
    LTv += LTv0
    
Tv0 = None
nLTv = len(LTv)
for i in  range(nLTv):
    if LTv[i][1] =="M":
        Vgamme = Vmajeur0 + (LTv[i][0]*7)%12
    else:
        Vgamme = Vmineur0 + (LTv[i][0]*7)%12
    LTpitch_bass =  [((4,0),2)] + [((4,randint(0,12)),choice([1,2,3])) for _ in range(choice([4,8]))]
    if i == nLTv -1:
        LTpitch_bass.append(((4,0),2))
    else:
        d = LTv[i+1][0]-LTv[i][0]
        if d == 1:
            LTpitch_bass.append(((4,7),2))
        elif d == -1:
            LTpitch_bass.append(((4,5),2))
        
    LT = list(Dvoix.items())
    for voix,D in LT:
        Linst2 = []
        for inst in D["Linst"]:
            if random()< 0.5:
                Linst2.append(inst)
        if len(Linst2) == 0:
            Linst2 = [inst]
        Dvoix[voix]["Linst2"]=Linst2
    for Tpitch_bass in LTpitch_bass: 
        for D in Dvoix.values():
            pitch_bass, n= Tpitch_bass
            Li = [next(D["Icycle"]) for _ in range(n)]
            for inst in D["Linst2"]:
                session.fork(do_part, args=[inst, pitch_bass, Dinst[inst]["transpo"],Li])
        session.wait_for_children_to_finish()


session.stop_transcribing().to_score().export_music_xml("Randzik_10_v1.xml")