Sadržaj:
2025 Autor: John Day | [email protected]. Zadnja promjena: 2025-01-13 06:57
Zadivite svoje prijatelje i obitelj ovim projektom koji otkriva notu koju svira neki instrument. Ovaj će projekt prikazati približnu frekvenciju, kao i glazbenu notu sviranu na elektroničkoj tipkovnici, aplikaciji za glasovir ili bilo kojem drugom instrumentu.
Pojedinosti
Za ovaj projekt, analogni izlaz iz detektora zvučnog modula šalje se na A0 analogni ulaz Arduino Uno. Analogni signal se uzorkuje i kvantizira (digitalizira). Kod za automatsku korelaciju, ponderiranje i ugađanje koristi se za pronalaženje osnovne frekvencije pomoću prva 3 razdoblja. Približna osnovna frekvencija zatim se uspoređuje s frekvencijama u oktavama 3, 4 i 5 kako bi se odredila najbliža frekvencija glazbenih nota. Konačno, pogodna bilješka za najbližu frekvenciju ispisuje se na ekranu.
Napomena: Ova instrukcija se fokusira samo na to kako izgraditi projekt. Za više informacija o pojedinostima i opravdanjima dizajna posjetite ovu vezu: Više informacija
Pribor
- (1) Arduino Uno (ili Genuino Uno)
- (1) Kompatibilan DEVMO senzor mikrofona osjetljivog modula za otkrivanje zvuka visoke osjetljivosti
- (1) Oplata za lemljenje
- (1) Kabel USB-A do B
- Kratkospojne žice
- Glazbeni izvor (klavir, klavijatura ili paino aplikacija sa zvučnicima)
- (1) Računalo ili prijenosno računalo
Korak 1: Konstruirajte hardver za detektor glazbenih nota
Koristeći Arduino Uno, spojne žice, ploča za lemljenje i DEVMO senzorski mikrofonski senzor visoke osjetljivosti (ili sličan) modul za otkrivanje zvuka konstruiraju krug prikazan na ovoj slici
Korak 2: Programirajte detektor glazbenih nota
U Arduino IDE dodajte sljedeći kôd.
gistfile1.txt
/* |
Naziv datoteke/skice: MusicalNoteDetector |
Verzija br.: v1.0 Kreirano 7 lipnja 2020 |
Izvorni autor: Clyde A. Lettsome, PhD, PE, MEM |
Opis: Ovaj kod/skica prikazuje približnu frekvenciju, kao i glazbenu notu koja se svira na aplikaciji za elektroničku klavijaturu ili klavir. Za ovaj projekt analogni izlaz iz |
Detektor zvučnog modula šalje se na analogni ulaz A0 Arduino Uno. Analogni signal se uzorkuje i kvantizira (digitalizira). Kod za automatsku korelaciju, ponderiranje i ugađanje koristi se |
pronaći osnovnu frekvenciju pomoću prva 3 razdoblja. Približna temeljna frekvencija zatim se uspoređuje s frekvencijama u oktavama 3, 4 i 5 kako bi se odredio najbliži mjuzikl |
notna frekvencija. Konačno, pogodna bilješka za najbližu frekvenciju ispisuje se na ekranu. |
Licenca: Ovaj program je besplatni softver; možete je dalje distribuirati i/ili mijenjati pod uvjetima GNU -ove opće javne licence (GPL) verzije 3 ili bilo koje kasnije |
verziju po vašem izboru, koju je objavila Zaklada za slobodni softver. |
Bilješke: Autorska prava (c) 2020. C. A. Lettsome Services, LLC |
Za više informacija posjetite |
*/ |
#define SAMPLES 128 // Max 128 za Arduino Uno. |
#define SAMPLING_FREQUENCY 2048 // Fs = Na temelju Nyquista, mora biti 2 puta najveća očekivana frekvencija. |
#define OFFSETSAMPLES 40 // koristi se za kalabriranje |
#define TUNER -3 // Podešavajte dok C3 ne bude 130,50 |
razdoblje uzorkovanja float -a; |
nepotpisane duge mikrosekunde; |
int X [UZORCI]; // stvoriti vektor uzoraka veličine za držanje stvarnih vrijednosti |
float autoCorr [UZORCI]; // stvoriti vektor uzoraka veličine za držanje imaginarnih vrijednosti |
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]; // stvoriti vektor pomaka |
int avgOffSet; // stvoriti vektor pomaka |
int i, k, periodEnd, periodBegin, period, podešivač, noteLocation, oktavaRange; |
float maxValue, minValue; |
duga svota; |
int prag = 0; |
int numOfCycles = 0; |
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, ukupno; |
bajt stanje_stroja = 0; |
int uzorciPerPeriod = 0; |
void setup () |
{ |
Serial.begin (115200); // 115200 Baud rate za serijski monitor |
} |
void loop () |
{ |
//***************************************************************** |
// Odjeljak kalibracije |
//***************************************************************** |
Serial.println ("Kalabriranje. Nemojte svirati nikakve note tijekom kalibracije."); |
za (i = 0; i <OFFSETSAMPLES; i ++) |
{ |
offSet = analogRead (0); // Očitava vrijednost s analognog pina 0 (A0), kvantificira je i sprema kao pravi pojam. |
//Serial.println(offSet); // koristite za podešavanje modula za otkrivanje zvuka na približno polovicu ili 512 kada se ne reproducira zvuk. |
sumOffSet = sumOffSet + offSet ; |
} |
uzorciPerPeriod = 0; |
maxValue = 0; |
//***************************************************************** |
// Pripremite se za prihvaćanje unosa iz A0 |
//***************************************************************** |
avgOffSet = okrugli (sumOffSet / OFFSETSAMPLES); |
Serial.println ("Odbrojavanje".); |
kašnjenje (1000); // stanka na 1 sekundu |
Serial.println ("3"); |
kašnjenje (1000); // stanka na 1 sekundu |
Serial.println ("2"); |
kašnjenje (1000); // stanka za 1 |
Serial.println ("1"); |
kašnjenje (1000); // pauzirajte 1 sekundu |
Serial.println ("Sviraj svoju notu!"); |
kašnjenje (250); // pauzirajte 1/4 sekunde za vrijeme reakcije |
//***************************************************************** |
// Prikupiti uzorke uzoraka iz A0 s razdobljem uzorkovanja u razdoblju uzorkovanja |
//***************************************************************** |
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Razdoblje u mikrosekundama |
za (i = 0; i <UZORCI; i ++) |
{ |
mikrosekunde = mikros (); // Vraća broj mikrosekundi otkad je Arduino ploča počela izvoditi trenutnu skriptu. |
X = analogRead (0); // Očitava vrijednost s analognog pina 0 (A0), kvantificira je i sprema kao pravi pojam. |
/ *preostalo vrijeme čekanja između uzoraka ako je potrebno u sekundama */ |
while (micros () <(microSeconds + (samplingPeriod * 1000000))) |
{ |
// ne činiti ništa samo čekati |
} |
} |
//***************************************************************** |
// Funkcija autokorelacije |
//***************************************************************** |
for (i = 0; i <UZORCI; i ++) // i = kašnjenje |
{ |
zbroj = 0; |
for (k = 0; k <UZORCI - i; k ++) // Uskladite signal sa odgođenim signalom |
{ |
zbroj = zbroj + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] je signal, a X [k+i] odgođena verzija |
} |
autoCorr = zbroj / UZORCI; |
// Prvi stroj za otkrivanje vršnih vrhova |
if (stanje_stroja == 0 && i == 0) |
{ |
prag = autoCorr * 0,5; |
stanje_stroja = 1; |
} |
inače if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, pronađite 1 razdoblje za korištenje prvog ciklusa |
{ |
maxValue = autoCorr ; |
} |
inace if (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
{ |
periodBegin = i-1; |
stanje_stroja = 2; |
brojOciklusa = 1; |
uzorciPerPeriod = (periodBegin - 0); |
period = uzorciPerPeriod; |
podešivač = TUNER+(50,04 * eksp. (-0,102 * uzorciPeriod)); |
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-podešivač; // f = fs/N |
} |
inace if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, nađite 2 razdoblja za prvi i drugi ciklus |
{ |
maxValue = autoCorr ; |
} |
inace if (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
{ |
periodEnd = i-1; |
stanje_stroja = 3; |
broj ciklusa = 2; |
uzorciPerPeriod = (periodEnd - 0); |
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-podešivač; // f = (2*fs)/(2*N) |
maxValue = 0; |
} |
inace if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, nađite 3 razdoblja za 1., 2. i 3. ciklus |
{ |
maxValue = autoCorr ; |
} |
inace if (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0) |
{ |
periodEnd = i-1; |
stanje_stroja = 4; |
broj ciklusa = 3; |
uzorciPerPeriod = (periodEnd - 0); |
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-podešivač; // f = (3*fs)/(3*N) |
} |
} |
//***************************************************************** |
// Analiza rezultata |
//***************************************************************** |
if (uzorciPeriod == 0) |
{ |
Serial.println ("Hmm ….. nisam siguran. Pokušavate li me prevariti?"); |
} |
drugo |
{ |
// priprema funkcija ponderiranja |
ukupno = 0; |
if (signalFrequency! = 0) |
{ |
ukupno = 1; |
} |
if (signalFrequency2! = 0) |
{ |
ukupno = ukupno + 2; |
} |
if (signalFrequency3! = 0) |
{ |
ukupno = ukupno + 3; |
} |
// izračunati frekvenciju pomoću funkcije ponderiranja |
signalFrequencyGuess = ((1/ukupno) * signalFrequency) + ((2/ukupno) * signalFrequency2) + ((3/ukupno) * signalFrequency3); // pronaći ponderiranu frekvenciju |
Serial.print ("Bilješka koju ste odsvirali je otprilike"); |
Serial.print (signalFrequencyGuess); // Ispis pogađanja frekvencije. |
Serial.println ("Hz."); |
// pronaći osminski raspon na temelju pretpostavke |
octaveRange = 3; |
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7)) |
{ |
za (i = 0; i <12; i ++) |
{ |
storedNoteFreq = 2 * storedNoteFreq ; |
} |
octaveRange ++; |
} |
// Pronađite najbližu bilješku |
minVrijednost = 10000000; |
noteLocation = 0; |
za (i = 0; i <12; i ++) |
{ |
if (minValue> abs (signalFrequencyGuess-storedNoteFreq )) |
{ |
minValue = abs (signalFrequencyGuess-storedNoteFreq ); |
noteLocation = i; |
} |
} |
// Ispis bilješke |
Serial.print ("Mislim da ste svirali"); |
if (noteLocation == 0) |
{ |
Serial.print ("C"); |
} |
inace if (noteLocation == 1) |
{ |
Serial.print ("C#"); |
} |
inace if (noteLocation == 2) |
{ |
Serial.print ("D"); |
} |
inace if (noteLocation == 3) |
{ |
Serial.print ("D#"); |
} |
inace if (noteLocation == 4) |
{ |
Serial.print ("E"); |
} |
inace if (noteLocation == 5) |
{ |
Serial.print ("F"); |
} |
inace if (noteLocation == 6) |
{ |
Serial.print ("F#"); |
} |
inace if (noteLocation == 7) |
{ |
Serial.print ("G"); |
} |
inace if (noteLocation == 8) |
{ |
Serial.print ("G#"); |
} |
inace if (noteLocation == 9) |
{ |
Serial.print ("A"); |
} |
inace if (noteLocation == 10) |
{ |
Serial.print ("A#"); |
} |
inace if (noteLocation == 11) |
{ |
Serial.print ("B"); |
} |
Serial.println (octaveRange); |
} |
//***************************************************************** |
//Stanite ovdje. Pritisnite gumb za resetiranje na Arduinu za ponovno pokretanje |
//***************************************************************** |
while (1); |
} |
pogledajte rawgistfile1.txt hostirano sa ❤ na GitHubu
Korak 3: Postavite detektor glazbenih nota
Spojite Arduino Uno na računalo pomoću koda napisanog ili učitanog u Arduino IDE. Sastavite i prenesite kôd na Arduino. Postavite strujni krug blizu izvora glazbe. Napomena: U uvodnom videu kao izvor glazbe koristim aplikaciju instaliranu na tabletu zajedno s zvučnicima računala. Pritisnite gumb za resetiranje na Arduino ploči, a zatim pustite notu na izvoru glazbe. Nakon nekoliko sekundi, detektor glazbenih nota prikazat će odsviranu notu i njezinu frekvenciju.