Mündəricat:

Arduino Musiqi Notes Detektoru: 3 addım
Arduino Musiqi Notes Detektoru: 3 addım
Anonim
Image
Image

Səs siqnalı ilə musiqi notlarının aşkarlanması, xüsusən də məhdud yaddaş və işləmə gücü səbəbiylə Arduino'da etmək çətindir. Ümumiyyətlə, not, aşkarlamanı çətinləşdirən saf bir sinus dalğası deyil. Müxtəlif musiqi alətlərinin tezlik çevrilməsini götürsək, çalınan nota əsasən çoxlu harmoniklər ola bilər. Hər bir alətin müxtəlif harmoniklərdən ibarət öz imzası var. Bu kodda, mümkün qədər çox cihazı əhatə edə biləcək bir proqram hazırlamağa çalışdım. Müxtəlif növ alətləri, klaviatura tərəfindən yaradılan müxtəlif tonları və hətta vokalın səsini yoxlamağa çalışdığım əlavə edilmiş videoya müraciət edə bilərsiniz. Algılamanın dəqiqliyi alətdən alətə dəyişir. Məhdud bir diapazonda (200-500Hz) bəzi alətlər (yəni fortepiano) üçün dəqiqdir, bəzi alətlərdə isə dəqiqliyi aşağıdır (yəni Harmonica).

Bu kod, əvvəllər hazırlanmış EasyFFT adlı FFT kodundan istifadə edir.

Kodun nümayişi yuxarıdakı videoda müxtəlif növ alət səsləri və vokal ilə göstərilmişdir.

Təchizat

- Arduino Nano/Uno və ya yuxarıda

- Arduino üçün mikrofon modulu

Addım 1: Qeyd Algılama Alqoritmi

Əvvəlki addımda qeyd edildiyi kimi, səs nümunələrində çoxlu tezliklərin olması səbəbindən aşkarlanması çətindir.

Proqram aşağıdakı axınla işləyir:

1. Məlumat əldə etmə:

- bu bölmədə səs məlumatlarından 128 nümunə götürülür, maraq tezliyindən asılı olaraq iki nümunə arasında ayrılma (seçmə tezliyi). Bu vəziyyətdə, Hann pəncərə funksiyasını və amplituda/RMS hesablamasını tətbiq etmək üçün iki nümunə arasındakı boşluqdan istifadə edirik. Bu kod analoji dəyərdən 500 çıxarmaqla da kobud sıfırlama aparır. Lazım gələrsə bu dəyər dəyişdirilə bilər. Tipik bir vəziyyət üçün bu dəyərlər yaxşı işləyir. Əlavə olaraq, 1200Hz ətrafında bir nümunə götürmə tezliyinə sahib olmaq üçün bəzi gecikmələrin əlavə edilməsi lazımdır. 1200 Hz nümunə götürmə halında, maksimum 600 HZ tezliyi aşkar edilə bilər.

for (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // kobud sıfır keçid sum1 = sum1+a; // orta dəyərə sum2 = sum2+a*a; // RMS dəyərinə a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // Hann pəncərəsi = 4*a; // float to int dönüşüm gecikdirmə ölçüsü Mikrosaniyələr (195); // əməliyyat tezliyi aralığına əsasən}

2. FFT:

Məlumat hazır olduqdan sonra FFT EasyFFT istifadə edərək həyata keçirilir. Bu EasyFFT funksiyası 128 nümunə üçün FFT -ni düzəltmək üçün dəyişdirilmişdir. Yaddaş istehlakını azaltmaq üçün kod da dəyişdirildi. Orijinal EasyFFT funksiyası 1028 nümunəyə (uyğun lövhə ilə) sahib olmaq üçün nəzərdə tutulmuşdur, halbuki bizə yalnız 128 nümunə lazımdır. Bu kod, orijinal EasyFFT funksiyası ilə müqayisədə yaddaş istehlakını təxminən 20% azaldır.

FFT edildikdən sonra, kod daha çox analiz üçün ən çox üstünlük təşkil edən 5 tezlik zirvəsini qaytarır. Bu tezlik amplituda azalan qaydada düzülmüşdür.

3. Hər bir zirvə üçün kod, onunla əlaqəli mümkün qeydləri aşkar edir. Bu kod yalnız 1200 Hz -ə qədər tarar. Maksimum amplituda olan tezliklə eyni qeydə ehtiyac yoxdur.

Bütün tezliklər 0 -dan 255 -ə qədər ölçülür.

burada ilk oktav aşkarlanır, məsələn, 65.4 Hz - 130.8 bir oktavanı, 130.8 Hz - 261.6 Hz digərini təmsil edir. Hər bir oktava üçün tezliklər 0 -dan 255 -ə qədər xəritələnir. Burada C -dən C -ə qədər olan xəritələmə.

if (f_peaks > 1040) {f_peaks = 0;} if (f_peaks > = 65.4 && f_peaks = 130.8 && f_peaks = 261.6 && f_peaks = 523.25 && f_peaks = 1046 && f_peaks <= 2093) {f_peaks = 255*((f_peaks /1046) -1);}

NoteV array dəyərləri notu aşkarlanan tezliklərə təyin etmək üçün istifadə olunur.

bayt NoteV [13] = {8, 23, 40, 57, 76, 96, 116, 138, 162, 187, 213, 241, 255};

4. Hər bir tezlik üçün notu hesabladıqdan sonra, eyni qeydi təklif edən çoxlu tezliklərin olması mümkündür. Düzgün bir çıxış koduna sahib olmaq üçün təkrarlamalar da nəzərə alınır. Kod, amplitüd sırasına və təkrarlarına əsaslanan bütün tezlik dəyərlərini əlavə edir və maksimum amplituda olan notu zirvəyə qaldırır.

Addım 2: Tətbiq

Koddan istifadə etmək düzdür, bununla yanaşı, eyni zamanda nəzərə alınmalı olan bir çox məhdudiyyətlər də var. Kod qeydlərin aşkarlanması üçün istifadə edildiyi üçün kopyalana bilər. İstifadə edərkən aşağıdakı məqamlar nəzərə alınmalıdır.

1. Pin Təyinatı:

Əlavə edilən Pin tapşırığına əsasən dəyişdirilməlidir. Təcrübəm üçün Analog pin 7 -də saxladım, void setup () {Serial.begin (250000); Mic_pin = A7; }

2. Mikrofon həssaslığı:

Mikrofonun həssaslığının dəyişdirilməsi lazımdır, belə bir dalğa forması yaxşı amplituda ilə yaradıla bilər. Əsasən, Mikrofon modulu həssaslıq ayarı ilə gəlir. siqnalın nə çox kiçik olması, nə də yüksək amplituda görə kəsilməməsi üçün uyğun həssaslıq.

3. Genlik həddi:

Bu kod yalnız kifayət qədər yüksək olduqda siqnal amplitudası olduqda aktivləşir. bu parametr istifadəçi tərəfindən əl ilə təyin olunmalıdır. Bu dəyər mikrofonun həssaslığından və tətbiqindən asılıdır.

əgər (sum2-sum1> 5) {

..

yuxarıdakı kodda sum2 RMS dəyərini verir, cəmi 1 orta dəyər verir. buna görə bu iki dəyər arasındakı fərq səs siqnalının amplitüdünü verir. mənim vəziyyətimdə, 5 ətrafında bir amplituda dəyəri ilə düzgün işləyir.

4. Varsayılan olaraq, bu kod aşkar edilmiş notu çap edəcək. lakin qeyddən başqa məqsəd üçün istifadə etməyi planlaşdırırsınızsa, birbaşa təyin olunmuş nömrədən istifadə edilməlidir. məsələn C = 0; C#= 1, D = 2, D#= 3 və irəli.

5. Alətin daha yüksək tezliyi varsa, kod yanlış çıxış verə bilər. maksimum tezlik seçmə tezliyi ilə məhdudlaşır. beləliklə, optimal çıxış əldə etmək üçün gecikmə dəyərlərinin altında oynaya bilərsiniz. Aşağıdakı kod gecikməsində 195 mikrosaniyə. optimal çıxışı əldə etmək üçün dəyişdirilə bilər. Bu ümumi icra müddətinə təsir edəcək.

{a = analogRead (Mic_pin) -500; // kobud sıfır sürüşmə

sum1 = sum1+a; // orta dəyərə sum2 = sum2+a*a; // RMS dəyərinə a = a*(sin (i*3.14/128)*sin (i*3.14/128)); // Hann pəncərəsi = 4*a; // float to int dönüşüm gecikdirmə ölçüsü Mikrosaniyələr (195); // əməliyyat tezliyi aralığına əsasən}

6. bu kod yalnız 2000Hz tezliyə qədər işləyəcək. nümunə götürmə arasındakı gecikməni aradan qaldıraraq 3-4 kHz ətrafında nümunə götürmə tezlikləri əldə edilə bilər.

Ehtiyat tədbirləri:

  • EasyFFT dərsliyində qeyd edildiyi kimi, FFT Arduinonun böyük bir yaddaşını yeyir. Bəzi dəyərləri saxlamağa ehtiyacı olan bir proqramınız varsa, daha yüksək yaddaşlı bir lövhədən istifadə etməyiniz məsləhətdir.
  • Bu kod bir alət/vokalçı üçün yaxşı işləyə bilər, digəri üçün pis ola bilər. Hesablama məhdudiyyətləri səbəbindən real vaxtda dəqiq təsbit mümkün deyil.

Addım 3: Yaz

Qeydlərin aşkarlanması hesablama baxımından sıx bir işdir, xüsusən də Arduinoda real vaxt çıxışı əldə etmək çox çətindir. Bu kod təxminən 6,6 nümunə /saniyə verə bilər (195 mikrosaniyə gecikmə əlavə edildi). Bu kod piano və digər alətlərlə yaxşı işləyir.

Ümid edirəm ki, bu kod və dərslik musiqi ilə bağlı layihənizdə faydalı olacaq. hər hansı bir şübhə və ya təklifiniz varsa şərh və ya mesaj göndərməkdən çekinmeyin.

Qarşıdakı dərsdə, musiqi akkordunun aşkarlanması üçün bu kodu dəyişdirəcəyəm. buna görə də izləmədə qalın.

Tövsiyə: