İçindekiler:

Arduino Müzik Nota Dedektörü: 3 Adım
Arduino Müzik Nota Dedektörü: 3 Adım
Anonim
Image
Image

Özellikle Arduino'da sınırlı bellek ve işlem gücü nedeniyle müzik notalarını ses sinyalinden algılamak zordur. Genel olarak, not, algılamayı zorlaştıran saf bir sinüs dalgası değildir. Çeşitli müzik aletlerinin frekans dönüşümünü alırsak, çalınan notaya göre birden fazla harmonik içerebilir. Her enstrümanın çeşitli harmoniklerin kendi imza kombinasyonu vardır. Bu kodda olabildiğince çok enstrümanı kapsayabilecek bir program yapmaya çalıştım. Çeşitli enstrüman türlerini, klavye tarafından üretilen çeşitli tonları ve hatta vokal seslerini kontrol etmeye çalıştığım ekteki videoya bakabilirsiniz. Algılamanın doğruluğu cihazdan cihaza değişir. Sınırlı bir aralıkta (200-500Hz) bazı enstrümanlar (yani piyano) için doğru iken, bazı enstrümanlar için düşük doğruluğa sahiptir (yani Armonika).

Bu kod, EasyFFT adlı önceden geliştirilmiş bir FFT kodunu kullanır.

Kodun gösterimi yukarıdaki videoda vokalin yanı sıra çeşitli enstrüman sesleri ile gösterilmiştir.

Gereçler

- Arduino Nano/Uno veya üstü

- Arduino için mikrofon modülü

Adım 1: Not Algılama Algoritması

Önceki adımda belirtildiği gibi, ses örneklerinde birden fazla frekansın bulunması nedeniyle algılama zordur.

Program aşağıdaki akışta çalışır:

1. Veri toplama:

- bu bölüm ses verilerinden 128 örnek alır, ilgilenilen frekansa bağlı olarak iki örnek arasındaki ayrım (örnekleme frekansı). Bu durumda, genlik/RMS hesaplamasının yanı sıra Hann pencere fonksiyonunu uygulamak için kullanılan iki örnek arasındaki boşluk kullanıyoruz. Bu kod aynı zamanda analog okuma değerinden 500 çıkararak kaba sıfırlama yapar. Bu değer istenirse değiştirilebilir. Tipik bir durum için bu değerler iyi sonuç verir. Ayrıca, örnekleme frekansının 1200 Hz civarında olması için biraz gecikme eklenmesi gerekir. 1200Hz örnekleme frekansı durumunda maksimum 600 HZ frekansı tespit edilebilir.

for(int i=0;i<128;i++) { a=analogRead(Mic_pin)-500; //kaba sıfır kaydırma toplamı1=toplam1+a; //ortalama değere sum2=sum2+a*a; // RMS değerine a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann penceresi içinde=4*a; // float'tan int'e dönüştürme gecikmesi için ölçeklendirmeMicroseconds(195); // çalışma frekans aralığına göre }

2. FFT:

Veriler hazır olduğunda, EasyFFT kullanılarak FFT gerçekleştirilir. Bu EasyFFT işlevi, 128 örnek için FFT'yi düzeltmek üzere değiştirilir. Kod ayrıca bellek tüketimini azaltmak için değiştirilir. Sadece 128 örneğe ihtiyacımız varken, 1028 adede kadar örneğe (uyumlu kart ile) sahip olacak şekilde tasarlanmış orijinal EasyFFT işlevi. bu kod, orijinal EasyFFT işlevine kıyasla bellek tüketimini yaklaşık %20 oranında azaltır.

FFT yapıldıktan sonra kod, daha fazla analiz için en baskın 5 frekans tepe noktasını döndürür. Bu frekans, azalan genlik sırasına göre düzenlenmiştir.

3. Her tepe noktası için kod, onunla ilişkili olası notları algılar. bu kod yalnızca 1200 Hz'e kadar tarar. Maksimum genlikli frekans ile aynı nota sahip olmak gerekli değildir.

Tüm frekanslar 0 ile 255 arasında eşlenir, burada birinci oktav algılanır, örneğin 65.4 Hz ila 130.8 bir oktavı temsil eder, 130.8 Hz ila 261.6 Hz bir diğerini temsil eder. Her oktav için, frekanslar 0'dan 255'e haritalanır. Burada haritalama C'den C'ye başlar.

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 dizi değerleri, notu tespit edilen frekanslara atamak için kullanılır.

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

4. Her frekans için notayı hesapladıktan sonra, aynı notayı öneren birden fazla frekansın mevcut olması söz konusu olabilir. Doğru bir çıktı koduna sahip olmak, tekrarları da dikkate alır. Kod, genlik sırasına ve tekrarlara dayalı olarak tüm frekans değerlerini toplar ve notayı maksimum genlikle zirveye çıkarır.

2. Adım: Uygulama

Kodu kullanmak basittir, ancak bu sırada akılda tutulması gereken birden fazla sınırlama vardır. Not tespiti için kullanıldığı için kod kopyalanabilir. Kullanırken aşağıdaki noktalara dikkat edilmelidir.

1. Pin Ataması:

Ekli Pin atamasına göre değiştirilmesi gerekiyor. Deneyim için Analog pin 7'de tuttum, geçersiz kurulum() {Serial.begin(250000); Mic_pin = A7; }

2. Mikrofon hassasiyeti:

Mikrofon duyarlılığının modifiye edilmesi gerekir, bu tür dalga biçimleri iyi bir genlikle oluşturulabilir. Çoğunlukla, Mikrofon modülü bir hassasiyet ayarıyla birlikte gelir. sinyal ne çok küçük olacak ne de daha yüksek genlik nedeniyle kesilmeyecek şekilde seçilecek uygun hassasiyet.

3. Genlik eşiği:

Bu kod, yalnızca sinyal genliği yeterince yüksekse etkinleşir. bu ayarın kullanıcı tarafından manuel olarak ayarlanması gerekir. bu değer, uygulamanın yanı sıra mikrofon duyarlılığına da bağlıdır.

if(toplam2-toplam1>5){

..

yukarıdaki kodda toplam2 RMS değerini, toplam 1 ise ortalama değeri verir. dolayısıyla bu iki değer arasındaki fark ses sinyalinin genliğini verir. benim durumumda, yaklaşık 5 genlik değeriyle düzgün çalışıyor.

4. Varsayılan olarak, bu kod algılanan notu yazdıracaktır. ancak, notu başka bir amaçla kullanmayı planlıyorsanız, doğrudan atanan numara kullanılmalıdır. örneğin C=0;C#=1, D=2, D#=3 ve sonrası.

5. Cihaz daha yüksek frekansa sahipse, kod yanlış çıkış verebilir. maksimum frekans, örnekleme frekansı ile sınırlıdır. böylece optimum çıktı elde etmek için gecikme değerlerinin altında oynayabilirsiniz. 195 mikrosaniyelik kod gecikmesinde. optimum çıktı elde etmek için ince ayar yapılabilir. Bu, genel yürütme süresini etkileyecektir.

{ a=analogRead(Mic_pin)-500; // kaba sıfır kaydırma

toplam1=toplam1+a; //ortalama değere sum2=sum2+a*a; // RMS değerine a=a*(sin(i*3.14/128)*sin(i*3.14/128)); // Hann penceresi=4*a'da; // float'tan int'e dönüştürme gecikmesi için ölçeklendirmeMicroseconds(195); // çalışma frekans aralığına göre }

6. Bu kod sadece 2000Hz frekansına kadar çalışacaktır. Örnekleme arasındaki gecikmeyi ortadan kaldırarak 3-4 kHz civarında örnekleme frekansı elde edilebilir.

Önlemler:

  • EasyFFT eğitiminde belirtildiği gibi, FFT, Arduino'nun büyük miktarda belleğini tüketir. Bu nedenle, bazı değerleri kaydetmesi gereken bir programınız varsa, daha yüksek belleğe sahip bir kart kullanmanız önerilir.
  • Bu kod, bir enstrüman/vokalist için iyi çalışabilir ve bir diğeri için kötü olabilir. Gerçek zamanlı Doğru algılama, hesaplama sınırlamaları nedeniyle mümkün değildir.

3. Adım: Yazlık

Not tespiti, hesaplama açısından yoğun bir iştir, özellikle Arduino'da gerçek zamanlı çıktı almak çok zordur. Bu kod, yaklaşık 6.6 örnek/saniye verebilir (195 mikrosaniye gecikme eklendi). bu kod piyano ve diğer bazı enstrümanlarla iyi çalışır.

Umarım bu kod ve eğitim, müzikle ilgili projenizde yardımcı olur. Herhangi bir şüphe veya öneri durumunda yorum veya mesaj göndermekten çekinmeyin.

Bir sonraki derste, müzik akoru tespiti için bu kodu değiştireceğim. bu yüzden bizi izlemeye devam edin.

Önerilen: