Detektor i Shënimeve Muzikore: 3 Hapa
Detektor i Shënimeve Muzikore: 3 Hapa
Anonim
Image
Image

Habitni miqtë dhe familjen tuaj me këtë projekt që zbulon notën e luajtur nga një instrument. Ky projekt do të shfaqë frekuencën e përafërt si dhe notën muzikore të luajtur në një tastierë elektronike, aplikacion pianoje ose ndonjë instrument tjetër.

Detajet

Për këtë projekt, dalja analoge nga detektori i modulit të zërit dërgohet në hyrjen analoge A0 të Arduino Uno. Sinjali analog merret mostra dhe kuantizohet (digjitalizohet). Kodi i autokorrelacionit, peshimit dhe akordimit përdoret për të gjetur frekuencën themelore duke përdorur 3 periudhat e para. Frekuenca e përafërt themelore krahasohet më pas me frekuencat në rangun e oktavave 3, 4 dhe 5 për të përcaktuar frekuencën më të afërt të notave muzikore. Më në fund shënimi i supozuar për frekuencën më të afërt shtypet në ekran.

Shënim: Ky udhëzues fokusohet vetëm në mënyrën e ndërtimit të projektit. Për më shumë informacion në lidhje me detajet dhe arsyetimet e projektimit, ju lutemi vizitoni këtë lidhje: Më shumë informacion

Furnizimet

  • (1) Arduino Uno (ose Genuino Uno)
  • (1) Sensori i mikrofonit DEVMO Moduli i zbulimit të tingullit me ndjeshmëri të lartë i pajtueshëm
  • (1) Tabela e bukës pa saldim
  • (1) Kabllo USB-A në B
  • Telat e kërcyesit
  • Burimi muzikor (piano, tastierë ose aplikacion për dhimbje me folës)
  • (1) Kompjuter ose laptop

Hapi 1: Ndërtoni pajisjen për detektorin e shënimeve muzikore

Vendosni detektorin e shënimeve muzikore
Vendosni detektorin e shënimeve muzikore

Duke përdorur një Arduino Uno, telat e lidhjes, një tabelë pa saldim dhe një modul të zbulimit të tingullit me ndjeshmëri të lartë të sensorit të mikrofonit DEVMO (ose të ngjashme) ndërtoni qarkun e treguar në këtë imazh

Hapi 2: Programoni Detektorin e Shënimeve Muzikore

Në Arduino IDE, shtoni kodin e mëposhtëm.

gistfile1.txt

/*
Emri i skedarit/skicës: MusicalNoteDetector
Versioni Nr.: V1.0 Krijuar më 7 qershor, 2020
Autori origjinal: Clyde A. Lettsome, PhD, PE, MEM
Përshkrimi: Ky kod/skicë tregon frekuencën e përafërt si dhe notën muzikore të luajtur në një tastierë elektronike ose aplikacion pianoje. Për këtë projekt, dalja analoge nga
detektori i modulit të zërit dërgohet në hyrjen analoge A0 të Arduino Uno. Sinjali analog merret mostra dhe kuantizohet (digjitalizohet). Kodi i autokorrelacionit, peshimit dhe akordimit përdoret për
gjeni frekuencën themelore duke përdorur 3 periudhat e para. Frekuenca e përafërt themelore krahasohet më pas me frekuencat në rangun e oktavave 3, 4 dhe 5 për të përcaktuar muzikën më të afërt
frekuenca e shënimeve. Më në fund shënimi i supozuar për frekuencën më të afërt shtypet në ekran.
Licenca: Ky program është softuer falas; mund ta rishpërndani dhe/ose modifikoni sipas kushteve të Licencës së Përgjithshme Publike GNU (GPL) versioni 3, ose ndonjë më vonë
versioni i zgjedhjes suaj, siç është publikuar nga Fondacioni i Softuerit të Lirë.
Shënime: E drejta e autorit (c) 2020 nga C. A. Lettsome Services, LLC
Për më shumë informacion vizitoni
*/
#përcakto SHEMBULL 128 // Maks 128 për Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Bazuar në Nyquist, duhet të jetë 2 herë frekuenca më e lartë e pritshme.
#përcaktoni OFFSETSAMPLE 40 // të përdorura për qëllime kalabruese
#define TUNER -3 // Rregulloni derisa C3 të jetë 130.50
marrja e mostrave notuesePeriudha;
mikro sekonda të gjata të panënshkruara;
int X [Mostrat]; // krijoni vektor me madhësi SHEMBULL për të mbajtur vlera reale
noton autoCorr [Mostrat]; // krijoni vektor me madhësi SHEMBULL për të mbajtur vlera imagjinare
nota e ruajturNoteFreq [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]; // krijoni vektor të kompensuar
int avgOffSet; // krijoni vektor të kompensuar
int i, k, periodEnd, periodFillim, period, rregullues, shënimLokacioni, oktavaRange;
float maxValue, minValue;
shumë e gjatë;
int thresh = 0;
int numOfCycles = 0;
sinjal notuesFrekuenca, sinjalFrekuenca2, sinjalFrekuenca3, sinjalFrekuencaGjestësia, gjithsej;
byte gjendja_makina = 0;
mostrat intPerPeriod = 0;
void setup ()
{
Serial.filloj (115200); // 115200 Norma Baud për Monitor Serial
}
lak void ()
{
//*****************************************************************
// Seksioni i Calabration
//*****************************************************************
Serial.println ("Calabrating. Ju lutemi mos luani asnjë shënim gjatë kalabracionit.");
për (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Lexon vlerën nga kunja analoge 0 (A0), e kuantizon dhe e ruan si term real.
//Serial.println(offSet sharedi]; // përdorni këtë për të rregulluar modulin e zbulimit të zërit në afërsisht gjysmën ose 512 kur nuk luhet zë.
sumOffSet = sumOffSet + offSet ;
}
mostraPerPeriudha = 0;
maxValue = 0;
//*****************************************************************
// Përgatituni për të pranuar të dhëna nga A0
//*****************************************************************
avgOffSet = raund (sumOffSet / OFFSETSAMPLES);
Serial.println ("Numërimi mbrapsht.");
vonesa (1000); // pauzë për 1 sekonda
Serial.println ("3");
vonesa (1000); // pauzë për 1 sekonda
Serial.println ("2");
vonesa (1000); // pauzë për 1
Serial.println ("1");
vonesa (1000); // pauzë për 1 sekonda
Serial.println ("Luani shënimin tuaj!");
vonesë (250); // pauzë për 1/4 sekondë për kohën e reagimit
//*****************************************************************
// Mblidhni mostrat e mostrave nga A0 me periudhën e mostrës së periudhës së kampionimit
//*****************************************************************
mostërPeriudha = 1.0 / SAMPLING_FREQUENCY; // Periudha në mikrosekonda
për (i = 0; i <mostrat; i ++)
{
mikro sekonda = mikros (); // Kthen numrin e mikrosekondave që kur bordi Arduino filloi të ekzekutojë skriptin aktual.
X = analogRead (0); // Lexon vlerën nga kunja analoge 0 (A0), e kuantizon dhe e ruan si term real.
/ *koha e mbetur e pritjes midis mostrave nëse është e nevojshme në sekonda */
ndërsa (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// mos bëni asgjë vetëm prisni
}
}
//*****************************************************************
// Funksioni i autokorrelacionit
//*****************************************************************
për (i = 0; i <mostrat; i ++) // i = vonesë
{
shuma = 0;
për (k = 0; k <Mostrat - i; k ++) // Përputhja e sinjalit me sinjalin e vonuar
{
shuma = shuma + ((((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] është sinjali dhe X [k+i] është versioni i vonuar
}
autoCorr = shuma / SHEMBUJ;
// Makina e parë e zbulimit të pikut të parë
nëse (makina_shtetërore == 0 && i == 0)
{
thresh = autoCorr * 0.5;
makina e gjendjes = 1;
}
përndryshe nëse (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, gjeni 1 periudhë për përdorimin e ciklit të parë
{
maxValue = autoCorr ;
}
përndryshe nëse (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
makinë_shtetërore = 2;
numOfCycles = 1;
mostraPerPeriudha = (periudhaFillo - 0);
periudhë = mostraPeriudhë;
rregullues = TUNER+(50.04 * exp (-0.102 * samplePerPeriod));
sinjal Frekuenca = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-rregullues; // f = fs/N
}
përndryshe nëse (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, gjeni 2 periudha për ciklin e parë dhe të dytë
{
maxValue = autoCorr ;
}
përndryshe nëse (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
makinë_shtetërore = 3;
numOfCycles = 2;
mostraPerPeriudha = (periudha Fundi - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-rregullues; // f = (2*fs)/(2*N)
maxValue = 0;
}
përndryshe nëse (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, gjeni 3 periudha për ciklin e parë, të dytë dhe të tretë
{
maxValue = autoCorr ;
}
përndryshe nëse (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
makinë_shtetërore = 4;
numOfCycles = 3;
mostraPerPeriudha = (periudha Fundi - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-rregullues; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Analiza e rezultateve
//*****************************************************************
nëse (mostratPerPeriudha == 0)
{
Serial.println ("Hmm….. nuk jam i sigurt. Po përpiqesh të më mashtrosh?");
}
tjeter
{
// përgatit funksionin e peshimit
gjithsej = 0;
nëse (sinjal Frekuenca! = 0)
{
gjithsej = 1;
}
nëse (sinjal Frekuenca2! = 0)
{
total = total + 2;
}
nëse (sinjal Frekuenca3! = 0)
{
total = total + 3;
}
// llogarit frekuencën duke përdorur funksionin e peshimit
signalFrequencyGuess = ((1/total) * sinjal Frekuenca) + ((2/gjithsej) * sinjal Frekuenca2) + ((3/gjithsej) * sinjal Frekuenca3); // gjeni një frekuencë të ponderuar
Serial.print ("Shënimi që keni luajtur është afërsisht");
Serial.print (signalFrequencyGuess); // Shtyp supozimin e frekuencës.
Serial.println ("Hz.");
// gjeni gamën e oktavës bazuar në supozimin
varg oktava = 3;
ndërsa (! (signalFrequencyGuess> = ruhetNoteFreq [0] -7 && signalFrequencyGuess <= ruhetNoteFreq [11] +7))
{
për (i = 0; i <12; i ++)
{
ruhetNoteFreq = 2 * ruhetNoteFreq ;
}
octaveRange ++;
}
// Gjeni shënimin më të afërt
minVlera = 10000000;
shënimLokacioni = 0;
për (i = 0; i <12; i ++)
{
if (minVlera> abs (sinjal FrekuencaGuess-ruhetNoteFreq ))
{
minValue = abs (sinjal FrekuencaGuess-ruajturNoteFreq );
shënimLokacioni = i;
}
}
// Shtyp shënimin
Serial.print ("Unë mendoj se keni luajtur");
nëse (shënimLokacioni == 0)
{
Serial.print ("C");
}
tjetër nëse (shënimLokacioni == 1)
{
Serial.print ("C#");
}
tjetër nëse (shënimLokacioni == 2)
{
Serial.print ("D");
}
tjetër nëse (shënimLokacioni == 3)
{
Serial.print ("D#");
}
tjetër nëse (shënimLokacioni == 4)
{
Serial.print ("E");
}
tjetër nëse (shënimLokacioni == 5)
{
Serial.print ("F");
}
tjetër nëse (shënimLokacioni == 6)
{
Serial.print ("F#");
}
tjetër nëse (shënimLokacioni == 7)
{
Serial.print ("G");
}
tjetër nëse (shënimLokacioni == 8)
{
Serial.print ("G#");
}
tjetër nëse (shënimLokacioni == 9)
{
Serial.print ("A");
}
tjetër nëse (shënimLokacioni == 10)
{
Serial.print ("A#");
}
tjetër nëse (shënimLokacioni == 11)
{
Serial.print ("B");
}
Serial.println (varg oktava);
}
//*****************************************************************
//Ndalo ketu. Shtypni butonin e rivendosjes në Arduino për të rinisur
//*****************************************************************
ndërsa (1);
}

shikoni rawgistfile1.txt të pritur me ❤ nga GitHub

Hapi 3: Konfiguroni detektorin e shënimeve muzikore

Lidhni Arduino Uno me PC me kodin e shkruar ose të ngarkuar në Arduino IDE. Përpiloni dhe ngarkoni kodin në Arduino. Vendoseni qarkun pranë burimit të muzikës. Shënim: Në videon hyrëse, unë përdor një aplikacion të instaluar në tabletë në lidhje me altoparlantët e kompjuterit si burimi im i muzikës. Shtypni butonin e rivendosjes në Bordin Arduino dhe më pas luani një shënim në burimin e muzikës. Pas disa sekondash, Detektori i Shënimeve Muzikore do të shfaqë shënimin e luajtur dhe frekuencën e tij.