Nuotin ilmaisin: 3 vaihetta
Nuotin ilmaisin: 3 vaihetta
Anonim
Image
Image

Yllätä ystäväsi ja perheesi tällä projektilla, joka havaitsee instrumentin soittaman nuotin. Tämä projekti näyttää likimääräisen taajuuden sekä nuotin, joka soitetaan elektronisella näppäimistöllä, pianosovelluksella tai muulla instrumentilla.

Yksityiskohdat

Tässä projektissa äänimoduulin ilmaisimen analoginen lähtö lähetetään Arduino Unon A0 -analogituloon. Analoginen signaali näytteistetään ja kvantisoidaan (digitoidaan). Autokorrelaatiota, painotusta ja virityskoodia käytetään perustaajuuden löytämiseen kolmen ensimmäisen jakson avulla. Likimääräistä perustaajuutta verrataan sitten oktaavien 3, 4 ja 5 taajuuksiin lähimmän nuotin taajuuden määrittämiseksi. Lopuksi lähimmälle taajuudelle arvattu muistiinpano tulostetaan näytölle.

Huomautus: Tässä ohjeessa keskitytään vain projektin rakentamiseen. Lisätietoja yksityiskohdista ja suunnittelun perusteluista löydät tästä linkistä: Lisätietoja

Tarvikkeet

  • (1) Arduino Uno (tai Genuino Uno)
  • (1) Yhteensopiva DEVMO -mikrofonianturin korkean herkkyyden äänentunnistusmoduulin kanssa
  • (1) Juotamaton leipälevy
  • (1) USB-A-B-kaapeli
  • Hyppyjohdot
  • Musiikkilähde (piano, näppäimistö tai paino -sovellus kaiuttimilla)
  • (1) Tietokone tai kannettava tietokone

Vaihe 1: Rakenna nuotinilmaisimen laitteisto

Asenna nuotinilmaisin
Asenna nuotinilmaisin

Käytä Arduino Unoa, liitäntäjohtoja, juotonta leipälevyä ja DEVMO -mikrofonianturin korkean herkkyyden äänentunnistusmoduulia (tai vastaavaa) muodostamaan tässä kuvassa näkyvä piiri

Vaihe 2: Ohjelmoi nuotinilmaisin

Lisää seuraava koodi Arduino IDE: hen.

gistfile1.txt

/*
Tiedoston/luonnoksen nimi: MusicalNoteDetector
Versio nro: v1.0 Luotu 7. kesäkuuta 2020
Alkuperäinen kirjoittaja: Clyde A. Lettsome, tohtori, PE, MEM
Kuvaus: Tämä koodi/luonnos näyttää likimääräisen taajuuden sekä nuotin, joka soitetaan elektronisella näppäimistöllä tai pianosovelluksella. Tässä projektissa analoginen lähtö
äänimoduulin ilmaisin lähetetään Arduino Unon A0 -analogituloon. Analoginen signaali näytteistetään ja kvantisoidaan (digitoidaan). Autokorrelaatiota, painotusta ja virityskoodia käytetään
löytää perustaajuus käyttämällä kolmea ensimmäistä jaksoa. Arvioitua perustaajuutta verrataan sitten oktaavien 3, 4 ja 5 taajuuksiin lähimmän musikaalin määrittämiseksi
muistiinpanotaajuus. Lopuksi lähimmälle taajuudelle arvattu muistiinpano tulostetaan näytölle.
Lisenssi: Tämä ohjelma on ilmainen ohjelmisto; voit jakaa sen uudelleen ja/tai muokata sitä GNU General Public License (GPL) -version 3 ehtojen mukaisesti tai myöhemmin
valitsemasi version Free Software Foundationin julkaisemana.
Huomautuksia: Tekijänoikeus (c) 2020, C. A. Lettsome Services, LLC
Lisätietoja on osoitteessa
*/
#define SAMPLES 128 // Enintään 128 Arduino Unolle.
#define SAMPLING_FREQUENCY 2048 // Fs = Nyquistin perusteella sen on oltava kaksi kertaa korkein odotettu taajuus.
#define OFFSETSAMPLES 40 // käytetään kalablaatiotarkoituksiin
#define TUNER -3 // Säädä kunnes C3 on 130,50
kelluva näytteenottoAika;
allekirjoittamattomat pitkät mikrosekunnit;
int X [NÄYTTEET]; // Luo SAMPLES -kokoinen vektori todellisten arvojen säilyttämiseksi
kelluva autoCorr [NÄYTTEET]; // luo vektori, jonka koko on SAMPLES pitämään kuvitteellisia arvoja
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]; // luoda offset -vektori
int avgOffSet; // luoda offset -vektori
int i, k, periodEnd, periodBegin, period, Adjuster, noteLocation, oktaavialue;
float maxValue, minValue;
pitkä summa;
int thresh = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, yhteensä;
tavu tila_kone = 0;
int näytteetPerPeriod = 0;
mitätön asennus ()
{
Sarja.alku (115200); // 115200 Sarjamonitorin siirtonopeus
}
tyhjä silmukka ()
{
//*****************************************************************
// Calabration -osio
//*****************************************************************
Serial.println ("Calabrating. Älä toista mitään nuotteja calabration aikana.");
for (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analoginen (0); // Lukee arvon analogisesta nastasta 0 (A0), kvantisoi sen ja tallentaa sen todellisena terminä.
//Sarja.println(offSet); // käytä tätä säätääksesi äänentunnistusmoduulin noin puoleen tai 512, kun ääntä ei toisteta.
sumOffSet = sumOffSet + offSet ;
}
samplePerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Valmistaudu syötteen vastaanottamiseen A0: sta
//*****************************************************************
avgOffSet = pyöreä (sumOffSet / OFFSETSAMPLES);
Serial.println ("Laskenta alas.");
viive (1000); // keskeytä 1 sekunti
Serial.println ("3");
viive (1000); // keskeytä 1 sekunti
Serial.println ("2");
viive (1000); // tauko 1
Serial.println ("1");
viive (1000); // keskeytä 1 sekunti
Serial.println ("Toista muistiinpanosi!");
viive (250); // tauko 1/4 sekunniksi reaktioaikaksi
//*****************************************************************
// Kerää näytteitä näytteestä A0 näytteenottoajanjakson aikana
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Jakso mikrosekunneissa
(i = 0; i <NÄYTTEET; i ++)
{
mikrosekunnit = mikros (); // Palauttaa mikrosekuntien määrän siitä lähtien, kun Arduino -kortti aloitti nykyisen komentosarjan suorittamisen.
X = analoginen (0); // Lukee arvon analogisesta nastasta 0 (A0), kvantisoi sen ja tallentaa sen todellisena terminä.
/ *jäljellä oleva odotusaika näytteiden välillä tarvittaessa sekunneissa */
kun taas (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// älä tee mitään vain odota
}
}
//*****************************************************************
// Automaattinen korrelaatiotoiminto
//*****************************************************************
for (i = 0; i <SAMPLES; i ++) // i = viive
{
summa = 0;
for (k = 0; k <SAMPLES - i; k ++) // Sovita signaali viivästetyn signaalin kanssa
{
summa = summa + ((((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] on signaali ja X [k+i] on viivästetty versio
}
autoCorr = summa / NÄYTTEET;
// Ensimmäinen huipputunnistustilakone
jos (tila_kone == 0 && i == 0)
{
heitto = autoCorr * 0,5;
tila_kone = 1;
}
else if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, etsi 1 jakso ensimmäisen syklin käyttämistä varten
{
maxValue = autoCorr ;
}
muuten jos (tila_kone == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
tila_kone = 2;
numOfCycles = 1;
samplePerPeriod = (periodBegin - 0);
aika = näytteetPerPeriod;
säädin = TUNER+(50,04 * exp (-0,102 * samplePerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-säädin; // f = fs/N
}
else if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, etsi 2 jaksoa ensimmäiselle ja toiselle jaksolle
{
maxValue = autoCorr ;
}
muuten jos (tila_kone == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
tila_kone = 3;
numOfCycles = 2;
samplePerPeriod = (periodEnd - 0);
signalFrequency2 = (((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-säädin; // f = (2*fs)/(2*N)
maxValue = 0;
}
else if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, etsi 3 jaksoa 1., 2. ja 3. syklille
{
maks.arvo = autoCorr ;
}
muuten jos (tila_kone == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
tila_kone = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = (((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-säädin; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Tulosanalyysi
//*****************************************************************
jos (samplePerPeriod == 0)
{
Serial.println ("Hmm….. en ole varma. Yritätkö huijata minua?");
}
muu
{
// valmistele painotus
yhteensä = 0;
jos (signalFrequency! = 0)
{
yhteensä = 1;
}
jos (signalFrequency2! = 0)
{
yhteensä = yhteensä + 2;
}
jos (signalFrequency3! = 0)
{
yhteensä = yhteensä + 3;
}
// laske taajuus painotusfunktion avulla
signalFrequencyGuess = ((1/yhteensä) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); // löytää painotettu taajuus
Serial.print ("Soittamasi nuotti on suunnilleen");
Serial.print (signalFrequencyGuess); // Tulosta taajuusarvaus.
Sarja.println ("Hz");
// löytää oktaavialueen arvauksen perusteella
oktaavialue = 3;
kun taas (! (signalFrequencyGuess> = tallennettuNoteFreq [0] -7 && signalFrequencyGuess <= tallennettuNoteFreq [11] +7))
{
(i = 0; i <12; i ++)
{
storageNoteFreq = 2 * tallennettuNoteFreq ;
}
oktaavialue ++;
}
// Etsi lähin nuotti
minValue = 10000000;
noteLocation = 0;
(i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storageNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storageNoteFreq );
noteLocation = i;
}
}
// Tulosta muistiinpano
Serial.print ("Luulen, että pelasit");
jos (noteLocation == 0)
{
Serial.print ("C");
}
muuten jos (noteLocation == 1)
{
Serial.print ("C#");
}
muuten jos (noteLocation == 2)
{
Serial.print ("D");
}
muuten jos (noteLocation == 3)
{
Serial.print ("D#");
}
muuten jos (noteLocation == 4)
{
Serial.print ("E");
}
muuten jos (noteLocation == 5)
{
Serial.print ("F");
}
muuten jos (noteLocation == 6)
{
Serial.print ("F#");
}
muuten jos (noteLocation == 7)
{
Serial.print ("G");
}
muuten jos (noteLocation == 8)
{
Serial.print ("G#");
}
muuten jos (noteLocation == 9)
{
Serial.print ("A");
}
muuten jos (noteLocation == 10)
{
Serial.print ("A#");
}
muuten jos (noteLocation == 11)
{
Serial.print ("B");
}
Sarja.println (oktaavialue);
}
//*****************************************************************
//Pysähdy tähän. Käynnistä uudelleen painamalla Arduinon nollauspainiketta
//*****************************************************************
kun taas (1);
}

katso rawgistfile1.txt, jota isännöi GitHub

Vaihe 3: Asenna nuotinilmaisin

Liitä Arduino Uno tietokoneeseen koodilla, joka on kirjoitettu tai ladattu Arduino IDE: hen. Kokoa ja lähetä koodi Arduinolle. Aseta piiri lähelle musiikkilähdettä. Huomautus: Esittelyvideossa käytän musiikkilähteenä sovellusta, joka on asennettu tablettiin PC -kaiuttimien kanssa. Paina Arduino Boardin nollauspainiketta ja toista sitten nuotti musiikkilähteestä. Muutaman sekunnin kuluttua nuotti -ilmaisin näyttää soitetun nuotin ja sen taajuuden.