Musieknootdetektor: 3 stappe
Musieknootdetektor: 3 stappe
Anonim
Image
Image

Verbaas jou vriende en familie met hierdie projek wat die noot wat deur 'n instrument gespeel word, opspoor. Hierdie projek toon die benaderde frekwensie sowel as die musieknoot wat op 'n elektroniese klawerbord, klavierprogram of enige ander instrument gespeel word.

Besonderhede

Vir hierdie projek word die analoog uitset van die klankmodule -detektor gestuur na die A0 analoog ingang van die Arduino Uno. Die analoog sein word bemonster en gekwantiseer (gedigitaliseer). Outokorrelasie-, weeg- en afstemkode word gebruik om die basiese frekwensie met behulp van die eerste 3 periodes te bepaal. Die benaderde fundamentele frekwensie word dan vergelyk met frekwensies in die oktawe 3, 4 en 5 om die naaste frekwensie van die musieknoot te bepaal. Uiteindelik word die raai -noot vir die naaste frekwensie op die skerm gedruk.

Opmerking: hierdie instruksies fokus slegs op die bou van die projek. Vir meer inligting oor die besonderhede en ontwerpregverdigings, besoek hierdie skakel: Meer inligting

Voorrade

  • (1) Arduino Uno (of Genuino Uno)
  • (1) DEVMO -mikrofoonsensor Versoenbaar met klankopsporingsmodule vir hoë sensitiwiteit
  • (1) Soldeerlose broodbord
  • (1) USB-A na B-kabel
  • Springdrade
  • Musikale bron (klavier, klawerbord of paino -app met luidsprekers)
  • (1) Rekenaar of skootrekenaar

Stap 1: Konstrueer die hardeware vir die musieknootdetektor

Stel die Musical Note Detector op
Stel die Musical Note Detector op

Deur 'n Arduino Uno te gebruik, bou verbindingsdrade, 'n soldeerlose broodbord en 'n DEVMO -mikrofoonsensor met 'n hoë sensitiwiteit -klankopsporingsmodule (of soortgelyke) die kring wat in hierdie prent getoon word.

Stap 2: Programmeer die Musical Note Detector

Voeg die volgende kode by in die Arduino IDE.

gistfile1.txt

/*
Lêer-/sketsnaam: MusicalNoteDetector
Weergawe -nr.: v1.0 Geskep op 7 Junie 2020
Oorspronklike outeur: Clyde A. Lettsome, PhD, PE, MEM
Beskrywing: Hierdie kode/skets toon die benaderde frekwensie sowel as die musieknoot wat op 'n elektroniese klawerbord of klavierprogram gespeel word. Vir hierdie projek, die analoog uitset van die
klankmodule -detektor word gestuur na die analoog A0 -ingang van die Arduino Uno. Die analoog sein word bemonster en gekwantiseer (gedigitaliseer). Outokorrelasie, gewig en afstemkode word gebruik om
vind basiese frekwensie met behulp van die eerste 3 periodes. Die benaderde fundamentele frekwensie word dan vergelyk met frekwensies in die oktawe 3, 4 en 5 om die naaste musiekblyspel te bepaal
let op frekwensie. Uiteindelik word die raai -noot vir die naaste frekwensie op die skerm gedruk.
Lisensie: Hierdie program is gratis sagteware; u kan dit herversprei en/of verander onder die voorwaardes van die GNU General Public License (GPL) weergawe 3, of later
weergawe van u keuse, soos gepubliseer deur die Free Software Foundation.
Notas: Kopiereg (c) 2020 deur C. A. Lettsome Services, LLC
Vir meer inligting, besoek
*/
#define SAMPLES 128 // Max 128 for Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Gebaseer op Nyquist, moet 2 keer die hoogste verwagte frekwensie wees.
#define OFFSETSAMPLES 40 // gebruik vir kalibrasie doeleindes
#define TUNER -3 // Pas aan totdat C3 130,50 is
vlotmonsterPeriode;
ongetekende lang mikrosekondes;
int X [Monsters]; // skep 'n vektor van MAATSELSTELLE om reële waardes te hou
float autoCorr [SAMPLES]; // skep 'n vektor van MAATSELSTELLE om denkbeeldige waardes te hou
float gestoorNoteFreq [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]; // skep 'n verrekeningsvektor
int avgOffSet; // skep 'n verrekeningsvektor
int i, k, periodEnd, periodBegin, period, adjuster, noteLocation, octaveRange;
float maxValue, minValue;
lang som;
int dors = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, totaal;
byte state_machine = 0;
int samplesPerPeriod = 0;
leemte opstelling ()
{
Serial.begin (115200); // 115200 Baud -tempo vir die seriële monitor
}
leemte lus ()
{
//*****************************************************************
// Kalibrasie -afdeling
//*****************************************************************
Serial.println ("Kalibrering. Moet asseblief nie tydens die kalibrasie enige note speel nie.");
vir (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Lees die waarde van analoog pen 0 (A0), kwantiseer dit en stoor dit as 'n werklike term.
//Serial.println(offSet ); // gebruik hierdie om die klankopsporingsmodule aan te pas tot ongeveer die helfte of 512 as geen geluid gespeel word nie.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Berei voor om insette van A0 te aanvaar
//*****************************************************************
avgOffSet = rond (sumOffSet / OFFSETSAMPLES);
Serial.println ("Aftel.");
vertraging (1000); // wag vir 1 sekonde
Serial.println ("3");
vertraging (1000); // wag vir 1 sekonde
Serial.println ("2");
vertraging (1000); // pouse vir 1
Serial.println ("1");
vertraging (1000); // wag vir 1 sekonde
Serial.println ("Speel u noot!");
vertraging (250); // pouse vir 1/4 sekonde vir reaksietyd
//*****************************************************************
// Versamel monsters van A0 met monsterperiode van monsternemingstydperk
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Periode in mikrosekondes
vir (i = 0; i <SAMPLES; i ++)
{
microSeconds = micros (); // Gee die aantal mikrosekondes terug sedert die Arduino -bord met die huidige script begin werk het.
X = analogRead (0); // Lees die waarde van analoog pen 0 (A0), kwantiseer dit en stoor dit as 'n werklike term.
/ *oorblywende wagtyd tussen monsters indien nodig in sekondes */
terwyl (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// niks doen nie, wag net
}
}
//*****************************************************************
// Outokorrelasie funksie
//*****************************************************************
vir (i = 0; i <SAMPLES; i ++) // i = vertraging
{
som = 0;
vir (k = 0; k <SAMPLES - i; k ++) // Pas sein met vertraagde sein
{
som = som + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] is die sein en X [k+i] is die vertraagde weergawe
}
autoCorr = som / VOORBEELDE;
// Eerste piekopsporing -staatsmasjien
as (state_machine == 0 && i == 0)
{
dors = autoCorr * 0.5;
staat_masjien = 1;
}
anders as (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, vind 1 tydperk vir die gebruik van eerste siklus
{
maxValue = autoCorr ;
}
anders as (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
staat_masjien = 2;
numOfCycles = 1;
samplesPerPeriod = (periodBegin - 0);
periode = monstersPerPeriod;
versteller = TUNER+(50.04 * exp (-0.102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-versteller; // f = fs/N
}
anders as (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, vind 2 periodes vir 1ste en 2de siklus
{
maxValue = autoCorr ;
}
anders as (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
staat_masjien = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-versteller; // f = (2*fs)/(2*N)
maxValue = 0;
}
anders as (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, vind 3 periodes vir 1ste, 2de en 3de siklus
{
maxValue = autoCorr ;
}
anders as (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
staatsmasjien = 4;
numOfCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-versteller; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Resultaatanalise
//*****************************************************************
as (samplesPerPeriod == 0)
{
Serial.println ("Hmm ….. ek is nie seker nie. Probeer jy my mislei?");
}
anders
{
// berei die weegfunksie voor
totaal = 0;
as (signalFrequency! = 0)
{
totaal = 1;
}
as (signalFrequency2! = 0)
{
totaal = totaal + 2;
}
as (signalFrequency3! = 0)
{
totaal = totaal + 3;
}
// bereken die frekwensie met behulp van die weegfunksie
signalFrequencyGuess = ((1/totaal) * signalFrequency) + ((2/totaal) * signalFrequency2) + ((3/totaal) * signalFrequency3); // vind 'n geweegde frekwensie
Serial.print ("Die noot wat u gespeel het, is ongeveer");
Serial.print (signalFrequencyGuess); // Druk die frekwensie -raaiskoot af.
Serial.println ("Hz.");
// vind oktaafreeks gebaseer op die raaiskoot
octaveRange = 3;
terwyl (! (signalFrequencyGuess> = storageNoteFreq [0] -7 && signalFrequencyGuess <= storageNoteFreq [11] +7))
{
vir (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
octaveRange ++;
}
// Vind die noot wat die naaste is
minWaarde = 10000000;
noteLocation = 0;
vir (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// Druk die nota af
Serial.print ("Ek dink jy het gespeel");
as (noteLocation == 0)
{
Serial.print ("C");
}
anders as (noteLocation == 1)
{
Serial.print ("C#");
}
anders as (noteLocation == 2)
{
Serial.print ("D");
}
anders as (noteLocation == 3)
{
Serial.print ("D#");
}
anders as (noteLocation == 4)
{
Serial.print ("E");
}
anders as (noteLocation == 5)
{
Serial.print ("F");
}
anders as (noteLocation == 6)
{
Serial.print ("F#");
}
anders as (noteLocation == 7)
{
Serial.print ("G");
}
anders as (noteLocation == 8)
{
Serial.print ("G#");
}
anders as (noteLocation == 9)
{
Serial.print ("A");
}
anders as (noteLocation == 10)
{
Serial.print ("A#");
}
anders as (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Stop hier. Druk die reset -knoppie op Arduino om weer te begin
//*****************************************************************
terwyl (1);
}

sien rawgistfile1.txt aangebied deur ❤ deur GitHub

Stap 3: Stel die Musical Note Detector op

Koppel die Arduino Uno aan die rekenaar met die kode wat in die Arduino IDE geskryf of gelaai is. Stel die kode saam en laai dit op na die Arduino. Plaas die kring naby die musiekbron. Opmerking: in die inleidingsvideo gebruik ek 'n app wat op die tablet geïnstalleer is, saam met rekenaarsprekers as my musiekbron. Druk die reset -knoppie op die Arduino Board en speel dan 'n noot oor die musiekbron. Na 'n paar sekondes sal die Musical Note Detector die gespeelde noot en die frekwensie daarvan wys.