Taula de continguts:

Detector de notes musicals: 3 passos
Detector de notes musicals: 3 passos

Vídeo: Detector de notes musicals: 3 passos

Vídeo: Detector de notes musicals: 3 passos
Vídeo: The Fun Theory 1 – Piano Staircase Initiative | Volkswagen 2024, Desembre
Anonim
Image
Image

Sorprèn als teus amics i familiars amb aquest projecte que detecta la nota que toca un instrument. Aquest projecte mostrarà la freqüència aproximada, així com la nota musical reproduïda en un teclat electrònic, una aplicació de piano o qualsevol altre instrument.

Detalls

Per a aquest projecte, la sortida analògica del detector del mòdul de so s’envia a l’entrada analògica A0 de l’Arduino Uno. El senyal analògic es mostra i es quantifica (digitalitza). El codi d’autocorrelació, ponderació i afinació s’utilitza per trobar la freqüència fonamental mitjançant els primers 3 períodes. A continuació, es compara la freqüència fonamental aproximada amb les freqüències del rang de les octaves 3, 4 i 5 per determinar la freqüència de notes musicals més propera. Finalment, la nota endevinada de la freqüència més propera s’imprimeix a la pantalla.

Nota: aquesta instrucció només es centra en com construir el projecte. Per obtenir més informació sobre els detalls i les justificacions de disseny, visiteu aquest enllaç: Més informació

Subministraments

  • (1) Arduino Uno (o Genuino Uno)
  • (1) Compatible amb mòdul de detecció de so d'alta sensibilitat del sensor de micròfon DEVMO
  • (1) Taula de pa sense soldadura
  • (1) Cable USB-A a B.
  • Filferros de pont
  • Font musical (piano, teclat o aplicació paino amb altaveus)
  • (1) Ordinador o ordinador portàtil

Pas 1: construïu el maquinari per al detector de notes musicals

Configureu el detector de notes musicals
Configureu el detector de notes musicals

Mitjançant un Arduino Uno, els cables de connexió, una placa sense soldar i un mòdul de detecció de so d'alta sensibilitat (o similar) del sensor de micròfon DEVMO construeixen el circuit que es mostra en aquesta imatge

Pas 2: programa el Detector de notes musicals

A l’IDE Arduino, afegiu el codi següent.

gistfile1.txt

/*
Nom del fitxer / esbós: MusicalNoteDetector
Número de versió: v1.0 Creat el 7 de juny de 2020
Autor original: Clyde A. Lettsome, PhD, PE, MEM
Descripció: aquest codi / esbós mostra la freqüència aproximada i la nota musical reproduïda en un teclat electrònic o una aplicació de piano. Per a aquest projecte, la sortida analògica del fitxer
El detector de mòduls de so s’envia a l’entrada analògica A0 de l’Arduino Uno. El senyal analògic es mostra i es quantifica (digitalitza). S’utilitza el codi d’autocorrelació, ponderació i afinació
trobar freqüència fonamental utilitzant els primers 3 períodes. La freqüència fonamental aproximada es compara amb les freqüències de les octaves 3, 4 i 5 per determinar el musical més proper
freqüència de notes. Finalment, la nota endevinada de la freqüència més propera s’imprimeix a la pantalla.
Llicència: aquest programa és programari lliure; podeu redistribuir-lo i / o modificar-lo segons els termes de la Llicència Pública General GNU (GPL) versió 3, o qualsevol altra versió posterior
versió que trieu, publicada per la Free Software Foundation.
Notes: Copyright (c) 2020 de C. A. Lettsome Services, LLC
Per obtenir més informació, visiteu
*/
#define SAMPLES 128 // Max 128 per a Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Basat en Nyquist, ha de ser 2 vegades la freqüència més alta esperada.
#define OFFSETSAMPLES 40 // s’utilitza amb finalitats calabradores
#define TUNER -3 // Ajusta fins que C3 sigui 130,50
període de mostreig flotant;
microSegons llargs sense signar;
int X [MOSTRES]; // Creeu vector de MOSTRES de mida per contenir valors reals
float autoCorr [MOSTRES]; // Creeu vector de MOSTRES de mida per mantenir valors imaginaris
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 sumOffSet = 0;
int offSet [OFFSETSAMPLES]; // crear vector de desplaçament
int avgOffSet; // crear vector de desplaçament
int i, k, periodEnd, periodBegin, period, ajust, noteLocation, octaveRange;
float maxValue, minValue;
suma llarga;
int batre = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte state_machine = 0;
int samplesPerPeriod = 0;
configuració nul·la ()
{
Serial.begin (115200); // 115200 Baud rate per al monitor de sèrie
}
bucle buit ()
{
//*****************************************************************
// Secció de calabració
//*****************************************************************
Serial.println ("Calabrating. Si us plau, no toqueu cap nota durant la calabració.");
per a (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Llegeix el valor del pin analògic 0 (A0), quantifiqueu-lo i deseu-lo com a terme real.
//Serial.println(offSet); // utilitzeu això per ajustar el mòdul de detecció de so a aproximadament la meitat o 512 quan no es reprodueixi cap so.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
Valor màxim = 0;
//*****************************************************************
// Prepareu-vos per acceptar l'entrada d'A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("Compte enrere");
retard (1000); // pausa durant 1 segon
Serial.println ("3");
retard (1000); // pausa durant 1 segon
Serial.println ("2");
retard (1000); // pausa per a 1
Serial.println ("1");
retard (1000); // pausa durant 1 segon
Serial.println ("Reprodueix la teva nota!");
retard (250); // Pausa durant 1/4 de segon durant el temps de reacció
//*****************************************************************
// Recolliu mostres de MOSTRES d'A0 amb el període de mostra del període de mostreig
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Període en microsegons
per a (i = 0; i <SAMPLES; i ++)
{
microSegons = micros (); // Retorna el nombre de microsegons des que la placa Arduino va començar a executar l'script actual.
X = analogRead (0); // Llegeix el valor del pin analògic 0 (A0), quantifiqueu-lo i deseu-lo com a terme real.
/ * temps d'espera restant entre mostres si és necessari en segons * /
while (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// no fer res només esperar
}
}
//*****************************************************************
// Funció d’autocorrelació
//*****************************************************************
for (i = 0; i <SAMPLES; i ++) // i = delay
{
suma = 0;
for (k = 0; k <SAMPLES - i; k ++) // Coincideix el senyal amb el senyal retardat
{
suma = suma + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] és el senyal i X [k + i] és la versió retardada
}
autoCorr = suma / MOSTRES;
// Primera màquina d'estat de detecció de pics
if (state_machine == 0 && i == 0)
{
batre = autoCorr * 0,5;
màquina_estat = 1;
}
altrament si (state_machine == 1 && i> 0 && beat 0) // state_machine = 1, trobeu 1 període per utilitzar el primer cicle
{
Valor màxim = autoCorr ;
}
else if (state_machine == 1 && i> 0 && batre <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
màquina_estat = 2;
numOfCycles = 1;
samplesPerPeriod = (períodeBegin - 0);
període = samplesPerPeriod;
ajustador = TUNER + (50,04 * exp (-0,102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = fs / N
}
altrament si (state_machine == 2 && i> 0 && batre 0) // state_machine = 2, trobeu 2 períodes per al 1r i 2n cicle
{
Valor màxim = autoCorr ;
}
else if (state_machine == 2 && i> 0 && batre <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
màquina_estat = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (2 * fs) / (2 * N)
Valor màxim = 0;
}
altrament si (state_machine == 3 && i> 0 && batre 0) // state_machine = 3, trobeu 3 períodes per al 1r, 2n i 3r cicle
{
Valor màxim = autoCorr ;
}
else if (màquina_estat == 3 && i> 0 && batre <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
màquina_estat = 4;
numOfCycles = 3;
samplesPerPeriod = (PeriodEnd - 0);
signalFrequency3 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (3 * fs) / (3 * N)
}
}
//*****************************************************************
// Anàlisi de resultats
//*****************************************************************
if (samplesPerPeriod == 0)
{
Serial.println ("Hmm ….. No estic segur. Esteu intentant enganyar-me?");
}
en cas contrari
{
// prepara la funció de ponderació
total = 0;
if (freqüència del senyal! = 0)
{
total = 1;
}
if (freqüència del senyal2! = 0)
{
total = total + 2;
}
if (signalFrequency3! = 0)
{
total = total + 3;
}
// calcular la freqüència mitjançant la funció de ponderació
signalFrequencyGuess = ((1 / total) * signalFrequency) + ((2 / total) * signalFrequency2) + ((3 / total) * signalFrequency3); // trobar una freqüència ponderada
Serial.print ("La nota que heu interpretat és aproximadament");
Serial.print (signalFrequencyGuess); // Imprimiu la suposició de freqüència.
Serial.println ("Hz.");
// trobar el rang d'octava basat en la suposició
rang d’octava = 3;
while (! (signalFrequencyGuess> = storageNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7))
{
per a (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
octaveRange ++;
}
// Cerqueu la nota més propera
Valor mínim = 10000000;
notaLocalització = 0;
per a (i = 0; i <12; i ++)
{
if (MinValue> abs (signalFrequencyGuess-storedNoteFreq )))
{
MinValue = abs (signalFrequencyGuess-storedNoteFreq );
notaLocalització = i;
}
}
// Imprimeix la nota
Serial.print ("Crec que has jugat");
if (noteLocation == 0)
{
Serial.print ("C");
}
else if (noteLocation == 1)
{
Serial.print ("C #");
}
else if (noteLocation == 2)
{
Serial.print ("D");
}
else if (noteLocation == 3)
{
Serial.print ("D #");
}
else if (noteLocation == 4)
{
Serial.print ("E");
}
else if (noteLocation == 5)
{
Serial.print ("F");
}
else if (noteLocation == 6)
{
Serial.print ("F #");
}
else if (noteLocation == 7)
{
Serial.print ("G");
}
else if (noteLocation == 8)
{
Serial.print ("G #");
}
else if (noteLocation == 9)
{
Serial.print ("A");
}
else if (noteLocation == 10)
{
Serial.print ("A #");
}
else if (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Atura't aquí. Feu clic al botó de reinici d'Arduino per reiniciar-lo
//*****************************************************************
mentre que (1);
}

visualitza rawgistfile1.txt allotjat amb ❤ per GitHub

Pas 3: configureu el detector de notes musicals

Connecteu l'Arduino Uno al PC amb el codi escrit o carregat a l'IDE Arduino. Compileu i pengeu el codi a Arduino. Col·loqueu el circuit a prop de la font de música. Nota: Al vídeo de presentació, faig servir una aplicació instal·lada a la tauleta juntament amb altaveus de PC com a font de música. Feu clic al botó de restabliment de la placa Arduino i, a continuació, reproduïu una nota a la font de música. Al cap d’uns segons, el Detector de notes musicals mostrarà la nota reproduïda i la seva freqüència.

Recomanat: