INHOUDSOPGAWE:
2025 Outeur: John Day | [email protected]. Laas verander: 2025-01-13 06:56
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
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.