Mini-projet : Conception d’un contrôleur MIDI + DMX

Le but de ce mini-projet est de concevoir son propre contrôleur MIDI et DMX pour faire de la MAO (Musique Assistée par Ordinateur) avec le logiciel Ableton Live et de synchroniser la lumière avec le son. Plusieurs étapes permettront de comprendre le fonctionnement d’un contrôleur MIDI et de la MAO :

Préambule

Le Musical Instrument Digital Interface ou MIDI est un protocole de communication et un format de fichier dédiés à la musique, et utilisés pour la communication entre instruments électroniquescontrôleursséquenceurs, et logiciels de musique.

Apparu dans les années 1980, issu d’une volonté de l’industrie de normaliser les échanges entre les différents instruments, ce protocole est devenu aujourd’hui un standard très répandu dans le matériel électronique de musique.

Wikipédia (MIDI)

Le contrôleur MIDI que l’on va concevoir ici permettra d’envoyer et de recevoir des messages MIDI afin de faciliter l’utilisation d’un logiciel de MAO (Musique Assistée par Ordinateur).

Le logiciel de MAO que l’on utilisera est Ableton Live (version Ableton Live 11 Intro).

Voici une vidéo d’exemple d’une utilisation d’un contrôleur MIDI avec Ableton Live :

Pour comprendre le fonctionnement de la MAO nous allons d’abord nous intéresser à la synthèse sonore et ses différents paramètres. Nous pourrons ensuite apprendre à utiliser le logiciel Ableton Live pour ensuite construire notre propre contrôleur MIDI.

Introduction à la synthèse sonore

https://www.youtube.com/watch?v=QEpk6feHMxQ

https://www.youtube.com/watch?v=0kW6ZMaDhGk

https://classic-intro.net/introductionalamusique/vingtieme3.html

Pour apprendre à utiliser les séquenceurs et les synthétiseurs, Ableton a créé une application en ligne sous forme de tutoriel. Suivre ce tutoriel sur le lien ci-dessous.

Learning music from Ableton

Learning Synths from Ableton

Conception d’un contrôleur MIDI et DMX :

Maintenant que nous savons utilisez Ableton Live il est temps de créer un contrôleur MIDI qui vous facilitera son utilisation.

Le contrôleur que vous allez concevoir permettra de gérer une piste d’instrument virtuel. Vous allez dans un premier temps choisir votre interface avec les capteurs à votre disposition pour modifier des effets, le volume, le pitch, etc… Vous devrez ensuite programmer une carte électronique rattaché à ces capteurs pour envoyer les bons messages MIDI via la liaison USB à l’ordinateur et au logiciel. La dernière phase sera de rattacher les commandes MIDI à Ableton Live.

Le contrôleur nous permettra aussi de contrôler une lumière scénique via le protocole DMX.

Vous êtes en binôme, un élève s’occupera de la partie DMX tandis que l’autre s’occupera de la partie MIDI. Il est cependant nécessaire de vous coordonner pour l’utilisation des capteurs et vous pouvez évidemment vous entraider.

L’interface

Vous allez programmer plusieurs capteurs afin qu’ils contrôlent le logiciel Ableton via le protocole MIDI et le projecteur via le protocole DMX.

Pour cela vous devez utiliser les capteurs suivants :

  • 1 bouton poussoir rouge – Active/désactive le son de l’instrument Ableton.
  • 1 bouton poussoir bleu – Active/désactive la lumière du projecteur DMX.
  • 1 fader – Modifie la valeur du volume de l’instrument Ableton / Fais varier l’intensité lumineuse du projecteur DMX.
  • 3 potentiomètres rotatifs – Modifie la valeur d’un effet de l’instrument Ableton et du projecteur DMX.
  • 1 encodeur optique – Modifie la valeur d’un effet de l’instrument Ableton et du projecteur DMX.
  • 1 sélecteur – Change le son de l’instrument Ableton / Change un effet sur le projecteur DMX.
  • 1 ou 4 PAD Trellis de 16 touches – Sert de séquenceur pour l’instrument Ableton / Active et désactive le projecteur DMX pour un effet stroboscopique qui suit le rythme de la musique.
  • 1 bouton poussoir jaune – Active/désactive un effet de l’instrument d’Ableton / Active/désactive le suivi du pad pour l’effet stroboscopique du projecteur DMX.
  • Au choix :
    • 1 capteur ToF de distance – Modifie la valeur d’un effet de l’instrument Ableton et du projecteur DMX.
    • 1 joystick – Modifie la valeur de deux effets (X et Y) de l’instrument Ableton et du projecteur DMX.
    • 1 gyroscope/accéléromètre MPU 6050 – Modifie la valeur d’un ou plusieurs effets de l’instrument Ableton et du projecteur DMX.
  • 1 bouton poussoir vert lié au capteur précédent – Active/désactive l’envoi de donnée du capteur.

Programmation

Pour la programmation des différents capteurs nous utiliserons une carte Teensy 4.0 qui est particulièrement adaptée pour la communication MIDI ainsi que l’environnement de programmation Arduino.

Vous pouvez vous référerez au 2 activités effectuées précédemment pour reprendre les bases de programmation DMX et MIDI :

A la suite vous trouverez aussi plusieurs ressources vous permettant d’avancer dans ce projet.

Les boutons poussoirs

Pour l’utilisation de bouton vous pouvez vous aider de cette page et utiliser la bibliothèque « bounce.h » :

Lien vers la page

Envoi des messages MIDI

La suite consiste à envoyer des messages MIDI par la connexion USB, dans « outils », sélectionner « MIDIx4 » dans « USB type » (il ne sera alors plus possible d’utiliser le moniteur série).

En reprenant l’activité déjà effectué sur la génération d’une note MIDI et en s’aidant de la documentation sur la gestion MIDI de la carte Teensy (https://www.pjrc.com/teensy/td_midi.html), modifier votre code pour envoyer les messages MIDI souhaités.

Pour envoyer des notes on utilisera les commandes :

usbMIDI.sendNoteOn(note, velocity, channel);
usbMIDI.sendNoteOff(note, velocity, channel);

Pour envoyer des valeurs de paramètres (effets, volumes, etc…) on utilisera la commande :

usbMIDI.sendControlChange(control, value, channel);

Programme exemple modification effet avec 2 potentiomètres rotatifs et 1 fader

// -------------------------------------------------------------
// TEENSY 4.0 – Contrôleur MIDI USB
// Potentiomètres et fader - Envoi des messages Control Change (CC)
// Mode USB : "Serial + MIDI"
// -------------------------------------------------------------

// Broches des potentiomètres
const int pot1 = 14;      // Potentiomètre 1 branché sur 14 
const int pot2 = 15;      // Potentiomètre 2 branché sur 15
const int fad1 = 16;      // Fader 1 branché sur 16
const int canal = 1;      // Canal MIDI utilisé (1 à 16) - un canal différent par contrôleur

// Structure représentant un potentiomètre MIDI
struct Pot {
  int broche;         // Entrée analogique sur la Teensy
  int numeroCC;       // Numéro du Control Change (0–127)
  int derniereValeur; // Dernière valeur envoyée (pour éviter les doublons)
};

// Tableau contenant deux potentiomètres + un fader
Pot pot[] = {
  { pot1, 3, -1 },   // CC3 (Control Change n°3)
  { pot2, 4, -1 },    // CC3 (Control Change n°4)
  { fad1, 1, -1 }
};
const int nbPot = sizeof(pot) / sizeof(pot[0]);

// -------------------------------------------------------------
// Fonction : lire et envoyer la valeur d’un potentiomètre en MIDI
// -------------------------------------------------------------
void gererPot(Pot &p) {
  int valeur = analogRead(p.broche); // Convertit 0–1023 → 0–127
  // N’envoie que si la variation est significative (> 1)
  if (abs(valeur - p.derniereValeur) > 8) {
    int valeur_midi = valeur/8;
    usbMIDI.sendControlChange(p.numeroCC, valeur_midi, canal);
    Serial.printf("CC%d = %d\n", p.numeroCC, valeur_midi);
    p.derniereValeur = valeur;
  }
}

// -------------------------------------------------------------
// Initialisation
// -------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.printf("=== Contrôleur MIDI === Canal %d ===\n", canal);
}

// -------------------------------------------------------------
// Boucle principale
// -------------------------------------------------------------
void loop() {
  // Lecture et envoi MIDI de chaque potentiomètre
  for (int i = 0; i < nbPot; i++) {
    gererPot(pot[i]);
  }

  delay(20); // Fréquence d’envoi ≈ 50 fois par seconde
}

Définition d’un nom le contrôleur

Créer un fichier texte « name.c » et l’enregistrer dans le dossier où se situe le programme Arduino.

Copier-coller les lignes de codes suivantes dans le fichier et remplacer les caractères dans la variable MIDI_NAME par ceux de votre nouveau nom de contrôleur et en remplaçant la valeur de la variable MIDI_NAME_LEN par le nombre de caractère de votre nouveau nom.

#include "usb_names.h"

#define MIDI_NAME   {'B','A','R',' ','1'}
#define MIDI_NAME_LEN  5

struct usb_string_descriptor_struct usb_string_product_name = {
        2 + MIDI_NAME_LEN * 2,
        3,
        MIDI_NAME
};

Enregistrer à nouveau votre fichier.

Le PAD Trellis d’Adafruit

Voici le programme permettant d’utiliser le pad en tant que séquenceur sur Ableton (la bibliothèque Trellis doit être installée) :

#include <Wire.h>
#include "Adafruit_Trellis.h"

// ---------- Trellis 4x4 ----------
Adafruit_Trellis matrix0 = Adafruit_Trellis();
Adafruit_TrellisSet trellis = Adafruit_TrellisSet(&matrix0);
const byte TRELLIS_ADDR = 0x70;
const int  NUM_STEPS    = 16;

// ---------- MIDI ----------
const byte MIDI_CH   = 6;
const byte NOTE_BASE = 60;
const byte VEL       = 100;

// ---------- Séquence ----------
bool stepOn[NUM_STEPS];
int  currentStep = 0;

// ---------- MIDI clock 24 ppqn ----------
volatile uint8_t clockTicks = 0;
volatile bool    running    = false;
volatile bool    stepPending = false; // <- FLAG pour demander un "advanceStep" dans loop()

// ---------- timing scan Trellis ----------
uint32_t lastScanMs = 0;
const uint32_t SCAN_PERIOD_MS = 20;

// ---------- helpers LEDs ----------
static inline void setLED(uint8_t i, bool on) {
  if (on) trellis.setLED(i);
  else    trellis.clrLED(i);
}
void refreshPattern() {
  for (int i=0;i<NUM_STEPS;i++) setLED(i, stepOn[i]);
}

// ---------- callbacks MIDI realtime (ISR SAFE) ----------
void onMidiClock() {
  if (!running) return;
  if (++clockTicks >= 6) {   // 6 ticks = 1/16
    clockTicks = 0;
    stepPending = true;      // <-- on demande l'avance, MAIS on ne touche pas au Trellis ici
  }
}
void onMidiStart()   { running = true;  currentStep = 0; clockTicks = 0; }
void onMidiStop()    { running = false; }
void onMidiContinue(){ running = true; }

// ---------- avance d'un pas (appelée depuis loop(), PAS dans l'ISR) ----------
void advanceStepAndUpdateLeds() {
  // retire le flash du pas précédent si besoin
  if (currentStep >= 0 && !stepOn[currentStep]) trellis.clrLED(currentStep);

  currentStep = (currentStep + 1) % NUM_STEPS;

  // playhead visuel : si le pas n'est pas actif, on l'allume pour montrer la position
  if (!stepOn[currentStep]) trellis.setLED(currentStep);

  trellis.writeDisplay(); // OK ici (hors ISR)

  // jouer la note si le pas est actif
  if (stepOn[currentStep]) {
    usbMIDI.sendNoteOn(NOTE_BASE, VEL, MIDI_CH);
    // gate court : on relâchera au tick suivant (ou au prochain scan)
    usbMIDI.sendNoteOff(NOTE_BASE, 0, MIDI_CH);
  }
}

void setup() {
  Wire.begin();
  Wire.setClock(400000); // I2C rapide, plus réactif

  trellis.begin(TRELLIS_ADDR);
  for (int i=0;i<NUM_STEPS;i++) stepOn[i] = false;
  refreshPattern();
  trellis.writeDisplay();

  usbMIDI.setHandleClock(onMidiClock);
  usbMIDI.setHandleStart(onMidiStart);
  usbMIDI.setHandleStop(onMidiStop);
  usbMIDI.setHandleContinue(onMidiContinue);
}

void loop() {
  // traiter les messages MIDI (déclenche les callbacks ci-dessus)
  while (usbMIDI.read()) {}

  // scanner le Trellis toutes les ~20 ms
  uint32_t now = millis();
  if (now - lastScanMs >= SCAN_PERIOD_MS) {
    lastScanMs = now;

    if (trellis.readSwitches()) {
      bool changed = false;
      for (uint8_t i=0;i<NUM_STEPS;i++) {
        if (trellis.justPressed(i)) {
          stepOn[i] = !stepOn[i];
          setLED(i, stepOn[i]);
          changed = true;
        }
      }
      if (changed) trellis.writeDisplay();
    }
  }

  // si un pas est demandé par la clock, on l'avance ICI (hors ISR)
  if (stepPending) {
    stepPending = false;
    advanceStepAndUpdateLeds();
  }
}

Affectation MIDI sur Ableton

Une fois que votre contrôleur envoi les bons messages MIDI il est nécessaire d’affecter les capteurs aux effets choisis.

Brancher en USB le contrôleur au PC.

Dans le menu « Options », aller dans « Préférences » puis dans « Link Tempo MIDI » et vérifier que votre contrôleur est bien repéré dans l’interface « MIDI ports ».

Sélectionner toutes les cases (Piste, Sync, Téléc., MPE) en entrée (« IN ») pour autoriser toutes les interactions entre le logiciel et le contrôleur.

Fermer la fenêtre.

Cliquer en haut à droite de la fenêtre principale sur le bouton « MIDI ».

Pour affecter un capteur à un effet il suffit alors de sélectionner un bouton d’effet puis de changer la valeur du capteur (en le bougeant par exemple) pour les lier entre eux.

Faire cette manipulation pour tous les effets que voulez affecter à votre contrôleur.

Pour sortir du mode affectation MIDI il suffit de cliquer à nouveau sur le bouton « MIDI ».

Vérifier alors que vos capteurs contrôle bien les effets désirés.