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

Bir enstrümanın çaldığı notayı algılayan bu proje ile arkadaşlarınızı ve ailenizi şaşırtın. Bu proje, bir elektronik klavyede, piyano uygulamasında veya başka herhangi bir enstrümanda çalınan notaların yanı sıra yaklaşık frekansı da gösterecektir.

Detaylar

Bu proje için, ses modülü dedektöründen gelen analog çıkış, Arduino Uno'nun A0 analog girişine gönderilir. Analog sinyal örneklenir ve nicelenir (sayısallaştırılır). İlk 3 periyodu kullanarak temel frekansı bulmak için otokorelasyon, ağırlıklandırma ve ayar kodu kullanılır. Yaklaşık temel frekans daha sonra en yakın nota frekansını belirlemek için oktav 3, 4 ve 5 aralığındaki frekanslarla karşılaştırılır. Son olarak en yakın frekans için tahmin edilen not ekrana yazdırılır.

Not: Bu talimat yalnızca projenin nasıl oluşturulacağına odaklanır. Ayrıntılar ve tasarım gerekçeleri hakkında daha fazla bilgi için lütfen şu bağlantıyı ziyaret edin: Daha Fazla Bilgi

Gereçler

  • (1) Arduino Uno (veya Genuino Uno)
  • (1) DEVMO Mikrofon Sensörü Yüksek Hassasiyetli Ses Algılama Modülü Uyumlu
  • (1) Lehimsiz Breadboard
  • (1) USB-A - B Kablosu
  • Atlama telleri
  • Müzik kaynağı (hoparlörlü piyano, klavye veya ağrılı uygulama)
  • (1) Bilgisayar veya dizüstü bilgisayar

Adım 1: Nota Dedektörü Donanımını Oluşturun

Nota Dedektörünü Ayarlayın
Nota Dedektörünü Ayarlayın

Arduino Uno, bağlantı kabloları, lehimsiz devre tahtası ve DEVMO Mikrofon Sensörü Yüksek Hassasiyetli Ses Algılama Modülü (veya benzeri) kullanarak bu resimde gösterilen devreyi oluşturun.

Adım 2: Nota Dedektörünü Programlayın

Arduino IDE'de aşağıdaki kodu ekleyin.

gistfile1.txt

/*
Dosya/Çizim Adı: MusicalNoteDetector
Sürüm No.: v1.0 7 Haziran 2020'de düzenlendi
Orijinal Yazar: Clyde A. Lettsome, PhD, PE, MEM
Açıklama: Bu kod/çizim, bir elektronik klavyede veya piyano uygulamasında çalınan notanın yanı sıra yaklaşık frekansı da görüntüler. Bu proje için, analog çıkış
ses modülü dedektörü Arduino Uno'nun A0 analog girişine gönderilir. Analog sinyal örneklenir ve nicelenir (sayısallaştırılır). Otokorelasyon, ağırlıklandırma ve ayar kodu,
İlk 3 periyodu kullanarak temel frekansı bulun. Yaklaşık temel frekans daha sonra en yakın müzikal frekansı belirlemek için oktav 3, 4 ve 5 aralığındaki frekanslarla karşılaştırılır.
not sıklığı. Son olarak en yakın frekans için tahmin edilen not ekrana yazdırılır.
Lisans: Bu program ücretsiz bir yazılımdır; GNU Genel Kamu Lisansı (GPL) sürüm 3 veya daha sonraki herhangi bir şart altında yeniden dağıtabilir ve/veya değiştirebilirsiniz.
Özgür Yazılım Vakfı tarafından yayınlandığı şekliyle seçtiğiniz sürümü.
Notlar: Telif hakkı (c) 2020 by C. A. Lettsome Services, LLC
Daha fazla bilgi için https://clydelettsome.com/blog/2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/ adresini ziyaret edin.
*/
#define SAMPLES 128 //Arduino Uno için maksimum 128.
#define SAMPLING_FREQUENCY 2048 //Fs = Nyquist'e göre, beklenen en yüksek frekansın 2 katı olmalıdır.
#define OFSETSAMPLES 40 //kalibrasyon amacıyla kullanılır
#define TUNER -3 //C3 130.50 olana kadar ayarlayın
yüzer örneklemePeriod;
imzasız uzun microSeconds;
int X[ÖRNEKLER]; //gerçek değerleri tutmak için SAMPLES boyutunda vektör oluştur
float autoCorr[ÖRNEKLER]; //sanal değerleri tutmak için SAMPLES boyutunda vektör oluştur
float depolanmışNotFreq[12] = {130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94};
int toplamOffSet = 0;
int ofset[OFFSETSAMPLES]; // offset vektörü oluştur
int avgOffSet; // offset vektörü oluştur
int i, k, periodEnd, periodBegin, period, ayarlayıcı, noteLocation, octaveRange;
float maxValue, minValue;
uzun toplam;
int eşik = 0;
int numOfCycles = 0;
kayan sinyalFrekans, sinyalFrekans2, sinyalFrekans3, sinyalFrekansTahmin, toplam;
bayt durum_makinesi = 0;
int samplePeriod = 0;
geçersiz kurulum()
{
Seri.başla(115200); //115200 Seri Monitör için Baud hızı
}
boşluk döngüsü()
{
//*****************************************************************
//Kalibrasyon Bölümü
//*****************************************************************
Serial.println("Kalibrasyon yapılıyor. Lütfen kalibrasyon sırasında nota çalmayınız.");
için (i = 0; i < OFFSETSAMPLES; i++)
{
offSet = analogRead(0); //Analog pin 0'dan (A0) değeri okur, kuantize eder ve gerçek terim olarak kaydeder.
//Serial.println(offSet); //hiç ses çalınmadığında ses algılama modülünü yaklaşık olarak yarıya veya 512'ye ayarlamak için bunu kullanın.
sumOffSet = toplamOffSet + ofset;
}
samplePeriod = 0;
maxValue = 0;
//*****************************************************************
// A0'dan gelen girişi kabul etmeye hazırlanın
//*****************************************************************
avgOffSet = round(sumOffSet / OFFSETSAMPLES);
Serial.println("Geri sayım yapılıyor.");
gecikme(1000); // 1 saniye duraklat
Seri.println("3");
gecikme(1000); // 1 saniye duraklat
Seri.println("2");
gecikme(1000); // 1 için duraklat
Seri.println("1");
gecikme(1000); // 1 saniye duraklat
Serial.println("Notunuzu çalın!");
gecikme(250); //reaksiyon süresi için 1/4 saniye duraklat
//*****************************************************************
// SamplePeriod örnekleme periyodu ile A0'dan SAMPLES örnekleri toplayın
//*****************************************************************
samplePeriod = 1.0 / SAMPLING_FREQUENCY; //Mikrosaniye cinsinden süre
için (i = 0; i < ÖRNEKLER; i++)
{
mikroSaniye = mikros(); //Arduino kurulu mevcut betiği çalıştırmaya başladığından beri geçen mikrosaniye sayısını döndürür.
X = analogRead(0); //Analog pin 0'dan (A0) değeri okur, kuantize eder ve gerçek terim olarak kaydeder.
/*gerekirse örnekler arasında saniye cinsinden kalan bekleme süresi */
while (micros() < (microSeconds + (samplingPeriod * 1000000)))
{
//hiçbir şey yapma sadece bekle
}
}
//*****************************************************************
//Otokorelasyon Fonksiyonu
//*****************************************************************
for (i = 0; i < ÖRNEK; i++) //i=gecikme
{
toplam = 0;
for (k = 0; k < ÖRNEKLER - i; k++) // Sinyali gecikmeli sinyalle eşleştirin
{
toplam = toplam + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] sinyaldir ve X[k+i] gecikmeli versiyondur
}
autoCorr = toplam / ÖRNEKLER;
// İlk Tepe Algılama Durum Makinesi
if (durum_makinesi==0 && i == 0)
{
harman = autoCorr * 0,5;
durum_makinesi = 1;
}
else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, birinci döngüyü kullanmak için 1 nokta bulun
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodBaşlangıç = i-1;
durum_makinesi = 2;
numOfCycles = 1;
samplePerPeriod = (periodBegin - 0);
periyot = samplePeriod;
ayarlayıcı = TUNER+(50.04 * exp(-0.102 * samplePeriod));
sinyalFrekans = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-ayarlayıcı; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, 1. ve 2. döngü için 2 periyot bulun
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periyotBitiş = i-1;
durum_makinesi = 3;
numOfCycles = 2;
samplePerPeriod = (periodEnd - 0);
sinyalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-ayarlayıcı; // f = (2*fs)/(2*N)
maxValue = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, 1., 2. ve 3. döngü için 3 periyot bulun
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periyotBitiş = i-1;
durum_makinesi = 4;
numOfCycles = 3;
samplePerPeriod = (periodEnd - 0);
sinyalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-ayarlayıcı; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Sonuç Analizi
//*****************************************************************
if (samplesPeriod == 0)
{
Serial.println("Hmm….. Emin değilim. Beni kandırmaya mı çalışıyorsun?");
}
Başka
{
// ağırlıklandırma fonksiyonunu hazırla
toplam = 0;
if (sinyal Frekansı !=0)
{
toplam = 1;
}
if(sinyalFrekans2 !=0)
{
toplam = toplam + 2;
}
if (signalFrequency3 !=0)
{
toplam = toplam + 3;
}
//ağırlık fonksiyonunu kullanarak frekansı hesaplayın
sinyalFrekansTahmin = ((1/toplam) * sinyalFrekans) + ((2/toplam) * sinyalFrekans2) + ((3/toplam) * sinyalFrekans3; // ağırlıklı bir frekans bul
Serial.print("Çaldığınız nota yaklaşık olarak ");
Serial.print(signalFrequencyGuess); // Frekans tahminini yazdır.
Serial.println("Hz.");
// tahmine göre oktav aralığını bul
oktavaralığı=3;
while (!(signalFrequencyGuess >= depolanmışNoteFreq[0]-7 && signalFrequencyGuess <= depolanmışNoteFreq[11]+7))
{
for(i = 0; ben < 12; ben++)
{
depolananNotFreq = 2 * depolananNotFreq;
}
oktavaralığı++;
}
//En yakın notu bul
minDeğer = 10000000;
notKonum = 0;
için (i = 0; i < 12; i++)
{
if(minValue> abs(signalFrequencyGuess-storedNoteFreq))
{
minValue = abs(signalFrequencyGuess-storedNoteFreq);
notKonum = i;
}
}
//Notu yazdır
Serial.print("Sanırım oynadınız");
if(noteLocation==0)
{
Seri.print("C");
}
else if(noteLocation==1)
{
Serial.print("C#");
}
else if(noteLocation==2)
{
Seri.print("D");
}
else if(noteLocation==3)
{
Seri.print("D#");
}
else if(noteLocation==4)
{
Seri.print("E");
}
else if(noteLocation==5)
{
Seri.print("F");
}
else if(noteLocation==6)
{
Seri.print("F#");
}
else if(noteLocation==7)
{
Seri.print("G");
}
else if(noteLocation==8)
{
Serial.print("G#");
}
else if(noteLocation==9)
{
Seri.print("A");
}
else if(noteLocation==10)
{
Serial.print("A#");
}
else if(noteLocation==11)
{
Seri.print("B");
}
Serial.println(octaveRange);
}
//*****************************************************************
//Burada durun. Yeniden başlatmak için Arduino'daki sıfırlama düğmesine basın
//*****************************************************************
iken (1);
}

GitHub tarafından ❤ ile barındırılan rawgistfile1.txt dosyasını görüntüle

Adım 3: Müzik Notası Dedektörünü Kurun

Arduino IDE'ye yazılan veya yüklenen kod ile Arduino Uno'yu PC'ye bağlayın. Kodu derleyin ve Arduino'ya yükleyin. Devreyi müzik kaynağına yakın yerleştirin. Not: Tanıtım videosunda, müzik kaynağım olarak PC hoparlörleri ile birlikte tablette kurulu bir uygulama kullanıyorum. Arduino Board üzerindeki sıfırlama düğmesine basın ve ardından müzik kaynağında bir not çalın. Birkaç saniye sonra Müzik Nota Dedektörü çalınan notayı ve frekansını görüntüleyecektir.