#include <string.h>
const byte piezo = 2; // Saída onde o Piezo está conectado.
const int bpm = 120; // Intuitivo.
const byte tamBarra = 4; // Batidas por barra.
const bool compound = 0; // Indica se o tempo usado compound ou não.
const byte maximo[2] = {4, 5}; // Para o strlcpy.
const float silentProp = 0.85; // Quanto tempo da nota é comido para simular o tempo de transição entre uma nota e outra, tipo a troca de notas em um violino.
//int bug = 0;
int notaLigada[8] = {100, 100, 100, 100, 100, 100, 100, 100}; // Buffer para a definição da posição da nota que é ligada com outra.
void setup() {
pinMode(piezo, OUTPUT);
// Serial.begin(9600);
}
void loop() {
float *temposOut = (float*)calloc(8, sizeof(float)); //Reserva um array de 8 posições para receber os tempos de cada nota da barra após decoder.
float *PartituraDinamica = (float*)calloc(8, sizeof(float)); //Reserva um array de 8 posições para receber frequências do decoder.
//Primeira barra:
char notasNaBarra[][4] = {"D4", "D4", "C4#", "D4", "E4", "F4", "E4", "F4"}; //Notas da primeira barra
decodeNotas(notasNaBarra, 8, PartituraDinamica); //Decoder.
char tempos[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"}; //Tempos na primera barra, agora melhorados!
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Segunda barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"G4", "A4", "C5", "B4", "B4b", "A4", "G4", "F4#"};
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Terceira Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"A4", "G4", "F4#", "G4", "C5", "A4", "F4"};
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "SM", "SM", "SM"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
for(int rep=0; rep<2; rep++){
//Início da Parte cantada.
//Quarta Barra:
for(int i=0; i<5; i++){
char newArray[][4] = {"P", "A4", "C5", "A4", "G4"}; //Sulução bandaid para a repetição, nota da música
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 5, PartituraDinamica);
for(int j=0; j<5; j++){
char newArray[][5] = {"SM", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 5, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 5);
//
//Quinta Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"F4", "A4", "F4", "E4", "D4", "F4", "F4", "P"};
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CCl", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Sexta Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"F4", "E4", "D4", "F4", "F4", "F4", "F4", "E4"};
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Sétima Barra:
for(int i=0; i<6; i++){
char newArray[][4] = {"D4", "B4b", "P", "B4b", "D5", "B4b"};
strlcpy(notasNaBarra[i],newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 6, PartituraDinamica);
for(int j=0; j<6; j++){
char newArray[][5] = {"CC", "SM", "SM", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 6, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 6);
//
//Oitava Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"A4", "G4", "B4b", "G4", "F4", "E4", "G4", "P"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Nona Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"F4", "E4", "D4", "C4", "D4", "E4", "F4", "G4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Decima Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"C5", "C5", "C5", "P", "A4", "C5", "A4"}; //Tie adapdata com uma nota de maior duração, segundo C5.
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"SM", "CCl", "CC", "SM", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Decima Primeira Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"G4", "F4", "A4", "F4", "E4", "D4", "F4", "P"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Decima Segunda Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"F4", "E4", "D4#", "D4", "D4", "P", "C5", "B4b"}; //Tie de dois D4 adaptado para apenas um D4.
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CCl", "CC", "CC", "CC", "CC"}; //Tie de dois D4 de 1/2 tempo colocado aqui como um D4 de 1 tempo.
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Decima Terceira Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"A4", "D5", "P", "D4", "D4", "C4#", "D4", "E4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Decima Quarta Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"F4", "E4", "F4", "G4", "A4", "C5", "B4", "B4b"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Decima Quinta Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"A4", "G4", "F4#", "A4", "G4", "G4", "C5"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "SM", "CC", "CCl"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Decima sexta barra:
for(int i=0; i<5; i++){
char newArray[][4] = {"C5", "A4", "F4", "P", "P"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 5, PartituraDinamica);
for(int j=0; j<5; j++){
char newArray[][5] = {"CC", "SM", "SM", "CC", "SM"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 5, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 5);
//
for(int rep2=0; rep2<2; rep2++){
// Decima sétima Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"A4", "B4b", "C5", "D4", "D4", "P", "G4"}; //Tie de duas notas D4 feita aumentando a duração da primeira D4.
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "CC", "CC", "CCl", "SM", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Decima oitava Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"A4", "B4b", "C4", "C4", "P", "A4", "G4"}; //Tie de duas notas C4 feita aumentando a duração da primeira D4.
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "CC", "CCl", "SM", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Decima nona Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"F4", "F4", "E4", "D4#", "E4", "D5", "C5#"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "SM", "CCl"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Vigésima Barra:
for(int i=0; i<7; i++){
char newArray[][4] = {"C5#", "C5", "P", "A4", "B4b", "C5", "D4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 7, PartituraDinamica);
for(int j=0; j<7; j++){
char newArray[][5] = {"CC", "SM", "CC", "CC", "CC", "CC", "CCl"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 7, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 7);
//
//Vigésima Primeira Barra:
for(int i=0; i<6; i++){
char newArray[][4] = {"D4", "P", "G4", "A4", "B4b", "C4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 6, PartituraDinamica);
for(int j=0; j<6; j++){
char newArray[][5] = {"SM", "CC", "CC", "CC", "CC", "SM"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 6, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 6);
//
//Vigésima Segunda Barra:
for(int i=0; i<8; i++){
char newArray[][4] = {"P", "A4", "G4", "F4", "F4", "E4", "D4#", "E4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 8, PartituraDinamica);
for(int j=0; j<8; j++){
char newArray[][5] = {"CC", "CC", "CC", "CC", "CC", "CC", "CC", "CC"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 8, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 8);
//
//Vigésima Terceira Barra:
for(int i=0; i<3; i++){
char newArray[][4] = {"D5", "C5", "F4"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 3, PartituraDinamica);
for(int j=0; j<3; j++){
char newArray[][5] = {"SM", "SM", "MN"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 3, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 3);
//Fim da Partitura!
}
// A partir daqui a partitura se repete, então os dois laços for pegam o pesado! Bora economizar tempo, man!
for(int i=0; i<1; i++){
char newArray[][4] = {"P"};
strlcpy(notasNaBarra[i], newArray[i], maximo[0]);
}
decodeNotas(notasNaBarra, 1, PartituraDinamica);
for(int j=0; j<1; j++){
char newArray[][5] = {"SM"};
strlcpy(tempos[j],newArray[j], maximo[1]);
}
decodeTempos(tempos, 1, bpm, tamBarra, compound, temposOut);
Leitor(temposOut, PartituraDinamica, silentProp, 1);
//
}
PartituraDinamica=NULL;
temposOut=NULL;
free(PartituraDinamica);
free(temposOut);
delay(50000000);
}
void decodeTempos(char tempos[][5], int tamanho, float bpm, int barra, float complex, float Output[]){
float duracaoBar = 0;
float newTempos[tamanho];
int tempVar[tamanho];
//Primeiro é necessário estabelecer a duração de cada nota conforme inputs de Time Signature e BPM da música, conforme falado pelo professor (compound e simple).
if(complex == 0){ //Tempo simples
duracaoBar = ((60*1*barra)/bpm);
}
else{ //Assinatura de tempo composta, isto é, feita de estacatos.
duracaoBar = ((((1*barra)/3)*60)/bpm);
}
for(int i=0; i<tamanho; i++){ //Aqui determina-se a parcela de tempo da nota através dos valores ASCII dados.
tempVar[i] = (tempos[i][0] + tempos[i][1]);
//Serial.println(tempVar[i]);
switch(tempVar[i]){
case(149): //Semibreve = SB = 'S'+'B' = 149
newTempos[i] = duracaoBar*1;
break;
case(155): //Mínima = MN = 'M' + 'N' = 155
newTempos[i] = duracaoBar*0.5;
if(tempos[i][2]=='.'||tempos[i][3]=='.'){ //Checagem feita em todas as notas para checar se são estacatas ou não!
newTempos[i] = newTempos[i]+(newTempos[i]*0.5);
}
break;
case(160): //SemiMínima = SM = 'S' + 'M' = 160
newTempos[i] = duracaoBar*0.25;
if(tempos[i][2]=='.'||tempos[i][3]=='.'){ //Checagem feita em todas as notas para checar se são estacatas ou não!
newTempos[i] = newTempos[i]+(newTempos[i]*0.5);
}
break;
case(134): //Colcheia = CC = 'C' + 'C' = 134
newTempos[i] = duracaoBar*0.125;
if(tempos[i][2]=='.'||tempos[i][3]=='.'){ //Checagem feita em todas as notas para checar se são estacatas ou não!
newTempos[i] = newTempos[i]+(newTempos[i]*0.5);
}
break;
case(150): //SemiColcheia = SC = 'S' + 'C' = 150
newTempos[i] = duracaoBar*0.0625;
if(tempos[i][2]=='.'||tempos[i][3]=='.'){ //Checagem feita em todas as notas para checar se são estacatas ou não!
newTempos[i] = newTempos[i]+(newTempos[i]*0.5);
}
break;
case(153): //Fusa = FS = 'F' + 'S' = 153
newTempos[i] = duracaoBar*0.03125;
if(tempos[i][2]=='.'||tempos[i][3]=='.'){ //Checagem feita em todas as notas para checar se são estacatas ou não!
newTempos[i] = newTempos[i]+(newTempos[i]*0.5);
}
break;
default:
Serial.println("Tempo invalido inserido.");
break;
}
if(tempos[i][2]=='l'){
notaLigada[i] = i;
//Serial.println(notaLigada[i]);
}
}
for(int j=0; j<tamanho; j++){
Output[j] = newTempos[j];
}
}
void Leitor(float tempos[], float Partitura[], const float deconFactor, int tamanho){
for(int j=0; j<tamanho; j++){
if(j==notaLigada[j]){
// Serial.println("ok");
PlayBuzer(Partitura[j],tempos[j], 1);
notaLigada[j] = 100;
}
else{
PlayBuzer(Partitura[j],tempos[j], deconFactor);
}
}
}
void PlayBuzer(float freq, float tempo, const float deconFactor){ //Tocador de frequências funcionando, por favor, sem mexer mais.
float periodo=(1000000.0/freq);
float tempodFim=micros()+((tempo*1000000)*deconFactor); //Adicionado para retirar parte da nota ao tocar ela, como uma pessoa em um instrumento de sopro ou cordas como o violino.
float tempodSilencio=micros()+(tempo*1000000);
while((micros()<tempodFim)&&freq!=0){
digitalWrite(piezo, HIGH);
//Serial.println("Por que liguei?");
delayMicroseconds(periodo/2);
digitalWrite(piezo, LOW);
//Serial.println("Tá funcionando"); //Antes de executar, sempre manter prints comentados... Puta dor de cabeça pra resolver isso...
delayMicroseconds(periodo/2);
//owTime=micros()+aftTime;
}
while(micros()<tempodSilencio){ //Delay sofiticado, basicamente.
digitalWrite(piezo, LOW);
// Serial.print(bug);
// Serial.println("ok");
// bug++;
}
}
void decodeNotas(char notas[][4], int quantidadeDeNotas, float freqDasNotas[]){
char notaAtual;
int Oitavo;
bool sharp = false;
bool bemol = false;
char nota[4];
for (int i=0; i<quantidadeDeNotas; i++) {
for(int j=0; j<4; j++){
nota[j]=notas[i][j];
}
int tam = strlen(nota);
if(tam != 1){
if (tam == 2) { // Nota sem sustenido, tipo C3
notaAtual = nota[0]; // Pega o primeiro char da string.
Oitavo = nota[1] - '0'; // Converte o número do oitavo para inteiro tirando o final '0', isto é, o 48, do código ASCII
sharp = false; //Me entrega que a nota não é sharp.
bemol = false; //Me entrega que a nota não é bemol.
}
else{ // Se a nota tem um tamanho de 3, o terceiro char ou é um '#', ou um "b". Logo a nota é sustenida.
notaAtual = nota[0]; //Puxa o primeiro char da string.
Oitavo = nota[1] - '0'; //Subtrai '0' em ASCII da nota[2] também em ASCII para descobrir o oitavo da nota.
if(nota[2]=='#'){
sharp = true; //Atualiza a flag como uma nota sharp.
bemol = false;
}
else{
sharp = false;
bemol = true; //Atualiza a flag como uma nota bemol.
}
}
freqDasNotas[i] = FreqDaNota(notaAtual, Oitavo, sharp, bemol);
}
else{
freqDasNotas[i]=0.0;
}
}
}
float FreqDaNota(char notaAtual, int Oitavo, bool Sharp, bool Bemol){
float momNote = 32.7032; //Nota inicial C1, pois é uma das notas mais baixas dos oitavos e a primeira nota do piano.
char notasPossiveis[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B'}; //Estabelece as notas que tenho dentro de um oitavo, para ver a distancia entre a nota adentrada.
int disNaNota=0;
int distancia;
for(int i=0; i<7; i++){
if(notaAtual==notasPossiveis[i]){ //Aqui descobre-se a distancia de cada nota, levando em consideração a existencida dos acidentes.
if(i==1) disNaNota=2;
else if(i==2) disNaNota=4;
else if(i==3) disNaNota=5;
else if(i==4) disNaNota=7;
else if(i==5) disNaNota=9;
else if(i==6) disNaNota=11;
break;
}
}
distancia = disNaNota+((Oitavo-1)*12);
if(Sharp==1){
distancia += 1;
}
if(Bemol==1){
distancia -= 1;
}
float freq = momNote*(pow(2.0, ((distancia)/12.0)));
return freq;
}