Pular para conteúdo

🎵 Notas Ativas

O MIDIHandler mantém um mapa interno de quais notas estão atualmente pressionadas (NoteOn recebido mas NoteOff ainda não). Diversas APIs permitem consultar esse estado.


API de Notas Ativas

getActiveNotes() — String formatada

Retorna uma string com todas as notas ativas:

std::string ativas = midiHandler.getActiveNotes();
Serial.println(ativas.c_str());
// Exemplo: "{C4, E4, G4}"

getActiveNotesVector() — Lista de strings

Retorna um vetor com cada nota como string:

auto notas = midiHandler.getActiveNotesVector();
// Exemplo: ["C4", "E4", "G4"]

for (const auto& n : notas) {
    Serial.println(n.c_str());
}

getActiveNotesCount() — Quantidade

Número de notas atualmente pressionadas:

size_t count = midiHandler.getActiveNotesCount();
Serial.printf("%d notas ativas\n", (int)count);

fillActiveNotes() — Array booleano

Preenche um array de 128 posições (uma por nota MIDI):

bool ativas[128] = {false};
midiHandler.fillActiveNotes(ativas);

// Verificar nota específica:
if (ativas[60]) Serial.println("C4 está pressionada!");

// Listar todas as ativas:
for (int i = 0; i < 128; i++) {
    if (ativas[i]) {
        Serial.printf("Nota %d ativa\n", i);
    }
}

Exemplo Completo

#include <ESP32_Host_MIDI.h>
// Tools > USB Mode → "USB Host"

void setup() {
    Serial.begin(115200);
    midiHandler.begin();
}

void loop() {
    midiHandler.task();

    // Mostrar notas ativas quando algo mudar
    static size_t lastCount = 0;
    size_t count = midiHandler.getActiveNotesCount();

    if (count != lastCount) {
        lastCount = count;

        if (count == 0) {
            Serial.println("[ sem notas ]");
        } else {
            Serial.printf("[%d notas] %s\n",
                (int)count,
                midiHandler.getActiveNotes().c_str());
        }
    }
}

Saída ao tocar um acorde de Dó maior e soltar:

[1 notas] {C4}
[2 notas] {C4, E4}
[3 notas] {C4, E4, G4}
[2 notas] {C4, E4}
[1 notas] {C4}
[ sem notas ]

Usar para Síntese de Áudio

O fillActiveNotes() é ideal para síntese em tempo real — copie o array uma vez por frame:

bool notas[128];
midiHandler.fillActiveNotes(notas);

// Sintetizar todas as notas ativas
for (int i = 0; i < 128; i++) {
    if (notas[i]) {
        float freq = 440.0f * powf(2.0f, (i - 69) / 12.0f);
        // addOscillator(freq);
    }
}

Piano Roll com notas ativas

#include <ESP32_Host_MIDI.h>

// Mostrar quais teclas estão pressionadas (ASCII art)
void printPianoRoll() {
    bool notas[128];
    midiHandler.fillActiveNotes(notas);

    // Teclas C4 a B4 (60–71)
    for (int i = 60; i <= 71; i++) {
        Serial.print(notas[i] ? "█" : "░");
    }
    Serial.println();
}

void loop() {
    midiHandler.task();
    printPianoRoll();
    delay(50);
}

Limpar Notas Ativas

Em alguns casos (desconexão, reset) você precisa limpar o estado:

// Zera o mapa interno de notas ativas
midiHandler.clearActiveNotesNow();

getActiveNotesString() — Alternativa

Alias de getActiveNotes() com nome alternativo:

std::string s = midiHandler.getActiveNotesString();
// Idêntico a getActiveNotes()

Monitorar Pressão de Teclas Específicas

Combine fillActiveNotes() com uma lista de notas de interesse:

const int ACORDE_CM[] = {60, 64, 67};  // C, E, G

bool notas[128];
midiHandler.fillActiveNotes(notas);

bool acordeCompleto = notas[60] && notas[64] && notas[67];
if (acordeCompleto) {
    Serial.println("Dó maior pressionado!");
}

Próximos Passos