Programando músicas para Arduino a partir de partituras

Introdução

Desde que fiz o último post sobre músicas para Arduino, algumas pessoas perguntaram como é possível “converter” partituras para tocar na placa. Essa tarefa pode ser um pouco difícil se você não tem nenhuma experiência com música, mas não se preocupe, que eu explico o básico.

Primeiro começamos com uma analogia. Um código para Arduino geralmente diz o que a placa deve fazer em que momento e por quanto tempo. Como exemplo vejamos o famoso código Blink:

// a função setup é executada apenas uma vez ao ligar a placa
// Um led deve ser conectado ao pine 
const int PINO_LED=13;
void setup() {
  // inicializa o pino 13 como saída.
  pinMode(PINO_LED, OUTPUT);
}

// a função loop é executada repetidamente enquanto a placa estiver ligada 
void loop() {
  digitalWrite(PINO_LED, HIGH);   // liga o LED (HIGH é o nível lógico)
  delay(1000);                       // espera por um segundo
  digitalWrite(PINO_LED, LOW);    // desliga o LED (LOW é o nível lógico)
  delay(1000);                       // espera por um segundo
}

Esse código diz que a placa deve repetidamente ligar o LED no pino 13 por um segundo, depois desligar o mesmo por um segundo; A ideia que quero passar é que com o código, dizemos os passos que a placa deve executar por determinado tempo. Da mesma forma, uma partitura diz ao músico como este deve tocar seu instrumento, assim como a duração de cada ação.  

Partituras

Em uma partitura, as notas musicais são representadas por símbolos distribuídos em linhas e espaços. Como exemplo vamos usar korobeiniki, uma das músicas no jogo tetris.

Fonte: Flute Tunes

Primeiramente repare que há um conjunto de cinco linhas horizontais, que é chamado pauta ou pentagrama. Este é dividido em medidas temporais iguais, chamadas compassos. As notas são representadas no tempo, indo da esquerda para a direita e representadas dentro dos compassos. A partitura de certa forma funciona como uma algoritmo, dizendo ao músico quando e por quanto tempo tocar determinadas notas.

Nota: Esse post é focado em músicas monofônicas, onde apenas uma nota é tocada por vez. Repare que na partitura acima nunca há duas notas na vertical, porém em muitos instrumentos isso é possível. A função tone() do Arduino pode tocar apenas uma nota de cada vez, sendo necessárias bibliotecas, hardware extra ou outros artifícios para tocar mais de uma nota simultaneamente.  As partituras mais fáceis de se adaptar são as de flauta ou outros instrumentos de sopro, por serem capazes naturalmente de tocar apenas uma nota por vez também. 

Notas musicais

Afinal, qual o significado físico de uma nota musical? Nós sabemos que o som é apenas a vibração do ar em determinadas frequências. Para cada nota musical equivale um valor bem específico de frequência, que é componente mais presente ou mais “forte” naquele som. A figura abaixo mostra as frequências para cada nota, então para tocar uma nota com o Arduino, basta usar a função tone() em um pino onde esteja conectado um buzzer piezo, usando a respectiva frequência em Hertz na tabela abaixo.

Fonte: Joe Wolfe

Exemplo, para tocar o dó central (C4) por 500 milissegundos:

tone(11, 262);
delay(500);
noTone(11);

A função tone() recebe um valor inteiro de frequência, por isso 261,63 foi arredondado para 262.

Continuando, as notas musicais são geralmente denominadas Dó, Ré, Mi, Fá, Sol, Lá e Si. Estas também são representadas pelas letras C, D, E, F, G, A e B respectivamente. Quanto mais acima a nota está no pentagrama, mais aguda ela é. Quanto mais abaixo, mais grave.  A cada linha e espaço nos compassos corresponde uma nota, como mostrado na figura a seguir.

Fonte : Wikipédia

Veja que para cada pentagrama, as notas musicais mudam de posição. As pautas acimas são representadas pelas claves de Sol (𝄞, repare que esta lembra um G), de Dó (𝄡) e Fá (𝄢, repare que está também lembra um F) . As partituras que procuro para converter músicas para o Arduino possuem geralmente apenas um pentagrama, já que o Arduino só pode tocar uma nota (sem truques). Partituras comuns podem conter dois (piano) ou vários (músicas para conjuntos de músicos);

Embora pareça muito difícil de decorar as notas de cada compasso, há mnemônicos que ajudam. Por exemplo, os espaços no compasso de Sol (G), o primeiro na imagem, formam a palavra FACE. Não há uma forma rápida de se decorar isso, é preciso treino e dedicação, mas se sua intenção é apenas converter a partitura no algorítimo, você pode levar o tempo que quiser e também pode olhar a localização das notas online.

Fonte : Ultra Musician

Acidentes

Em um teclado ou piano, essas notas da figura acima representam apenas as notas brancas. Então para representar as outras notas (sustenido e bemol) são utilizados acidentes ( e ). Esses dizem que uma nota deve ser abaixada ou elevada um semitom, ou seja, uma nota C (Dó) acompanhada de um se torna C, que é um pouco mais aguda que o dó. Já uma nota D (Ré) se é mais grave que o Ré por um semitom. Isso também quer dizer que esta é equivalente ao C. Essas mudanças são válidas para toda o compasso atual, a menos que um bequadro ♮ retorne a nota ao seu tom original. 

Esses acidentes podem estar representados no começo do compasso (representado a escala), afetando todas as notas que correspondem aquele espaço ou linha do compasso por toda a partitura. Para mais detalhes visite a página da Wikipédia sobre acidentes.

Duração das notas

Ok, até agora só vimos como descobrir quais as notas, mas não a duração das mesmas. Isso é representado pela formato de cada, como representado na figura a seguir:

Fonte: GCF GLobal

Sim, isso mesmo. As durações são representadas por frações. Essas notas possuem nomes também (como semibreve, mínima etc). A ideia por trás disso é que cada nota na figura tem metade da duração da anterior. No entanto, as notas não tem duração fixa (em segundos, por exemplo) e isso é dado pelo pela marcação de metrônomo para cada música.  Repare novamente na partitura de tetris, há na figura um detalhe:

Esse valor é dado em batidas por minuto (BPM). Então em um minuto há 144 notas semínimas (1/4). Dessa forma, para essa partitura uma nota semínima tem duração de 60segundos/144 = 0,41666 segundos ou 416 milissegundos. De forma similar é possível encontrar a duração de todas as outras notas. O que eu faço no Arduíno é calcular a duração na nota semibreve (1) e dividi-la para encontrar as outras.

Ah, muitas vezes as notas vêm acompanhadas de pequenos pontos, esses indicam que as notas devem ser estendidas por mais metade do tempo, ou seja, sua duração é de 150%. Sendo chamadas de notas pontuadas. No exemplo da música de tetris acima é possível ver algumas dessas notas.

Por enquanto é isso sobre a teoria. Esse tutorial foi pensado para ser o mais breve possível e não um curso de música, hehe. Para mais informações sobre o assunto visite a página sobre notação musical moderna na Wikipédia.

Exemplo

Como exemplo vamos utilizar a partitura de tetris acima. Primeiro começamos por listar as frequências de todas as notas. Isso é feito para tornar o código mais legível, em vez de passar a frequência diretamente para a função tone(). Nem todas são utilizadas, mas essa parte geralmente é copiada e colada para poupar tempo.

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
#define REST 0

Repare que apenas os acidentes sustenidos() estão representados. Claro, um bemol ( ) equivale a um sustenido ou natural( exemplo G = F♯), não sendo necessário repetir os valores. 

Agora calculamos a duração de uma nota semibreve (1).

// "velocidade" da música, em BPM
int tempo=144; 
// isso calcula a duração da nota em ms (60s/tempo)*4semibreves
int semibreve = (60000 * 4) / tempo; //duração de uma nota semibreve (1) em milissegundos

Assim, para achar a duração de uma nota semi mínima (1/4) basta dividir esse valor por 4 e assim por diante.

Agora, vamos identificar as notas da música. Começamos pelo primeiro compasso:

Como pode-se ver, há 6 notas no compasso. 2 são semínimas (1/4) e as outras 4 são colcheias (1/8). Você pode pegar o nome das notas pela posição na terceira imagem acima.

Assim:

  • a primeira nota é E5, com duração de 1/4;
  • a segunda nota é B4, com duração de 1/8;
  • a terceira nota é C5, com duração de 1/8;
  • a quarta nota é D5, com duração de 1/4;
  • a quinta nota é C5, com duração de 1/8;
  • a sexta nota é B4, com duração de 1/8;

Essas notas poderiam ser organizadas da seguinte forma:

tone(11, NOTE_E5, semibreve/4);
delay(semibreve/4);
tone(11, NOTE_B4, semibreve/8);
delay(semibreve/8);
tone(11, NOTE_C5, semibreve/8);
delay(semibreve/8);
tone(11, NOTE_D5, semibreve/4);
delay(semibreve/4);
tone(11, NOTE_C5, semibreve/8);
delay(semibreve/8);
tone(11, NOTE_B4, semibreve/8);
delay(semibreve/8);

Claro que isso ficaria muito longo para a música completa, além de ser mais difícil de ler se for preciso corrigir alguma coisa.

Então a solução que utilizo é colocar as notas em um vetor, acompanhadas das durações. Cada linha representa um compasso:

int melodia[] = {
  NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8,
  ...
}

Agora, continuando com o compasso seguinte:

int melodia[] = {
  NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  ...
}

E depois com o terceiro compasso:

Nesse compasso há um caso especial. Uma das notas está acompanhada de um pequeno ponto. Isso indica que essa nota é tocada por mais 50% de sua duração. Então, como essa nota é uma semi mínima (1/4), passa a ter duração (1/4 + 1/8 = 3/8). Não se preocupe com a matemática, o Arduino calula isso pra gente :)

Para representar notas pontuadas, uso um sinal negativo. No código principal, o Arduino toca identifica que os valores negativos são notas pontuadas, tocando-as pelo tempo correto.

int melodia[] = {
  NOTE_E5, 4, NOTE_B4,8, NOTE_C5,8, NOTE_D5,4, NOTE_C5,8, NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  ...
}

Agora você já deve entender o básico para transcrever as notas da partitura para o Arduino. O  resultado final é o seguinte:

int melodia[] = {
  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,

  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,

  NOTE_E5,2,  NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,2,   NOTE_A4,2,
  NOTE_GS4,2,  NOTE_B4,4,  REST,8, 
  NOTE_E5,2,   NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,4,   NOTE_E5,4,  NOTE_A5,2,
  NOTE_GS5,2,
};

Mas não acabamos ainda, é preciso uma função que interprete e reproduza o vetor acima. Isso é feito abaixo no setup(), mas o código pode ser copiado para o loop() para se repetir-se. O sketch simplesmente lê cada valor de nota e duração do vetor, usa a função tone() para gerar a onda na frequência adequada e espera pelo tempo de se ler a próxima nota.

int divisor = 0, duracao = 0;

void setup() {
  // itera as notas da melodia. 
  // lembre-se, o vetor é o dobro de notas (notas + durações)
  for (int nota = 0; nota < totalNotas * 2; nota = nota + 2) {

    // calcula a duração de cada nota
    divisor = melodia[nota + 1];
    if (divisor > 0) {
      // nota comum, apenas continua
      duracao = (semibreve) / divisor;
    } else if (divisor < 0) {
      // notas ponteadas são representadas com números negativos!!
      duracao = (semibreve) / abs(divisor);
      duracao *= 1.5; // aumenta a duração pela metade para notas pontuadas
   }

    // apenas tocamos a nota por 90% da duração, deixando 10% como uma pausa
    // Isso é feito para "separar" duas notas iguais tocadas em seguida
    tone(buzzer, melodia[nota], duracao*0.9);

    // Espera pela duração especificada até a próxima nota.
    delay(duracao);
    
    // para a geração de tom antes de mover pra próxima nota.
    noTone(buzzer);
  }
}

void loop() {
  // não é preciso repetir a música, mas essa pode ser copiada aqui se desejado.
}

Código completo

Assim, o código completo fica:

/* 
  Tetris - (Korobeiniki) 
  Connect a piezo buzzer or speaker to pin 11 or select a new pin.
  More songs available at https://github.com/robsoncouto/arduino-songs                                            
                                              
                                              Robson Couto, 2019
*/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
#define REST 0

// pino onde o buzzer está conectado
int buzzer =11;

// "velocidade" da música, em BPM
int tempo=144; 

// notas da melodia seguidas da duração.
// um 4 significa uma semínima, um 8 uma colcheia , 16 semicolcheia, etc
// !!números negativos são usados para representar notas pontuadas,
// então -4 significa uma semínima pontuada, isto é, uma semínima mais uma colcheia!!
int melodia[] = {

  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,

  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,
  
  NOTE_E5,2,  NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,2,   NOTE_A4,2,
  NOTE_GS4,2,  NOTE_B4,4,  REST,8, 
  NOTE_E5,2,   NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,4,   NOTE_E5,4,  NOTE_A5,2,
  NOTE_GS5,2,

};

// retorna o numero de notas no vetor
int totalNotas=sizeof(melodia)/sizeof(melodia[0])/2; 

// isso calcula a duração da nota em ms (60s/tempo)*4semibreves
int semibreve = (60000 * 4) / tempo; //duração de uma nota semibreve (1) em milissegundos

int divisor = 0, duracao = 0;

void setup() {
  // itera as notas da melodia. 
  // lembre-se, o vetor é o dobro de notas (notas + durações)
  for (int nota = 0; nota < totalNotas * 2; nota = nota + 2) {

    // calcula a duração de cada nota
    divisor = melodia[nota + 1];
    if (divisor > 0) {
      // nota comum, apenas continua
      duracao = (semibreve) / divisor;
    } else if (divisor < 0) {
      // notas ponteadas são representadas com números negativos!!
      duracao = (semibreve) / abs(divisor);
      duracao *= 1.5; // aumenta a duração pela metade para notas pontuadas
   }

    // apenas tocamos a nota por 90% da duração, deixando 10% como uma pausa
    // Isso é feito para "separar" duas notas iguais tocadas em seguida
    tone(buzzer, melodia[nota], duracao*0.9);

    // Espera pela duração especificada até a próxima nota.
    delay(duracao);
    
    // para a geração de tom antes de mover pra próxima nota.
    noTone(buzzer);
  }
}

void loop() {
  // não é preciso repetir a música, mas essa pode ser copiada aqui se desejado.
}

Veja o resultado do código no vídeo abaixo:

Acha o código difícil? Para adaptar suas músicas você só precisa substituir as notas e durações do vetor e mudar a variável tempo para o valor adequado.

Mais músicas para Arduino podem ser encontardas no meu github. Lá eu também deixo os links das partituras utilizadas em cada código.

Por enquanto é isso. Obrigado pela leitura  e até um próximo post o/

Robson Couto

Recentemente graduado Engenheiro Eletricista. Gosto de dedicar meu tempo a aprender sobre computadores, eletrônica, programação e engenharia reversa. Documento meus projetos no Dragão quando possível.

5 thoughts to “Programando músicas para Arduino a partir de partituras”

  1. Comecei agora com Arduino e tava brincando com essa parte de músicas pelo buzzer e estou tentando já tem 2 dias mas não consigo imaginar como fazer um led piscar junto das notas.
    Você tem uma dica, fera?
    VLW! Ótimo trabalho!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *