Informatique musicale : créer un séquenceur pas-à-pas avec Python

Informatique musicale : créer un séquenceur pas-à-pas avec Python

Pycon-Fr 2016, Rennes

Aujourd’hui, que ce soit via « Maschine » de Native Instruments, « Push » de Ableton, ou encore via des machines à l’esprit plus vintage comme le « Dark Time » de Doepfer ou des émulations de vieilles boites à rythmes, les musiciens retrouvent le goût du séquencement pas à pas ou « Step Sequencing ».
Le bidouilleur que je suis avait envie de détourner son matériel pour reproduire ce type d’outil de création…

Après une introduction au MIDI et aux principes d’un séquenceur, nous verrons comment nous pouvons, avec Python et la librairie mido, « hacker » un certain synthétiseur hardware pour en faire un séquenceur pas à pas, à l’aide d’une boucle d’événements. Nous essaierons même de l’interfacer avec Ableton Live pour contrôler non plus les sons du synthétiseur, mais des samples !

Vidéo disponible ici :

Nowadays, using Native Instruments "Maschine", Ableton "Push", or machines with a vintage heritage such as Doepfer "Dark Time", musicians enjoy getting back to a special kind of sequencing which is step sequencing.
I wanted to hack with my current hardware to try and do the same as these tools.

After an introduction to MIDI and notions of sequencing, we will see how, thanks to Python and the Mido library, we can hack hardware to turn it into a step sequencer, using an event loop. We will try and interface our program with Ableton Live to control not only sounds from the synthetizer, but also trigger samples!

Video (in French) available @


Yann Gravrand

October 16, 2016


  1. BUILD A STEP SEQUENCER IN PYTHON Pycon-Fr, Rennes, 2016

  2. WHO AM I? Yann Gravrand (@ygravrand) Tech lead Musicos

  3. PART 1: BACKGROUND Musical instruments Synthetizers and samplers Sequencers Step

  4. MUSICAL INSTRUMENTS Can be played by humans Some can be

    "played" by computers: Synthetizers Samplers ...
  5. SYNTHETIZERS Sound generators Generally, a lot of parameters can be

  6. FAMOUS SYNTHETIZERS Minimoog (analog) : 70s DX7 (digital) : 80s

  7. FAMOUS SYNTHETIZERS Nord Lead (analog modeling) Mininova (analog modeling)

  8. VST VST Plugins

  9. SAMPLERS Do not generate sounds themselves Play samples (little chunks

    of sound)
  10. SAMPLES / NOTES: One sample for the whole keyboard (pitch

    adjusted or not)
  11. One sample for each note

  12. One sample for a group of notes, pitch is ajusted

  13. DRUM MACHINES? Sound generator + step sequencer TR 909 Tempest

  14. SEQUENCERS Play a sequence of notes Several tracks, instruments...

  15. STEP SEQUENCER A 4/4 measure is divided into: 4 quarter

    notes Each quarter note is divided into 4 steps --> A sequence is usually 16 steps long
  16. STEP SEQUENCER Example: on the TR 808

  17. STEP SEQUENCER For each step, we define: the note /

    pitch other attributes: length... ... and activate it or not
  18. EXAMPLES Daft punk - Aerodynamic @ 1:03 4 * 16-step

  19. EXAMPLES Daft punk - Aerodynamic @ 2:28 4 * 16-step

    patterns, some notes off
  20. USING A STEP SEQUENCER "Live" mode: turn steps on and

    off in real time, adjust pitch, length... "Step by step" mode: for each step, define the note attributes. No timing, no rush
  21. PART 2: THE PROJECT Project goals MIDI Using mido The

    Dirty Part: blocking, threads, asyncio...
  22. I HAD A cool synth Colorful (and empty) pads

  23. AND A snake

  24. PROJECT GOALS Make the synthetizer play notes using Python Modify

    and turn notes on / off to create a sequence Implement "step by step" and "live" modes Change tempo in real time Make interactions possible with any controller... ... Starting with mine, of course :)
  25. MIDI: MUSICAL INSTRUMENT DIGITAL INTERFACE Extremely old standard: 1983! Still

    largely in use today To synchronize and communicate between devices Message types: Notes (NOTE ON, NOTE OFF) Control Change (Ex: Filter resonance, Hold pedal...) Program Change (Change instrument) Sys ex ...

    pads pressed, keys pressed, knobs turned... Midi output: play a note, turn a LED on...
  27. MIDI INPUT: RECEIVING MESSAGES Message reception blocks So if we

    want to do something else in parallel, we have to handle this in a thread or coroutine or...? inport = mido.open_input() msg = inport.receive() # Blocking call

    play notes, we need a timer between NOTE_ON and NOTE_OFF (note duration). time.sleep? import mido outport = mido.open_output() msg = mido.Message('note_on', note=100, velocity=3) outport.send(msg) outport.send(mido.Message('note_off', note=100))
  29. ALIGNING NOTES (STEPS) WITH TEMPO Naive implementation: Two problems: time.sleep

    also blocks, so we have to handle it in a thread or coroutine or... Waking up, sleeping for X seconds, waking up...: the tempo slowly drifts while True: outport.send(mido.Message(...)) time.sleep(tempo.step_duration)

    have: 1. independent yet connected blocking loops? 2. timing accuracy to keep a stable tempo?
  31. SOLUTIONS Threads Many queues to avoid shared state Coroutines with

    asyncio Everything in a single thread, less concurrency issues Ok since our app is I/O bound ...But we have to modify mido to insert yield from or await... Greenlets with gevent Monkey patches time.sleep so we can use mido as is and have greenlets Drifting? calculate absolute times
  32. PROPOSED DESIGN Main process is I/O bound Console process is

    CPU bound!
  33. PART 3: IMPLEMENTATION & DEMO System overview Implementing a controller


  35. IMPLEMENTING A CONTROLLER Map messages from controller (pad pressed) to

    sequencer actions (toggle step) Send messages to controller for feedback (LEDs...)
  36. INTERPRETING EVENTS Some events are represented by a single message

    Others are the result of a sequence of messages (ex: NPRN LSB, MSB) Solution: a RulesChain Each Rule matches a message A state automaton keeps track of the matched rules Flexible rules evaluation engine self.register('FILTER', self.on_cc, RulesChain(Rule(type_='control_change', control='74'), Rule(type_='control_change', control='27', value='0')) )
  37. REACTING TO SEQUENCER STATES Event system: self.sequencer.on(SequencerEvents.STEP_BEGIN, self, self.on_step_begin) ...

    def on_step_begin(self, step): # Turn on current step LED self.sequencer.output(self, *msb_lsb_output(60, 0, 32 + step.pos))
  38. IN ACTION!

  39. IN ACTION! Bass pattern Drum pattern 1 Drum pattern 2

    Mozart pattern (32-step sequence) Daft punk - da funk
  40. FUTURE Plans: Release in Open Source Chords (especially important for

    a drum machine...) Multi track Load / save to midi External tempo sync Reactive Web interface (iPad, ...) Conquer the world!
  41. THANK YOU! @ygravrand Soon: