Pular para conteúdo

🎛️ Introdução

ESP32_Host_MIDI é uma biblioteca Arduino de código aberto que transforma o ESP32 em um hub MIDI universal com suporte a 9 transportes simultâneos, todos operando pela mesma API limpa de eventos.


O Que É a Biblioteca

A ideia central é simples: não importa de onde o MIDI vem — USB, Bluetooth, WiFi, cabo serial, rádio — ele chega sempre na mesma fila de eventos (getQueue()), com o mesmo formato (MIDIEventData), pronto para processar.

for (const auto& ev : midiHandler.getQueue()) {
    ev.status;      // "NoteOn", "NoteOff", "ControlChange", "PitchBend"...
    ev.channel;     // 1–16
    ev.note;        // número MIDI (0–127)
    ev.noteOctave;  // "C4", "D#5", "G3"...
    ev.velocity;    // 0–127
    ev.timestamp;   // millis() na chegada
    ev.chordIndex;  // agrupa notas simultâneas
}

Ao mesmo tempo, midiHandler.sendNoteOn() e outros métodos de envio transmitem para todos os transportes ativos simultaneamente. Um evento que chega pelo USB pode sair imediatamente pelo BLE, pelo DIN-5 e pelo WiFi — sem nenhum código extra.


Os 9 Transportes

mindmap
  root((ESP32\nHost MIDI))
    USB Host
      ESP32-S3 / S2 / P4
      Teclados class-compliant
      Latência < 1 ms
    BLE MIDI
      Qualquer ESP32 com BT
      iOS · macOS · Android
      Latência 3-15 ms
    USB Device
      ESP32-S3 / S2 / P4
      Aparece como interface USB
      Latência < 1 ms
    ESP-NOW
      Qualquer ESP32
      Mesh P2P sem router
      Latência 1-5 ms
    RTP-MIDI WiFi
      AppleMIDI / RFC 6295
      macOS · iOS · Logic Pro
      Latência 5-20 ms
    Ethernet MIDI
      W5500 SPI ou P4 nativo
      Ideal para estúdios
      Latência 2-10 ms
    OSC
      WiFi UDP bidirecional
      Max/MSP · PD · SC
      Latência 5-15 ms
    UART / DIN-5
      Qualquer ESP32
      Sintetizadores vintage
      Latência < 1 ms
    MIDI 2.0 UDP
      UMP over UDP
      16-bit velocity
      Latência 5-20 ms

Arquitetura de Software

Separação por Cores do FreeRTOS

O ESP32 tem dois núcleos. A biblioteca usa essa separação para garantir baixa latência:

graph TD
    subgraph CORE0["🔵 Core 0 — Drivers e Stack"]
        USB_TASK["USB Host Task\n(USBConnection)"]
        BLE_STACK["Pilha BLE\n(BLEConnection)"]
        WIFI["Pilha WiFi / Ethernet\n(RTP-MIDI, OSC, ESP-NOW)"]
    end

    subgraph CORE1["🟢 Core 1 — Seu Código"]
        LOOP["loop()"]
        TASK["midiHandler.task()"]
        USER["Seu código\n(display, synth, etc.)"]
    end

    subgraph BUFFERS["🔄 Ring Buffers (thread-safe)"]
        RB1["portMUX spinlock\nbuffer USB"]
        RB2["portMUX spinlock\nbuffer BLE"]
        RB3["portMUX spinlock\nbuffers WiFi"]
    end

    USB_TASK --> RB1
    BLE_STACK --> RB2
    WIFI --> RB3
    RB1 --> TASK
    RB2 --> TASK
    RB3 --> TASK
    TASK --> LOOP
    LOOP --> USER

    style CORE0 fill:#1A237E,color:#fff,stroke:#283593
    style CORE1 fill:#1B5E20,color:#fff,stroke:#2E7D32
    style BUFFERS fill:#37474F,color:#fff,stroke:#546E7A

Fluxo de um Evento NoteOn

sequenceDiagram
    participant USB as 🔌 Teclado USB
    participant DRIVER as USB Host Driver
    participant BUF as Ring Buffer
    participant HANDLER as MIDIHandler
    participant USER as Seu Código

    USB->>DRIVER: Pacote USB-MIDI (4 bytes)
    DRIVER->>BUF: Armazena com portMUX (Core 0)
    loop Cada loop()
        USER->>HANDLER: midiHandler.task()
        HANDLER->>BUF: Lê mensagens pendentes
        BUF->>HANDLER: [0x09, 0x90, 0x3C, 0x64]
        HANDLER->>HANDLER: Parseia → MIDIEventData
        Note over HANDLER: status="NoteOn"<br/>note=60 (C4)<br/>velocity=100
        HANDLER->>USER: getQueue() retorna evento
    end

Camadas da Biblioteca

Camada Arquivo Responsabilidade
Feature detection ESP32_Host_MIDI.h Detecta USB, BLE, PSRAM por chip
Transporte abstrato MIDITransport.h Interface comum para todos transportes
Processador central MIDIHandler.h/.cpp Fila, accordes, notas ativas, envio
Configuração MIDIHandlerConfig.h Struct de configuração do handler
Transportes built-in USBConnection, BLEConnection, ESPNowConnection Registrados automaticamente
Transportes externos UART, RTP-MIDI, Ethernet, OSC, MIDI2, USBDevice Incluídos manualmente no sketch
Integração teoria GingoAdapter.h Bridge com Gingoduino
MIDI 2.0 MIDI2Support.h Parser, builder e scaler UMP

Casos de Uso Típicos

Hub MIDI de Palco

Teclado USB ──────────────────────────────────────────┐
iPhone BLE ───────────────────────────────────────────┤
ESP-NOW (pedais) ─────────────────────────────────────┤──► MIDIHandler ──► USB Device → Computador FOH
                                                       │              ──► DIN-5 → Rack de efeitos
                                                       │              ──► ESP-NOW → Outros performers

Interface de Estúdio

macOS (RTP-MIDI via WiFi) ────────────────────────────┐
Sintetizador DIN-5 ───────────────────────────────────┤──► MIDIHandler ──► USB Device → DAW
iPad (BLE MIDI) ──────────────────────────────────────┘              ──► DIN-5 (THRU) → Outros synths

Experimento MIDI 2.0

ESP32-A (teclado USB) ──────────► MIDIHandler ──► MIDI2UDPConnection ──► UDP →
── UDP → MIDI2UDPConnection ──► MIDIHandler ──► ESP32-B (display, síntese)
                                               (16-bit velocity, 32-bit CC)

Próximos Passos