Turinys:

Muzikos natų detektorius: 3 žingsniai
Muzikos natų detektorius: 3 žingsniai

Video: Muzikos natų detektorius: 3 žingsniai

Video: Muzikos natų detektorius: 3 žingsniai
Video: Arduino pamoka Nr. 10: Muzikinis sintezatorius 2024, Liepa
Anonim
Image
Image

Nustebinkite savo draugus ir šeimos narius šiuo projektu, kuris aptinka instrumentu grojamą natą. Šiame projekte bus rodomas apytikslis dažnis ir muzikos nata, grojama elektronine klaviatūra, fortepijono programa ar bet kuriuo kitu instrumentu.

Išsami informacija

Šiam projektui analoginis išėjimas iš garso modulio detektoriaus siunčiamas į Arduino Uno A0 analoginę įvestį. Analoginis signalas atrenkamas ir kvantuojamas (suskaitmeninamas). Autokoreliacijos, svėrimo ir derinimo kodas naudojamas norint rasti pagrindinį dažnį, naudojant pirmuosius 3 laikotarpius. Tada apytikslis pagrindinis dažnis lyginamas su 3, 4 ir 5 oktavų dažnių dažniais, kad būtų nustatytas artimiausias muzikos natų dažnis. Galiausiai ekrane atspausdinama artimiausio dažnio užrašyta pastaba.

Pastaba: ši instrukcija skirta tik tam, kaip sukurti projektą. Norėdami gauti daugiau informacijos apie detales ir dizaino pagrindimą, apsilankykite šioje nuorodoje: Daugiau informacijos

Prekės

  • (1) „Arduino Uno“(arba „Genuino Uno“)
  • (1) Suderinamas su DEVMO mikrofono jutiklio didelio jautrumo garso aptikimo moduliu
  • (1) Lydmetalinė duonos lenta
  • (1) USB-A-B kabelis
  • Jumperio laidai
  • Muzikos šaltinis (fortepijonas, klaviatūra arba „Weight“programa su garsiakalbiais)
  • (1) Kompiuteris ar nešiojamas kompiuteris

1 veiksmas: sukurkite aparatinę muzikinio užrašo detektorių

Nustatykite muzikos natos detektorių
Nustatykite muzikos natos detektorių

Naudodami „Arduino Uno“, prijungimo laidus, be litavimo duonos lentą ir „DEVMO“mikrofono jutiklio didelio jautrumo garso aptikimo modulį (ar panašų) sukurkite šiame paveikslėlyje pavaizduotą grandinę

2 veiksmas: užprogramuokite muzikos natos detektorių

Į „Arduino IDE“pridėkite šį kodą.

gistfile1.txt

/*
Failo/eskizo pavadinimas: MusicalNoteDetector
Versijos Nr.: v1.0 Sukurta 2020 m. Birželio 7 d
Originalus autorius: Clyde A. Lettsome, PhD, PE, MEM
Aprašymas: Šis kodas/eskizas rodo apytikslį dažnį ir muzikinę natą, grojamą elektronine klaviatūra ar fortepijono programa. Šiam projektui analoginė išvestis iš
garso modulio detektorius siunčiamas į „Arduino Uno“A0 analoginę įvestį. Analoginis signalas atrenkamas ir kvantuojamas (suskaitmeninamas). Naudojamas autokoreliacijos, svėrimo ir derinimo kodas
rasti pagrindinį dažnį, naudojant pirmuosius 3 periodus. Tada apytikslis pagrindinis dažnis lyginamas su 3, 4 ir 5 oktavų dažnių dažniais, kad būtų galima nustatyti artimiausią miuziklą
pastabų dažnis. Galiausiai ekrane atspausdinama artimiausio dažnio užrašyta pastaba.
Licencija: Ši programa yra nemokama programinė įranga; galite ją platinti ir (arba) modifikuoti pagal GNU bendrosios viešosios licencijos (GPL) 3 versijos sąlygas arba bet kurią vėliau
jūsų pasirinkta versija, kurią paskelbė „Free Software Foundation“.
Pastabos: autorių teisės (c) 2020 m. Pateikė C. A. Lettsome Services, LLC
Norėdami gauti daugiau informacijos, apsilankykite
*/
#define SAMPLES 128 // Maks. 128 „Arduino Uno“.
#define SAMPLING_FREQUENCY 2048 // Fs = Remiantis Nyquist, turi būti 2 kartus didesnis už didžiausią numatomą dažnį.
#define OFFSETSAMPLES 40 // naudojami kalabuliavimo tikslais
#define TUNER -3 // Koreguokite, kol C3 bus 130,50
float samplingPeriod;
nepasirašytos ilgos mikrosekundės;
int X [MĖGINIAI]; // sukurkite dydžio pavyzdžių vektorių realioms vertėms laikyti
plūduriuojanti autoCorr [MĖGINIAI]; // sukurkite dydžio pavyzdžių vektorių įsivaizduojamoms vertėms laikyti
plūdė saugomaNoteFreq [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]; // sukurti poslinkio vektorių
int avgOffSet; // sukurti poslinkio vektorių
int i, k, periodEnd, periodBegin, period, reguliatorius, noteLocation, octaveRange;
plūdė maxValue, minValue;
ilga suma;
int thresh = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
baitų būsenos_ mašina = 0;
int mėginiaiPerPeriod = 0;
negaliojanti sąranka ()
{
Serial.begin (115200); // 115200 Serijos monitoriaus baudų dažnis
}
tuštumos kilpa ()
{
//*****************************************************************
// Kalabravimo skyrius
//*****************************************************************
Serial.println ("Calabrating. Prašome negroti jokių natų kalabravimo metu.");
(i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Skaito vertę iš analoginio kaiščio 0 (A0), kvantuoja ją ir išsaugo ją kaip tikrąjį terminą.
//Serial.println(offSet); // naudokite tai, kad garso aptikimo modulį sureguliuotumėte maždaug iki pusės arba 512, kai neskamba garsas.
sumOffSet = sumOffSet + offSet ;
}
samplePerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Pasiruoškite priimti įvestį iš A0
//*****************************************************************
avgOffSet = apvalus (sumOffSet / OFFSETSAMPLES);
Serial.println („Skaičiuoti atgal“);
vėlavimas (1000); // pauzė 1 sekundei
Serial.println ("3");
vėlavimas (1000); // pauzė 1 sekundei
Serial.println ("2");
vėlavimas (1000); // pristabdyti 1
Serial.println ("1");
vėlavimas (1000); // pauzė 1 sekundei
Serial.println („Paleiskite savo užrašą!“);
vėlavimas (250); // pertrauka 1/4 sekundės reakcijos laikui
//*****************************************************************
// Surinkite SAMPLES mėginius iš A0 su mėginių ėmimo laikotarpiu
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Periodas mikrosekundėmis
(i = 0; i <MĖGINIAI; i ++)
{
mikrosekundės = mikros (); // Pateikia mikrosekundžių skaičių nuo tada, kai „Arduino“plokštė pradėjo vykdyti dabartinį scenarijų.
X = analogRead (0); // Skaito vertę iš analoginio kaiščio 0 (A0), kvantuoja ją ir išsaugo ją kaip tikrąjį terminą.
/ *likęs laukimo laikas tarp mėginių, jei reikia, sekundėmis */
tuo tarpu (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// nieko nedaryk, tik lauk
}
}
//*****************************************************************
// Autokoreliacijos funkcija
//*****************************************************************
(i = 0; i <MĖGINIAI; i ++) // i = uždelsimas
{
suma = 0;
for (k = 0; k <SAMPLES - i; k ++) // Suderinkite signalą su uždelstu signalu
{
suma = suma + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] yra signalas, o X [k+i] yra uždelsta versija
}
autoCorr = suma / MĖGINIAI;
// Pirmoji pikų aptikimo būsenos mašina
jei (būsenos mašina == 0 && i == 0)
{
kūlimas = autoCorr * 0,5;
būsenos_ mašina = 1;
}
kitaip jei (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, raskite 1 laikotarpį, kad galėtumėte naudoti pirmąjį ciklą
{
maxValue = autoCorr ;
}
kitaip jei (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
būsenos_ mašina = 2;
numOfCycles = 1;
samplePerPeriod = (periodBegin - 0);
laikotarpis = mėginiaiPerPeriodas;
reguliatorius = TUNER+(50,04 * exp (-0,102 * mėginiai per laikotarpį));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-reguliatorius; // f = fs/N
}
kitaip jei (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, raskite 2 laikotarpius 1 ir 2 ciklui
{
maxValue = autoCorr ;
}
kitaip jei (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
būsenos_ mašina = 3;
numOfCycles = 2;
samplePerPeriod = (periodEnd - 0);
signalFrequency2 = (((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-reguliatorius; // f = (2*fs)/(2*N)
maxValue = 0;
}
kitaip jei (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, raskite 3 laikotarpius 1, 2 ir 3 ciklams
{
maxValue = autoCorr ;
}
kitaip jei (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
būsenos_ mašina = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = (((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-reguliatorius; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Rezultatų analizė
//*****************************************************************
jei (samplePerPeriod == 0)
{
Serial.println ("Hmm ….. nesu tikras. Ar bandote mane apgauti?");
}
Kitas
{
// parengti svėrimo funkciją
iš viso = 0;
jei (signalFrequency! = 0)
{
iš viso = 1;
}
jei (signalFrequency2! = 0)
{
iš viso = iš viso + 2;
}
jei (signalFrequency3! = 0)
{
iš viso = iš viso + 3;
}
// apskaičiuoti dažnį naudojant svėrimo funkciją
signalFrequencyGuess = ((1/iš viso) * signalFrequency) + ((2/iš viso) * signalFrequency2) + ((3/iš viso) * signalFrequency3); // rasti svertinį dažnį
Serial.print („Pastaba, kurią grojote, yra apytiksliai“);
Serial.print (signalFrequencyGuess); // Spausdinti dažnio spėjimą.
Serial.println („Hz“);
// suraskite oktavos diapazoną pagal spėjimą
oktavaRange = 3;
nors (! (signalFrequencyGuess> = saugomasNoteFreq [0] -7 && signalFrequencyGuess <= saugomasNoteFreq [11] +7))
{
(i = 0; i <12; i ++)
{
storageNoteFreq = 2 * saugomiNoteFreq ;
}
oktavaRange ++;
}
// Raskite artimiausią užrašą
minVertybė = 10000000;
noteLocation = 0;
(i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storageNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storageNoteFreq );
noteLocation = i;
}
}
// Spausdinti užrašą
Serial.print („Manau, kad žaidėte“);
if (noteLocation == 0)
{
Serial.print („C“);
}
kitaip, jei (noteLocation == 1)
{
Serial.print („C#“);
}
kitaip, jei (noteLocation == 2)
{
Serial.print ("D");
}
kitaip, jei (noteLocation == 3)
{
Serial.print ("D#");
}
kitaip, jei (noteLocation == 4)
{
Serial.print („E“);
}
kitaip, jei (noteLocation == 5)
{
Serial.print ("F");
}
kitaip, jei (noteLocation == 6)
{
Serial.print ("F#");
}
kitaip, jei (noteLocation == 7)
{
Serial.print ("G");
}
kitaip, jei (noteLocation == 8)
{
Serial.print ("G#");
}
kitaip, jei (noteLocation == 9)
{
Serial.print ("A");
}
kitaip, jei (noteLocation == 10)
{
Serial.print ("A#");
}
kitaip jei (noteLocation == 11)
{
Serial.print („B“);
}
Serial.println (octaveRange);
}
//*****************************************************************
//Sustok čia. Norėdami paleisti iš naujo, paspauskite „Arduino“atstatymo mygtuką
//*****************************************************************
tuo tarpu (1);
}

peržiūrėti rawgistfile1.txt, kurį priglobia „GitHub“❤

3 veiksmas: nustatykite muzikos natos detektorių

Prijunkite „Arduino Uno“prie kompiuterio naudodami kodą, parašytą arba įkeltą į „Arduino IDE“. Sudarykite ir įkelkite kodą į „Arduino“. Padėkite grandinę arti muzikos šaltinio. Pastaba: įvadiniame vaizdo įraše kaip muzikos šaltinį naudoju planšetiniame kompiuteryje įdiegtą programą kartu su kompiuterio garsiakalbiais. Paspauskite „Arduino“lentos atstatymo mygtuką ir paleiskite muzikos šaltinio pastabą. Po kelių sekundžių muzikos natos detektorius parodys grojamą natą ir jos dažnumą.

Rekomenduojamas: