Hangjegy -érzékelő: 3 lépés
Hangjegy -érzékelő: 3 lépés
Anonim
Image
Image

Lepje meg barátait és családját ezzel a projekttel, amely érzékeli a hangszer által játszott hangot. Ez a projekt megjeleníti a hozzávetőleges gyakoriságot, valamint az elektronikus billentyűzeten, zongoraalkalmazásban vagy bármely más hangszeren játszott hangot.

Részletek

Ehhez a projekthez a hangmodul -érzékelő analóg kimenete az Arduino Uno A0 analóg bemenetére kerül. Az analóg jel mintavételezése és kvantálása (digitalizálása) történik. Az autokorreláció, a súlyozás és a hangolási kód az alapvető frekvencia megtalálására szolgál az első 3 periódus használatával. A hozzávetőleges alapfrekvenciát ezután összehasonlítják a 3., 4. és 5. oktáv frekvenciájával, hogy meghatározzák a legközelebbi hangjegy gyakoriságát. Végül a legközelebbi frekvencia találgatott megjegyzése kerül a képernyőre.

Megjegyzés: Ez az utasítás csak a projekt felépítésére összpontosít. A részletekről és a tervezés indoklásáról bővebb információt ezen a linken talál: További információ

Kellékek

  • (1) Arduino Uno (vagy Genuino Uno)
  • (1) A DEVMO mikrofonérzékelő nagy érzékenységű hangérzékelő modullal kompatibilis
  • (1) Forrasztás nélküli kenyértábla
  • (1) USB-A-B kábel
  • Jumper vezetékek
  • Zenei forrás (zongora, billentyűzet vagy súlyalkalmazás hangszórókkal)
  • (1) Számítógép vagy laptop

1. lépés: Készítse el a hangjegy -érzékelő hardverét

Állítsa be a hangjegy -érzékelőt
Állítsa be a hangjegy -érzékelőt

Az Arduino Uno, csatlakozóvezetékek, forrasztás nélküli kenyértábla és DEVMO mikrofonérzékelő nagy érzékenységű hangfelismerő modul (vagy hasonló) segítségével állítsa össze az ezen az ábrán látható áramkört

2. lépés: Programozza a hangjegy -érzékelőt

Az Arduino IDE -ben adja hozzá a következő kódot.

gistfile1.txt

/*
Fájl/vázlat neve: MusicalNoteDetector
Verziószám: v1.0 Létrehozva: 2020. június 7
Eredeti szerző: Clyde A. Lettsome, PhD, PE, MEM
Leírás: Ez a kód/vázlat megjeleníti a hozzávetőleges gyakoriságot, valamint az elektronikus billentyűzeten vagy zongoraalkalmazásban lejátszott hangot. Ehhez a projekthez az analóg kimenet a
hangmodul érzékelőt küld az Arduino Uno A0 analóg bemenetére. Az analóg jel mintavételezése és kvantálása (digitalizálása) történik. Az autokorrelációs, súlyozási és hangolási kódot használják
megtalálja az alapvető gyakoriságot az első 3 periódus használatával. A hozzávetőleges alapfrekvenciát ezután összehasonlítják a 3., 4. és 5. oktáv frekvenciájával, hogy meghatározzák a legközelebbi zenét
megjegyzés gyakorisága. Végül a legközelebbi frekvencia találgatott megjegyzése kerül a képernyőre.
Licenc: Ez a program ingyenes szoftver; újra terjesztheti és/vagy módosíthatja a GNU General Public License (GPL) 3. verziója vagy bármely későbbi feltétele szerint
az Ön által választott verzió, amint azt a Free Software Foundation közzétette.
Megjegyzések: Szerzői jog (c) 2020, C. A. Lettsome Services, LLC
További információ:
*/
#define MINTÁK 128 // Maximum 128 az Arduino Uno számára.
#define SAMPLING_FREQUENCY 2048 // Fs = Nyquist alapján kétszer a legmagasabb várható gyakoriságnak kell lennie.
#define OFFSETSAMPLES 40 // kalabázási célokra használják
#define TUNER -3 // Állítsa be, amíg a C3 értéke 130,50
float samplingPeriod;
előjel nélküli hosszú mikroszekundumok;
int X [MINTÁK]; // MINTA méretű vektor készítése valós értékek tárolására
úszó autoCorr [MINTÁK]; // minták méretű vektor létrehozása képzeletbeli értékek tárolására
float storageNoteFreq [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]; // offset vektor létrehozása
int avgOffSet; // offset vektor létrehozása
int i, k, periodEnd, periodBegin, period, Adjuster, noteLocation, oktávRange;
float maxValue, minValue;
hosszú összeg;
int thresh = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
bájt állapot_gép = 0;
int mintákPerPeriod = 0;
üres beállítás ()
{
Sorozat.kezdet (115200); // 115200 Baud arány a soros monitorhoz
}
üres hurok ()
{
//*****************************************************************
// Kalabrációs szakasz
//*****************************************************************
Serial.println ("Calabrating. Kérjük, ne játsszon semmilyen hangot a calabration alatt.");
for (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analóg olvasás (0); // Kiolvassa az értéket a 0 analóg tűből (A0), kvantálja és mentse el valós kifejezésként.
//Serial.println(offSet); // ezzel állíthatja be a hangérzékelő modult körülbelül felére vagy 512 -re, ha nincs hang.
sumOffSet = sumOffSet + offSet ;
}
samplePerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Készüljön fel az A0 bemenetének elfogadására
//*****************************************************************
avgOffSet = kerek (sumOffSet / OFFSETSAMPLES);
Serial.println ("Visszaszámlálás.");
késleltetés (1000); // szünet 1 másodpercig
Serial.println ("3");
késleltetés (1000); // szünet 1 másodpercig
Serial.println ("2");
késleltetés (1000); // szünet 1
Serial.println ("1");
késleltetés (1000); // szünet 1 másodpercig
Serial.println ("Játszd a jegyzeted!");
késleltetés (250); // szünet 1/4 másodperc a reakcióidő érdekében
//*****************************************************************
// SAMPLES minták gyűjtése az A0 -ból a mintavételi időszak mintavételi időszakával
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Periódus mikroszekundumokban
for (i = 0; i <MINTAK; i ++)
{
microSeconds = micros (); // Visszaadja a mikroszekundumok számát azóta, hogy az Arduino kártya elkezdte futtatni az aktuális szkriptet.
X = analógOlvasás (0); // Kiolvassa az értéket a 0 analóg tűből (A0), kvantálja és mentse el valós kifejezésként.
/ *hátralévő várakozási idő a minták között, ha szükséges másodpercekben */
míg (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// ne csinálj semmit csak várj
}
}
//*****************************************************************
// Autokorrelációs függvény
//*****************************************************************
for (i = 0; i <MINTAK; i ++) // i = késleltetés
{
összeg = 0;
for (k = 0; k <MINTÁK - i; k ++) // Párosítsa a jelet a késleltetett jellel
{
összeg = összeg + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] a jel, X [k+i] pedig a késleltetett verzió
}
autoCorr = összeg / MINTA;
// Első csúcsérzékelő állapotgép
ha (állapot_gép == 0 && i == 0)
{
cséplés = autoCorr * 0,5;
állapot_gép = 1;
}
egyébként if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, keressen 1 pontot az első ciklus használatához
{
maxValue = autoCorr ;
}
különben ha (állapot_gép == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
állapot_gép = 2;
numOfCycles = 1;
mintákPerPeriod = (periodBegin - 0);
időszak = mintákPerPeriod;
beállító = TUNER+(50,04 * exp (-0,102 * mintaperiódus));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-beállító; // f = fs/N
}
egyébként if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, keress 2 periódust az 1. és a 2. ciklushoz
{
maxValue = autoCorr ;
}
különben ha (állapot_gép == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
állapot_gép = 3;
numOfCycles = 2;
mintákPerPeriod = (periodEnd - 0);
signalFrequency2 = (((számOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-beállító; // f = (2*fs)/(2*N)
maxValue = 0;
}
egyébként if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, keress 3 periódust az 1., 2. és 3. ciklushoz
{
maxValue = autoCorr ;
}
egyébként ha (állapot_gép == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
állapot_gép = 4;
numOfCycles = 3;
mintákPerPeriod = (periodEnd - 0);
signalFrequency3 = (((számOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-beállító; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Eredményelemzés
//*****************************************************************
if (samplePerPeriod == 0)
{
Serial.println ("Hmm ….. Nem vagyok biztos benne. Meg akar csalni?");
}
más
{
// előkészíti a súlyozási függvényt
összesen = 0;
ha (signalFrequency! = 0)
{
összesen = 1;
}
ha (signalFrequency2! = 0)
{
összesen = összesen + 2;
}
ha (signalFrequency3! = 0)
{
összesen = összesen + 3;
}
// a gyakoriság kiszámítása a súlyozási funkció segítségével
signalFrequencyGuess = ((1/összesen) * jelFrekvencia) + ((2/összesen) * jelFrekvencia2) + ((3/összesen) * jelFrekvencia3); // súlyozott gyakoriság keresése
Serial.print ("A lejátszott hang kb.");
Serial.print (signalFrequencyGuess); // Nyomtassa ki a gyakorisági tippet.
Soros.println ("Hz");
// oktávtartomány megtalálása a találgatás alapján
oktávRange = 3;
while (! (signalFrequencyGuess> = storageNoteFreq [0] -7 && signalFrequencyGuess <= storageNoteFreq [11] +7))
{
mert (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
oktávRange ++;
}
// Keresse meg a legközelebbi jegyzetet
minValue = 10000000;
noteLocation = 0;
mert (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storageNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storageNoteFreq );
noteLocation = i;
}
}
// Nyomtassa ki a jegyzetet
Serial.print ("Azt hiszem, játszottál");
if (noteLocation == 0)
{
Soros.nyomtatás ("C");
}
egyébként ha (noteLocation == 1)
{
Serial.print ("C#");
}
egyébként ha (noteLocation == 2)
{
Serial.print ("D");
}
egyébként ha (noteLocation == 3)
{
Serial.print ("D#");
}
egyébként ha (noteLocation == 4)
{
Serial.print ("E");
}
egyébként ha (noteLocation == 5)
{
Serial.print ("F");
}
egyébként ha (noteLocation == 6)
{
Serial.print ("F#");
}
egyébként ha (noteLocation == 7)
{
Serial.print ("G");
}
egyébként ha (noteLocation == 8)
{
Serial.print ("G#");
}
egyébként ha (noteLocation == 9)
{
Serial.print ("A");
}
egyébként ha (noteLocation == 10)
{
Serial.print ("A#");
}
egyébként ha (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Állj meg itt. Az újraindításhoz nyomja meg az Arduino reset gombját
//*****************************************************************
míg (1);
}

nézd meg a rawgistfile1.txt fájlt, amelyet a GitHub ❤ üzemeltet

3. lépés: Állítsa be a hangjegy -érzékelőt

Csatlakoztassa az Arduino Uno -t a számítógéphez az Arduino IDE -be írt vagy betöltött kóddal. Fordítsa össze és töltse fel a kódot az Arduino -ba. Helyezze az áramkört a zeneforrás közelébe. Megjegyzés: A bemutatkozó videóban a táblagépre telepített alkalmazást használom a számítógép hangszóróival együtt zeneforrásként. Nyomja meg az Arduino Board alaphelyzetbe állító gombját, majd játssza le a zenei forrást. Néhány másodperc múlva a hangjegy -érzékelő megjeleníti a lejátszott hangot és annak gyakoriságát.

Ajánlott: