Երաժշտական նոտաների դետեկտոր `3 քայլ
Երաժշտական նոտաների դետեկտոր `3 քայլ
Anonim
Image
Image

Amazարմացրեք ձեր ընկերներին և ընտանիքին այս նախագծով, որը հայտնաբերում է գործիքի նվագարկումը: Այս նախագիծը կցուցադրի մոտավոր հաճախականությունը, ինչպես նաև երաժշտական նոտան, որը հնչում է էլեկտրոնային ստեղնաշարի, դաշնամուրի հավելվածի կամ որևէ այլ գործիքի վրա:

Մանրամասներ

Այս նախագծի համար ձայնային մոդուլի դետեկտորից անալոգային ելքն ուղարկվում է Arduino Uno- ի A0 անալոգային մուտքին: Անալոգային ազդանշանը նմուշառվում և քվանտացվում է (թվայնացված): Ավտոկորելացիայի, կշռման և կարգաբերման ծածկագիրը օգտագործվում է հիմնական հաճախականությունը գտնելու համար `օգտագործելով առաջին 3 շրջանները: Մոտավոր հիմնարար հաճախականությունը այնուհետև համեմատվում է 3, 4 և 5 օկտավաների տիրույթների հաճախականությունների հետ `որոշելու երաժշտական նոտայի ամենամոտ հաճախականությունը: Ի վերջո, ամենամոտ հաճախականության ենթադրվող գրառումը տպվում է էկրանին:

Նշում. Այս հրահանգը կենտրոնանում է միայն ծրագրի կառուցման վրա: Մանրամասների և նախագծման հիմնավորումների մասին լրացուցիչ տեղեկությունների համար այցելեք այս հղումը ՝ Լրացուցիչ տեղեկություններ

Պարագաներ

  • (1) Arduino Uno (կամ Genuino Uno)
  • (1) DEVMO խոսափողի սենսոր Բարձր զգայունության ձայնի հայտնաբերման մոդուլ Համատեղելի
  • (1) Եռակցման առանց տախտակ
  • (1) USB-A- ից B մալուխ
  • Jumper լարերը
  • Երաժշտական աղբյուր (դաշնամուր, ստեղնաշար կամ ցավազրկող ծրագիր բարձրախոսներով)
  • (1) համակարգիչ կամ նոութբուք

Քայլ 1. Կառուցեք սարքավորում երաժշտական նոտաների դետեկտորի համար

Կարգավորեք երաժշտական նշումների դետեկտորը
Կարգավորեք երաժշտական նշումների դետեկտորը

Arduino Uno- ի միջոցով միացման լարերը, առանց զոդման տախտակը և DEVMO խոսափողի սենսորը բարձր զգայունության ձայնի հայտնաբերման մոդուլը (կամ նմանատիպ) կառուցեք այս նկարում ցուցադրված միացումը

Քայլ 2. Programրագրեք երաժշտական նշումների դետեկտորը

Arduino IDE- ում ավելացրեք հետևյալ ծածկագիրը:

gistfile1.txt

/*
Ֆայլի/Էսքիզի անվանումը ՝ MusicalNoteDetector
Տարբերակ թիվ. V1.0 Ստեղծվել է 7 հունիսի, 2020 թ
Բնօրինակի հեղինակ ՝ Clyde A. Lettsome, PhD, PE, MEM
Նկարագրություն. Այս ծածկագիրը/ուրվագիծը ցուցադրում է մոտավոր հաճախականությունը, ինչպես նաև երաժշտական նոտան, որը հնչում է էլեկտրոնային ստեղնաշարի կամ դաշնամուրի հավելվածի վրա: Այս նախագծի համար անալոգային ելքը
ձայնային մոդուլի դետեկտորն ուղարկվում է Arduino Uno- ի A0 անալոգային մուտքին: Անալոգային ազդանշանը նմուշառվում և քվանտացվում է (թվայնացված): Ավտոկորելացիան, կշռման և թյունինգի կոդը օգտագործվում է
գտեք հիմնարար հաճախականությունը ՝ օգտագործելով առաջին 3 շրջանները: Մոտավոր հիմնարար հաճախականությունը համեմատվում է 3, 4 և 5 օկտավաների հաճախականությունների հետ `որոշելու ամենամոտ երաժշտական երաժշտությունը
նշումների հաճախականությունը: Ի վերջո, ամենամոտ հաճախականության ենթադրվող գրառումը տպվում է էկրանին:
Լիցենզիա. Այս ծրագիրը անվճար ծրագրակազմ է. կարող եք այն վերաբաշխել և/կամ փոփոխել այն GNU General Public License (GPL) 3 -րդ տարբերակի կամ ավելի ուշ
ձեր նախընտրած տարբերակը, ինչպես հրապարակել է Ազատ ծրագրային ապահովման հիմնադրամը:
Նշումներ. Հեղինակային իրավունք (գ) 2020 ՝ C. A. Lettsome Services, LLC
Լրացուցիչ տեղեկությունների համար այցելեք
*/
#սահմանել Նմուշներ 128 // Max 128 Arduino Uno- ի համար:
#սահմանել SAMPLING_FREQUENCY 2048 // Fs = Nyquist- ի հիման վրա պետք է լինի 2 անգամ սպասված ամենաբարձր հաճախականությունից:
#սահմանել OFFSETSAMPLES 40 // օգտագործվում է աղետաբեր նպատակների համար
#սահմանեք TUNER -3 // Կարգավորեք մինչև C3- ը լինի 130,50
բոց նմուշառումPամանակաշրջան;
անստորագիր երկար միկրովայրկյաններ;
int X [Նմուշներ]; // ստեղծել չափսերի վեկտոր `իրական արժեքներ պահելու համար
float autoCorr [Նմուշներ]; // ստեղծել նմուշների վեկտոր `երևակայական արժեքներ պահելու համար
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]; // ստեղծել օֆսեթ վեկտոր
int avgOffSet; // ստեղծել օֆսեթ վեկտոր
int i, k, periodEnd, periodBegin, period, adjustuster, noteLocation, octaveRange;
float maxValue, minValue;
երկար գումար;
int thresh = 0;
int numOfCycles = 0;
բոց ազդանշանՀաճախականություն, ազդանշանՀաճախականություն 2, ազդանշանՀաճախականություն3, ազդանշանՀաճախականությունԳուշակիր, ընդհանուր;
բայթ state_machine = 0;
int նմուշներPerPeriod = 0;
դատարկ կարգավորում ()
{
Serial.begin (115200); // 115200 Baud տոկոսադրույքը սերիական մոնիտորի համար
}
դատարկ շրջան ()
{
//*****************************************************************
// Calabration բաժին
//*****************************************************************
Serial.println ("Calabrating. Խնդրում ենք, որևէ գրառում մի կատարեք գնահատման ժամանակ:");
(i = 0; i <OFFSETSAMPLES; i ++)
{
անջատված է = analogRead (0); // Կարդում է անալոգային 0 (A0) արժեքը, քվանտացնում և պահում որպես իրական տերմին:
//Serial.println(offSet ); // օգտագործեք սա `ձայնի հայտնաբերման մոդուլը մոտավորապես կեսին կամ 512 -ին կարգավորելու համար, երբ ձայն չի հնչում:
sumOffSet = sumOffSet + offSet ;
}
samplePerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Պատրաստվեք ընդունելություն A0- ից
//*****************************************************************
avgOffSet = կլոր (sumOffSet / OFFSETSAMPLES);
Serial.println («Հետհաշվարկ»);
ուշացում (1000); // դադար 1 վայրկյան
Serial.println ("3");
ուշացում (1000); // դադար 1 վայրկյան
Serial.println ("2");
ուշացում (1000); // դադար 1 -ի համար
Serial.println ("1");
ուշացում (1000); // դադար 1 վայրկյան
Serial.println («Նվագարկեք ձեր գրառումը»);
ուշացում (250); // դադար 1/4 վայրկյան արձագանքի ժամանակի համար
//*****************************************************************
// Հավաքեք A0- ի նմուշներ նմուշառման ժամանակահատվածի նմուշառմամբ
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Pամանակահատվածը միկրո վայրկյաններում
համար (i = 0; i <Նմուշներ; i ++)
{
microSeconds = micros (); // Վերադարձնում է միկրովայրկյանների քանակը, քանի դեռ Arduino տախտակը սկսել է ընթացիկ սցենարի գործարկումը:
X = analogRead (0); // Կարդում է անալոգային 0 (A0) արժեքը, քվանտացնում և պահում որպես իրական տերմին:
/ *նմուշների միջև սպասման մնացած ժամանակը անհրաժեշտության դեպքում վայրկյանների ընթացքում */
իսկ (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// ոչինչ մի արա, պարզապես սպասիր
}
}
//*****************************************************************
// Ավտոկորելյացիայի գործառույթ
//*****************************************************************
համար (i = 0; i <Նմուշներ; i ++) // i = ուշացում
{
գումար = 0;
համար (k = 0; k <Նմուշներ - i; k ++) // Համապատասխանեցրեք ազդանշանը հետաձգված ազդանշանի հետ
{
գումար = գումար + ((((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] ազդանշանն է, իսկ X [k+i] ՝ հետաձգված տարբերակը
}
autoCorr = գումար / Նմուշներ;
// First Peak Detect State Machine
եթե (state_machine == 0 && i == 0)
{
thresh = autoCorr * 0.5;
պետական_մեքենա = 1;
}
այլապես, եթե (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, գտեք 1 շրջան առաջին ցիկլի օգտագործման համար
{
maxValue = autoCorr ;
}
այլապես, եթե (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
պետական_ մեքենա = 2;
numOfCycles = 1;
samplePerPeriod = (periodBegin - 0);
ժամանակաշրջան = samplePerPeriod;
կարգավորիչ = TUNER+(50.04 * exp (-0.102 * samplePerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-կարգավորիչ; // f = fs/N
}
այլապես, եթե (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, գտեք 2 շրջան 1 -ին և 2 -րդ ցիկլի համար
{
maxValue = autoCorr ;
}
այլապես, եթե (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
պետական_ մեքենա = 3;
numOfCycles = 2;
samplePerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-կարգավորիչ; // f = (2*fs)/(2*N)
maxValue = 0;
}
այլապես, եթե (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, գտեք 3 շրջան 1 -ին, 2 -րդ և 3 -րդ ցիկլի համար
{
maxValue = autoCorr ;
}
այլապես, եթե (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
պետական_ մեքենա = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-կարգավորիչ; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Արդյունքների վերլուծություն
//*****************************************************************
եթե (samplePerPeriod == 0)
{
Serial.println («Հմմ …… ես վստահ չեմ: Փորձու՞մ ես ինձ խաբել»);
}
ուրիշ
{
// պատրաստել քաշի գործառույթը
ընդամենը = 0;
եթե (ազդանշանՀաճախականություն! = 0)
{
ընդամենը = 1;
}
եթե (signalFrequency2! = 0)
{
ընդհանուր = ընդհանուր + 2;
}
եթե (signalFrequency3! = 0)
{
ընդհանուր = ընդհանուր + 3;
}
// հաշվարկել հաճախականությունը `օգտագործելով կշռման գործառույթը
signalFrequencyGuess = ((1/ընդհանուր) * signalFrequency) + ((2/ընդհանուր) * signalFrequency2) + ((3/ընդհանուր) * signalFrequency3); // գտնել կշռված հաճախականություն
Serial.print («Ձեր նվագած նոտան մոտավորապես»);
Serial.print (signalFrequencyGuess); // Տպեք հաճախականության գուշակությունը:
Serial.println («Հզ.»);
// գուշակության հիման վրա գտեք օկտավայի տիրույթ
octaveRange = 3;
մինչդեռ (! (signalFrequencyGuess> = պահվում է NotFreq [0] -7 && signalFrequencyGuess <= պահվում է NotFreq [11] +7))
{
համար (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
octaveRange ++;
}
// Գտեք ամենամոտ գրառումը
minValue = 10000000;
noteLocation = 0;
համար (i = 0; i <12; i ++)
{
եթե (minValue> abs)
{
minValue = abs (signalFrequencyGuess-storageNoteFreq );
noteLocation = i;
}
}
// Տպել նշումը
Serial.print («Կարծում եմ ՝ խաղացել ես»);
եթե (noteLocation == 0)
{
Serial.print («C»);
}
այլապես, եթե (noteLocation == 1)
{
Serial.print («C#»);
}
այլապես, եթե (noteLocation == 2)
{
Serial.print («D»);
}
այլապես, եթե (noteLocation == 3)
{
Serial.print ("D#");
}
այլապես, եթե (noteLocation == 4)
{
Serial.print («E»);
}
հակառակ դեպքում (noteLocation == 5)
{
Serial.print ("F");
}
այլապես, եթե (noteLocation == 6)
{
Serial.print ("F#");
}
այլապես, եթե (noteLocation == 7)
{
Serial.print ("G");
}
այլապես, եթե (noteLocation == 8)
{
Serial.print ("G#");
}
այլապես, եթե (noteLocation == 9)
{
Serial.print ("A");
}
այլապես, եթե (noteLocation == 10)
{
Serial.print ("A#");
}
հակառակ դեպքում (noteLocation == 11)
{
Serial.print («B»);
}
Serial.println (octaveRange);
}
//*****************************************************************
//Կանգնիր այստեղ. Վերագործարկելու համար սեղմեք Arduino- ի վերակայման կոճակը
//*****************************************************************
մինչդեռ (1);
}

դիտել rawgistfile1.txt- ը hosted -ի հետ GitHub- ի կողմից

Քայլ 3: Կարգավորեք երաժշտական նշումների դետեկտորը

Arduino Uno- ն միացրեք համակարգչին Arduino IDE- ում գրված կամ բեռնված ծածկագրով: Կազմեք և վերբեռնեք կոդը Arduino- ում: Շղթան տեղադրեք երաժշտության աղբյուրին մոտ: Նշում. Ներածական տեսանյութում ես օգտագործում եմ պլանշետի վրա տեղադրված ծրագիրը ՝ համակարգչի բարձրախոսների հետ միասին, որպես իմ երաժշտության աղբյուր: Հպեք Arduino- ի տախտակի վերակայման կոճակին, այնուհետև նվագարկեք երաժշտության աղբյուրի գրառումը: Մի քանի վայրկյան անց Երաժշտական նշումների դետեկտորը կցուցադրի նվագարկված գրառումը և դրա հաճախականությունը:

Խորհուրդ ենք տալիս: