Sommario:

Rilevatore di note musicali: 3 passaggi
Rilevatore di note musicali: 3 passaggi

Video: Rilevatore di note musicali: 3 passaggi

Video: Rilevatore di note musicali: 3 passaggi
Video: Leggere la musica è FACILE - 1 (le note sulle righe) 2024, Dicembre
Anonim
Image
Image

Stupisci i tuoi amici e familiari con questo progetto che rileva la nota suonata da uno strumento. Questo progetto mostrerà la frequenza approssimativa e la nota musicale suonata su una tastiera elettronica, un'app per pianoforte o qualsiasi altro strumento.

Particolari

Per questo progetto, l'uscita analogica dal rilevatore del modulo sonoro viene inviata all'ingresso analogico A0 dell'Arduino Uno. Il segnale analogico viene campionato e quantizzato (digitalizzato). Il codice di autocorrelazione, ponderazione e sintonizzazione viene utilizzato per trovare la frequenza fondamentale utilizzando i primi 3 periodi. La frequenza fondamentale approssimativa viene quindi confrontata con le frequenze nelle ottave 3, 4 e 5 per determinare la frequenza della nota musicale più vicina. Infine la nota indovinata per la frequenza più vicina viene stampata sullo schermo.

Nota: questa istruzione si concentra solo su come costruire il progetto. Per ulteriori informazioni sui dettagli e le giustificazioni del design, visitare questo collegamento: Ulteriori informazioni

Forniture

  • (1) Arduino Uno (o Genuino Uno)
  • (1) Modulo di rilevamento del suono ad alta sensibilità del sensore del microfono DEVMO compatibile
  • (1) tagliere senza saldatura
  • (1) Cavo da USB-A a B
  • Ponticelli
  • Sorgente musicale (pianoforte, tastiera o app paino con altoparlanti)
  • (1) Computer o laptop

Passaggio 1: costruire l'hardware per il rilevatore di note musicali

Imposta il rilevatore di note musicali
Imposta il rilevatore di note musicali

Utilizzando un Arduino Uno, cavi di connessione, una breadboard senza saldatura e un modulo di rilevamento del suono ad alta sensibilità del sensore del microfono DEVMO (o simile) costruisci il circuito mostrato in questa immagine

Passaggio 2: programma il rilevatore di note musicali

Nell'IDE di Arduino, aggiungi il seguente codice.

gistfile1.txt

/*
Nome file/schizzo: MusicalNoteDetector
Versione n.: v1.0 Creata il 7 giugno 2020
Autore originale: Clyde A. Lettsome, PhD, PE, MEM
Descrizione: questo codice/schizzo mostra la frequenza approssimativa e la nota musicale suonata su una tastiera elettronica o un'app per pianoforte. Per questo progetto, l'uscita analogica del
il rilevatore del modulo sonoro viene inviato all'ingresso analogico A0 di Arduino Uno. Il segnale analogico viene campionato e quantizzato (digitalizzato). Il codice di autocorrelazione, ponderazione e sintonizzazione viene utilizzato per
trova la frequenza fondamentale usando i primi 3 periodi. La frequenza fondamentale approssimativa viene quindi confrontata con le frequenze nelle ottave 3, 4 e 5 per determinare il musical più vicino
frequenza di nota. Infine la nota indovinata per la frequenza più vicina viene stampata sullo schermo.
Licenza: questo programma è un software gratuito; puoi ridistribuirlo e/o modificarlo secondo i termini della GNU General Public License (GPL) versione 3, o successive
versione di tua scelta, come pubblicata dalla Free Software Foundation.
Note: Copyright (c) 2020 di C. A. Lettsome Services, LLC
Per maggiori informazioni visita
*/
#define SAMPLES 128 //Max 128 per Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Fs = Basato su Nyquist, deve essere 2 volte la frequenza massima prevista.
#define OFFSETSAMPLES 40 //usato per scopi di calibrazione
#define TUNER -3 //Regola fino a quando C3 è 130.50
periodo di campionamento float;
microsecondi lunghi senza segno;
int X[CAMPIONI]; //crea un vettore di dimensioni SAMPLES per contenere valori reali
float autoCorr[SAMPLES]; //crea un vettore di dimensioni SAMPLES per contenere valori immaginari
float storedNoteFreq[12] = {130,81, 138,59, 146,83, 155,56, 164,81, 174,61, 185, 196, 207,65, 220, 233,08, 246,94};
int sommaOffSet = 0;
int offSet[CAMPIONI OFFSET]; //crea un vettore di offset
int avgOffSet; //crea un vettore di offset
int i, k, periodEnd, periodBegin, period, Adjuster, noteLocation, octaveRange;
float maxValue, minValue;
lunga somma;
int soglia = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, totale;
byte state_machine = 0;
int campioniPerPeriod = 0;
configurazione nulla()
{
Serial.begin(115200); //115200 Baud rate per il monitor seriale
}
ciclo vuoto()
{
//*****************************************************************
//Sezione di calibrazione
//*****************************************************************
Serial.println("Calatura. Per favore non suonare nessuna nota durante la calibrazione.");
for (i = 0; i < CAMPIONI OFFSET; i++)
{
offSet = analogRead(0); //Legge il valore dal pin analogico 0 (A0), lo quantizza e lo salva come termine reale.
//Serial.println(offSet); //usalo per regolare il modulo di rilevamento del suono a circa la metà oa 512 quando non viene riprodotto alcun suono.
sommaOffSet = sommaOffSet + offSet;
}
campioniPerPeriod = 0;
valoremax = 0;
//*****************************************************************
//Prepararsi ad accettare input da A0
//*****************************************************************
avgOffSet = round(sumOffSet / OFFSETSAMPLES);
Serial.println("Conto alla rovescia.");
ritardo(1000); //pausa per 1 secondo
Serial.println("3");
ritardo(1000); //pausa per 1 secondo
Serial.println("2");
ritardo(1000); //pausa per 1
Serial.println("1");
ritardo(1000); //pausa per 1 secondo
Serial.println("Riproduci la tua nota!");
ritardo(250); //pausa di 1/4 di secondo per il tempo di reazione
//*****************************************************************
//Raccogli i campioni SAMPLES da A0 con il periodo di campionamento del periodo di campionamento
//*****************************************************************
campionamentoPeriod = 1.0 / SAMPLING_FREQUENCY; //Periodo in microsecondi
for (i = 0; i < CAMPIONI; i++)
{
microSecondi = micros(); //Restituisce il numero di microsecondi da quando la scheda Arduino ha iniziato a eseguire lo script corrente.
X = analogRead(0); //Legge il valore dal pin analogico 0 (A0), lo quantizza e lo salva come termine reale.
/*tempo di attesa residuo tra i campioni se necessario in secondi */
while (micros() < (microSeconds + (samplingPeriod * 1000000)))
{
//non fare niente aspetta
}
}
//*****************************************************************
//Funzione di autocorrelazione
//*****************************************************************
for (i = 0; i < SAMPLES; i++) //i=ritardo
{
somma = 0;
for (k = 0; k < SAMPLES - i; k++) // Abbina segnale con segnale ritardato
{
somma = somma + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] è il segnale e X[k+i] è la versione ritardata
}
autoCorr = somma / CAMPIONI;
// Primo picco di rilevamento della macchina a stati
if (state_machine==0 && i == 0)
{
soglia = autoCorr * 0.5;
state_machine = 1;
}
else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, trova 1 punto per l'utilizzo del primo ciclo
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodoInizio = i-1;
state_machine = 2;
numOfCycles = 1;
campioniPerPeriod = (periodBegin - 0);
periodo = campioniPerPeriod;
aggiustatore = TUNER+(50.04 * exp(-0.102 * samplePerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-regolatore; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, trova 2 punti per il 1° e il 2° ciclo
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodoFine = i-1;
state_machine = 3;
numOfCycles = 2;
campioniPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-regolatore; // f = (2*fs)/(2*N)
valoremax = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, trova 3 punti per il 1°, 2° e 3° ciclo
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodoFine = i-1;
state_machine = 4;
numOfCycles = 3;
campioniPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-regolatore; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Analisi dei risultati
//*****************************************************************
if (campioniPerPeriod == 0)
{
Serial.println("Hmm….. non sono sicuro. Stai cercando di ingannarmi?");
}
altro
{
//prepara la funzione di ponderazione
totale = 0;
if (frequenza del segnale !=0)
{
totale = 1;
}
if(frequenza segnale2 !=0)
{
totale = totale + 2;
}
if (segnaleFrequenza3 !=0)
{
totale = totale + 3;
}
//calcola la frequenza usando la funzione di ponderazione
signalFrequencyGuess = ((1/total) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); //trova una frequenza ponderata
Serial.print("La nota che hai suonato è approssimativamente ");
Serial.print(signalFrequencyGuess); //Stampa la stima della frequenza.
Serial.println("Hz.");
//trova l'intervallo di ottava in base all'ipotesi
intervallo di ottava=3;
while (!(signalFrequencyGuess >= storedNoteFreq[0]-7 && signalFrequencyGuess <= storedNoteFreq[11]+7))
{
for(i = 0; i < 12; i++)
{
storedNoteFreq = 2 * storedNoteFreq;
}
intervallo di ottava++;
}
//Trova la nota più vicina
valoremin = 10000000;
notaPosizione = 0;
per (i = 0; i < 12; i++)
{
if(minValue> abs(signalFrequencyGuess-storedNoteFreq))
{
minValue = abs(signalFrequencyGuess-storedNoteFreq);
notaLocation = i;
}
}
//Stampa la nota
Serial.print("Penso che tu abbia giocato");
if(notaPosizione==0)
{
Serial.print("C");
}
else if(notaPosizione==1)
{
Serial.print("C#");
}
else if(notaPosizione==2)
{
Serial.print("D");
}
else if(notaPosizione==3)
{
Serial.print("D#");
}
else if(notaPosizione==4)
{
Serial.print("E");
}
else if(notaPosizione==5)
{
Serial.print("F");
}
else if(noteLocation==6)
{
Serial.print("F#");
}
else if(noteLocation==7)
{
Serial.print("G");
}
else if(noteLocation==8)
{
Serial.print("S#");
}
else if(notaPosizione==9)
{
Serial.print("A");
}
else if(notaPosizione==10)
{
Serial.print("A#");
}
else if(noteLocation==11)
{
Serial.print("B");
}
Serial.println(octaveRange);
}
//*****************************************************************
//Fermati qui. Premi il pulsante di ripristino su Arduino per riavviare
//*****************************************************************
mentre (1);
}

visualizza rawgistfile1.txt ospitato con ❤ da GitHub

Passaggio 3: impostare il rilevatore di note musicali

Collega Arduino Uno al PC con il codice scritto o caricato nell'IDE Arduino. Compila e carica il codice su Arduino. Posizionare il circuito vicino alla sorgente musicale. Nota: nel video introduttivo, utilizzo un'app installata sul tablet insieme agli altoparlanti del PC come sorgente musicale. Premi il pulsante di ripristino sulla scheda Arduino e quindi riproduci una nota sulla sorgente musicale. Dopo alcuni secondi, Musical Note Detector visualizzerà la nota suonata e la sua frequenza.

Consigliato: