Мазмуну:

Музыкалык нота детектору: 3 кадам
Музыкалык нота детектору: 3 кадам

Video: Музыкалык нота детектору: 3 кадам

Video: Музыкалык нота детектору: 3 кадам
Video: ЛОВИМ ВСЕХ??? Радиоприемник Tecsun pl368. Все диапазонный радиоприем 2024, Ноябрь
Anonim
Image
Image

Аспапта ойногон нотаны аныктоочу бул долбоор менен досторуңузду жана үй -бүлөңүздү таң калтырыңыз. Бул долбоор болжолдуу жыштыкты, ошондой эле электрондук клавиатурада, пианино колдонмосунда же башка аспапта ойногон музыкалык нотаны көрсөтөт.

Чоо -жайы

Бул долбоор үчүн үн модулунун детекторунан аналогдук чыгаруу Arduino Unoнун A0 аналогдук киришине жөнөтүлөт. Аналогдук сигнал үлгү алынат жана квантташтырылат (санариптештирилет). Автокорреляция, таразалоо жана тюнинг коду алгачкы 3 мезгилди колдонуу менен негизги жыштыкты табуу үчүн колдонулат. Эң жакын музыкалык нотанын жыштыгын аныктоо үчүн болжолдуу фундаменталдык жыштык 3, 4 жана 5 диапазондорундагы жыштыктар менен салыштырылат. Акырында эң жакын жыштыктагы божомол экранга басылат.

Эскертүү: Бул нускоочу долбоорду кантип курууга гана багытталган. Деталдар жана дизайн негиздемелери жөнүндө көбүрөөк маалымат алуу үчүн бул шилтемеге баш багыңыз: Көбүрөөк маалымат

Жабдуулар

  • (1) Arduino Uno (же Genuino Uno)
  • (1) DEVMO микрофону сенсорунун жогорку сезгичтиги үн аныктоо модулу шайкеш келет
  • (1) Solderless Breadboard
  • (1) USB-Aдан B кабелине
  • Өткөргүч зымдар
  • Музыкалык булак (фортепиано, клавиатура же спикерлери бар Paino колдонмосу)
  • (1) Компьютер же ноутбук

1 -кадам: Музыкалык нота детекторунун жабдууларын куруу

Музыкалык нота детекторун орнотуңуз
Музыкалык нота детекторун орнотуңуз

Arduino Uno, туташуу зымдары, ширетилбеген нан жана DEVMO микрофон сенсорунун жогорку сезгичтиги үн аныктоо модулун (же окшошторун) колдонуу менен бул сүрөттө көрсөтүлгөн схеманы түзүңүз.

2 -кадам: Музыкалык нота детекторун программалоо

Arduino IDEге төмөнкү кодду кошуңуз.

gistfile1.txt

/*
Файлдын/эскиздин аталышы: MusicalNoteDetector
Версия No.: V1.0 Түзүлгөн: 7 -июнь, 2020 -жыл
Түпнуска автор: Клайд А. Летсом, PhD, PE, MEM
Description: Бул код/эскиз болжолдуу жыштыкты, ошондой эле электрондук клавиатурада же пианино колдонмосунда ойнотулган музыкалык нотаны көрсөтөт. Бул долбоор үчүн аналогдук чыгаруу
үн модулунун детектору Arduino Unoнун A0 аналогдук киришине жөнөтүлөт. Аналогдук сигнал үлгү алынат жана квантташтырылат (санариптештирилет). Автокорреляция, салмак жана тюнинг коду колдонулат
алгачкы 3 мезгилди колдонуу менен негизги жыштыкты табыңыз. Болжолдуу фундаменталдык жыштык андан кийин 3, 4 жана 5 диапазондорундагы жыштыктарга салыштырылып, эң жакын музыкалык чыгарманы аныктайт.
эскертүү жыштыгы. Акырында эң жакын жыштыктагы божомол экранга басылат.
Лицензия: Бул программа бекер программа; аны кайра бөлүштүрүп жана/же GNU General Public License (GPL) 3 версиясынын шарттарына ылайык, же кийинчерээк өзгөртө аласыз
Free Software Foundation тарабынан тандалган версия.
Эскертүүлөр: Copyright (c) 2020 тарабынан C. A. Lettsome Services, LLC
Көбүрөөк маалымат алуу үчүн https://clydelettsome.com/blog/2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/ барыңыз
*/
#үлгүлөрдү 128 // Arduino Uno үчүн Max 128.
#аныктоо SAMPLING_FREQUENCY 2048 // Fs = Nyquistдин негизинде, күтүлгөн эң жогорку жыштыктан 2 эсе көп болушу керек.
#define OFFSETSAMPLES 40 // калибрлөө максатында колдонулат
#define TUNER -3 // C3 130.50 болгонго чейин тууралаңыз
float samplingPeriod;
кол коюлбаган узун микросекунддар;
int X [ҮЛГҮЛӨР]; // чыныгы баалуулуктарды кармоо үчүн SAMPLES өлчөмүндөгү векторду түзүңүз
калкып калуучу autoCorr [SAMPLES]; // ойдон чыгарылган баалуулуктарды кармоо үчүн SAMPLES өлчөмүндөгү векторду түзүңүз
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]; // офсет векторун түзүү
int avgOffSet; // офсет векторун түзүү
int i, k, periodEnd, periodBegin, мезгил, жөнгө салуучу, noteLocation, octaveRange;
float maxValue, minValue;
узун сумма;
int thresh = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
байт state_machine = 0;
int samplePerPeriod = 0;
жараксыз орнотуу ()
{
Serial.begin (115200); // Serial Monitor үчүн 115200 Baud rate
}
боштук цикл ()
{
//*****************************************************************
// Калабрация бөлүмү
//*****************************************************************
Serial.println ("Calabrating. Сураныч, калабрация учурунда эч кандай ноталарды ойнотпоңуз.");
үчүн (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = 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 секундга тыныгуу
//*****************************************************************
// SamplePeriodдун үлгүлүү мезгили менен A0 үлгүлөрүн чогултуу
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Период микросекундтарда
үчүн (i = 0; i <ҮЛГҮЛӨР; i ++)
{
microSeconds = micros (); // Arduino тактасы учурдагы скриптти иштете баштагандан берки микросекунддардын санын кайтарат.
X = analogRead (0); // 0 (A0) аналогдук пинден маанини окуйт, аны кванттап, чыныгы термин катары сактайт.
/ *керек болгон учурда үлгүлөрдүн ортосунда калган күтүү убактысы */
while (micros () <(microSeconds + (samplePeriod * 1000000)))
{
// эч нерсе кылба, жөн эле күт
}
}
//*****************************************************************
// Автокорреляция Функциясы
//*****************************************************************
үчүн (i = 0; i <ҮЛГҮЛӨР; i ++) // i = кечигүү
{
сумма = 0;
for (k = 0; k <SAMPLES - i; k ++) // Кечигүү сигналы менен дал келүү сигналы
{
сумма = сумма + ((((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] - сигнал жана X [k+i] - кечиктирилген версия
}
autoCorr = сумма / ҮЛГҮЛӨР;
// Биринчи чок мамлекеттик машинаны аныктайт
if (state_machine == 0 && i == 0)
{
бастыруу = autoCorr * 0.5;
state_machine = 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;
state_machine = 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, 1 жана 2 -цикл үчүн 2 мезгилди табыңыз
{
maxValue = autoCorr ;
}
башка болсо (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
state_machine = 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, 1, 2 жана 3 -цикл үчүн 3 мезгилди табыңыз
{
maxValue = autoCorr ;
}
башка болсо (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
state_machine = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-жөнгө салуучу; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Жыйынтык анализи
//*****************************************************************
эгерде (samplePerPeriod == 0)
{
Serial.println ("Хмм….. Мен так билбейм. Сиз мени алдап жатасызбы?");
}
башка
{
// салмактоо функциясын даярдоо
total = 0;
эгер (signalFrequency! = 0)
{
жалпы = 1;
}
эгер (signalFrequency2! = 0)
{
жалпы = жалпы + 2;
}
эгер (signalFrequency3! = 0)
{
жалпы = жалпы + 3;
}
// таразалоо функциясын колдонуп жыштыкты эсептөө
signalFrequencyGuess = ((1/total) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); // салмактуу жыштыкты табуу
Serial.print ("Сиз ойногон нота болжол менен");
Serial.print (signalFrequencyGuess); // Жыштык божомолун басып чыгаруу.
Serial.println ("Гц.");
// божомолдун негизинде октаванын диапазонун табуу
octaveRange = 3;
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7))
{
үчүн (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storedNoteFreq ;
}
octaveRange ++;
}
// Эң жакын нотаны табыңыз
minValue = 10000000;
noteLocation = 0;
үчүн (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
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догу баштапкы абалга келтирүү баскычын басыңыз
//*****************************************************************
while (1);
}

GitHub тарабынан ❤ менен хостинг rawgistfile1.txt көрүү

3 -кадам: Музыкалык нота детекторун орнотуңуз

Arduino Unoну Arduino IDEге жазылган же жүктөлгөн код менен компьютерге туташтырыңыз. Кодду түзүңүз жана Arduinoго жүктөңүз. Районду музыка булагына жакын коюңуз. Эскертүү: Киришүү видеосунда мен музыка булагы катары планшетке орнотулган колдонмону компьютердин динамиктери менен бирге колдоном. Arduino тактасындагы баштапкы абалга келтирүү баскычын басып, анан музыка булагына жазууну ойнотуңуз. Бир нече секунддан кийин музыкалык нота детектору ойнотулган нотаны жана анын жыштыгын көрсөтөт.

Сунушталууда: