Musiqili Not Detektoru: 3 addım
Musiqili Not Detektoru: 3 addım
Anonim
Image
Image

Bir alətin çaldığı notu algılayan bu layihə ilə dostlarınızı və ailənizi heyrətləndirin. Bu layihə, elektron klaviatura, fortepiano tətbiqi və ya hər hansı digər alətdə çalınan musiqili notun təxminən təxmini tezliyini göstərəcək.

Detallar

Bu layihə üçün səs modulu detektorundan analoq çıxış Arduino Uno -nun A0 analoq girişinə göndərilir. Analoq siqnal nümunə götürülür və kvantlaşdırılır (rəqəmləşdirilir). Avtokorrelyasiya, çəki və tənzimləmə kodu ilk 3 dövrdən istifadə edərək əsas tezliyi tapmaq üçün istifadə olunur. Təxmini əsas tezlik daha sonra ən yaxın musiqi notunun tezliyini təyin etmək üçün 3, 4 və 5 oktavalardakı tezliklər ilə müqayisə olunur. Nəhayət, ən yaxın tezlik üçün təxmin edilən qeyd ekranda çap olunur.

Qeyd: Bu təlimat yalnız layihənin necə qurulacağına yönəlmişdir. Detallar və dizayn əsaslandırmaları haqqında daha çox məlumat üçün bu linkə daxil olun: Ətraflı Məlumat

Təchizat

  • (1) Arduino Uno (və ya Genuino Uno)
  • (1) DEVMO Mikrofon Sensoru Yüksək Həssaslıq Səs Algılama Modulu Uyğundur
  • (1) Lehimsiz Çörək Paneli
  • (1) USB-A-B Kabeli
  • Jumper telləri
  • Musiqi mənbəyi (fortepiano, klaviatura və ya dinamikləri olan paino proqramı)
  • (1) Kompüter və ya dizüstü kompüter

Addım 1: Musiqili Not Detektoru üçün Avadanlıq qurun

Musiqili Not Detektorunu qurun
Musiqili Not Detektorunu qurun

Bir Arduino Uno, əlaqə telləri, lehimsiz çörək taxtası və DEVMO Mikrofon Sensoru Yüksək Həssaslıq Səs Algılama Modulu (və ya bənzəri) istifadə edərək bu şəkildə göstərilən dövrə qurun.

Addım 2: Musiqili Not Detektorunu proqramlaşdırın

Arduino IDE -də aşağıdakı kodu əlavə edin.

gistfile1.txt

/*
Fayl/Eskiz Adı: MusicalNoteDetector
Versiya No.: v1.0 7 İyun 2020 tarixində yaradılmışdır
Orijinal Müəllif: Clyde A. Lettsome, PhD, PE, MEM
Təsvir: Bu kod/eskiz, elektron klaviatura və ya fortepiano tətbiqində çalınan musiqi notunun təxmini tezliyini göstərir. Bu layihə üçün
səs modulu detektoru Arduino Uno'nun A0 analog girişinə göndərilir. Analoq siqnal nümunə götürülür və kvantlaşdırılır (rəqəmləşdirilir). Avtokorrelyasiya, çəki və tənzimləmə kodu istifadə olunur
ilk 3 dövrdən istifadə edərək əsas tezliyi tapın. Təxmini əsas tezlik daha sonra ən yaxın musiqini təyin etmək üçün 3, 4 və 5 oktavalı tezliklər ilə müqayisə olunur.
tezliyi qeyd edin. Nəhayət, ən yaxın tezlik üçün təxmin edilən qeyd ekranda çap olunur.
Lisenziya: Bu proqram pulsuz proqramdır; GNU General Public License (GPL) 3 -cü versiya və ya daha sonra onu yenidən paylaya və/və ya dəyişdirə bilərsiniz.
Pulsuz Proqram Vəqfi tərəfindən nəşr olunduğu kimi, seçdiyiniz versiyadır.
Qeydlər: Müəlliflik hüququ (c) 2020 tərəfindən C. A. Lettsome Services, LLC
Ətraflı məlumat üçün https://clydelettsome.com/blog/2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/ saytına daxil olun.
*/
#define NÜMUNƏLƏR 128 // Arduino Uno üçün Max 128.
#define SAMPLING_FREQUENCY 2048 // Fs = Nyquist əsasında, gözlənilən ən yüksək tezliyin 2 qatını təşkil etməlidir.
#define OFFSETSAMPLES 40 // kalabrasiya məqsədləri üçün istifadə olunur
#define TUNER -3 // C3 130.50 olana qədər tənzimləyin
float nümunə götürmə müddəti;
imzasız uzun microSeconds;
int X [NÜMUNƏLƏR]; // həqiqi dəyərləri saxlamaq üçün NÜMUNƏ ölçüsündə vektor yaradın
float autoCorr [NÜMUNƏLƏR]; // xəyali dəyərləri saxlamaq üçün SAMPLES ölçülü vektor yaradın
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]; // ofset vektoru yaradın
int avgOffSet; // ofset vektoru yaradın
int i, k, periodEnd, periodBegin, period, ayarlayıcı, noteLocation, octaveRange;
float maxValue, minValue;
uzun məbləğ;
int thresh = 0;
int numOfCycles = 0;
float siqnalıFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
bayt state_machine = 0;
int nümunələriPerPeriod = 0;
boş quraşdırma ()
{
Serial.begin (115200); // Serial Monitor üçün 115200 Baud dərəcəsi
}
boşluq döngəsi ()
{
//*****************************************************************
// Kalabrasiya Bölməsi
//*****************************************************************
Serial.println ("Calabrating. Zəhmət olmasa kalabrasiya zamanı heç bir qeyd oynamayın.");
üçün (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Dəyəri analoq pin 0 -dan (A0) oxuyur, kəmiyyətləndirir və real termin kimi saxlayır.
//Serial.println(offSet ); // heç bir səs çalınmadıqda səs aşkarlama modulunu təxminən yarısına və ya 512 -ə uyğunlaşdırmaq üçün istifadə edin.
sumOffSet = sumOffSet + offSet ;
}
nümunələrPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// A0 girişini qəbul etməyə hazırlaşın
//*****************************************************************
avgOffSet = yuvarlaq (sumOffSet / OFFSETSAMPLES);
Serial.println ("Geri saymaq.");
gecikmə (1000); // 1 saniyə ara verin
Serial.println ("3");
gecikmə (1000); // 1 saniyə ara verin
Serial.println ("2");
gecikmə (1000); // 1 dayan
Serial.println ("1");
gecikmə (1000); // 1 saniyə ara verin
Serial.println ("Qeydinizi oxuyun!");
gecikmə (250); // reaksiya müddəti üçün 1/4 saniyə ara verin
//*****************************************************************
// A0 -dan NÜMUNƏ nümunələri götürün, nümunə götürmə müddəti ilə
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Dövr mikrosaniyələrdə
üçün (i = 0; i <NÜMUNƏLƏR; i ++)
{
microSeconds = micros (); // Arduino lövhəsi cari skriptin işə salınmasından bəri mikrosaniyələrin sayını qaytarır.
X = analogRead (0); // Dəyəri analoq pin 0 -dan (A0) oxuyur, kəmiyyətləndirir və real termin kimi saxlayır.
/ *lazım gələrsə saniyələr ərzində nümunələr arasında qalan gözləmə müddəti */
while (micros () <(microSeconds + (samplePreiod * 1000000)))
{
// heç nə etmə, sadəcə gözlə
}
}
//*****************************************************************
// Avtokorrelyasiya funksiyası
//*****************************************************************
for (i = 0; i <NÜMUNƏLƏR; i ++) // i = gecikmə
{
cəmi = 0;
for (k = 0; k <NÜMUNƏLƏR - i; k ++) // Gecikmiş siqnalla uyğun siqnal
{
cəmi = cəmi + ((((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] siqnaldır və X [k+i] gecikmiş versiyadır
}
autoCorr = cəmi / NÜMUNƏLƏR;
// First Peak Detect State Machine
əgər (state_machine == 0 && i == 0)
{
harman = autoCorr * 0.5;
dövlət_maşın = 1;
}
başqa halda (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, birinci dövrənin istifadəsi üçün 1 dövr tapın
{
maxValue = autoCorr ;
}
başqa halda (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
dövlət_maşın = 2;
numOfCycles = 1;
samplePerPeriod = (periodBegin - 0);
dövr = nümunələrPerPeriod;
tənzimləyici = TUNER+(50.04 * exp (-0.102 * samplePerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplePerPeriod))-tənzimləyici; // f = fs/N
}
başqa halda (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, 1 -ci və 2 -ci dövr üçün 2 dövr tapın
{
maxValue = autoCorr ;
}
başqa halda (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
dövlət_maşın = 3;
numOfCycles = 2;
samplePerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-tənzimləyici; // f = (2*fs)/(2*N)
maxValue = 0;
}
başqa halda (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, 1, 2 və 3 -cü dövr üçün 3 dövr tapın
{
maxValue = autoCorr ;
}
başqa halda (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
dövlət_maşın = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplePerPeriod))-tənzimləyici; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Nəticələrin təhlili
//*****************************************************************
əgər (samplePerPeriod == 0)
{
Serial.println ("Hmm….. Mən əmin deyiləm. Məni aldatmaq istəyirsən?");
}
başqa
{
// ağırlıq funksiyasını hazırlayın
cəmi = 0;
əgər (siqnal Tezliyi! = 0)
{
cəmi = 1;
}
əgər (siqnalFrequency2! = 0)
{
cəmi = cəmi + 2;
}
if (signalFrequency3! = 0)
{
cəmi = cəmi + 3;
}
// ağırlıq funksiyasından istifadə edərək tezliyi hesablayın
signalFrequencyGuess = ((1/total) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); // ağırlıqlı bir tezlik tapın
Serial.print ("Oynadığınız not təxminəndir");
Serial. çap (signalFrequencyGuess); // Tezlik təxminini çap edin.
Serial.println ("Hz.");
// təxmin əsasında oktava aralığını tapın
oktav aralığı = 3;
isə (! (signalFrequencyGuess> = storageNoteFreq [0] -7 && signalFrequencyGuess <= saxlanılanNoteFreq [11] +7))
{
üçün (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
octaveRange ++;
}
// Ən yaxın notu tapın
minValue = 10000000;
noteLocation = 0;
üçün (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// Qeyd yazdırın
Serial.print ("Məncə sən oynamısan");
əgər (noteLocation == 0)
{
Serial.print ("C");
}
başqa halda (noteLocation == 1)
{
Serial.print ("C#");
}
başqa halda (noteLocation == 2)
{
Serial.print ("D");
}
başqa halda (noteLocation == 3)
{
Serial.print ("D#");
}
başqa halda (noteLocation == 4)
{
Serial.print ("E");
}
başqa halda (noteLocation == 5)
{
Serial.print ("F");
}
başqa halda (noteLocation == 6)
{
Serial.print ("F#");
}
başqa halda (noteLocation == 7)
{
Serial.print ("G");
}
başqa halda (noteLocation == 8)
{
Serial.print ("G#");
}
başqa halda (noteLocation == 9)
{
Serial.print ("A");
}
başqa halda (noteLocation == 10)
{
Serial.print ("A#");
}
başqa halda (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Burada dayan. Yenidən başlatmaq üçün Arduino -da sıfırlama düyməsini vurun
//*****************************************************************
isə (1);
}

GitHub tərəfindən ❤ ilə evlənən rawgistfile1.txt -ə baxın

Addım 3: Musiqili Not Detektorunu qurun

Arduino Une -ni Arduino IDE -də yazılmış və ya yüklənmiş kodla PC -yə qoşun. Kodu tərtib edin və Arduinoya yükləyin. Dövrəni musiqi mənbəyinə yaxın qoyun. Qeyd: Giriş videosunda, musiqi mənbəyim olaraq PC hoparlörləri ilə birlikdə tabletə quraşdırılmış bir tətbiqdən istifadə edirəm. Arduino lövhəsindəki sıfırlama düyməsini vurun və sonra musiqi mənbəyində qeyd edin. Bir neçə saniyə sonra Musiqili Not Detektoru çalınan notu və onun tezliyini göstərəcək.