Daftar Isi:

Detektor Catatan Musik: 3 Langkah
Detektor Catatan Musik: 3 Langkah

Video: Detektor Catatan Musik: 3 Langkah

Video: Detektor Catatan Musik: 3 Langkah
Video: 3 Bocah Terlindas Truk Saat Selfie Di Atas Motor 2024, Juli
Anonim
Image
Image

Buat kagum teman dan keluarga Anda dengan proyek ini yang mendeteksi nada yang dimainkan oleh instrumen. Proyek ini akan menampilkan perkiraan frekuensi serta not musik yang dimainkan pada keyboard elektronik, aplikasi piano, atau instrumen lainnya.

rincian

Untuk proyek ini, output analog dari detektor modul suara dikirim ke input analog A0 dari Arduino Uno. Sinyal analog diambil sampelnya dan dikuantisasi (digitisasi). Autokorelasi, pembobotan dan kode tuning digunakan untuk mencari frekuensi fundamental menggunakan 3 periode pertama. Perkiraan frekuensi dasar kemudian dibandingkan dengan frekuensi dalam rentang oktaf 3, 4, dan 5 untuk menentukan frekuensi not musik terdekat. Akhirnya catatan tebakan untuk frekuensi terdekat dicetak ke layar.

Catatan: Instruksi ini hanya berfokus pada bagaimana membangun proyek. Untuk informasi lebih lanjut tentang detail dan justifikasi desain, silakan kunjungi tautan ini: Informasi Lebih Lanjut

Perlengkapan

  • (1) Arduino Uno (atau Genuino Uno)
  • (1) Sensor Mikrofon DEVMO Kompatibel dengan Modul Deteksi Suara Sensitivitas Tinggi
  • (1) Papan tempat memotong roti tanpa solder
  • (1) Kabel USB-A ke B
  • Kabel jumper
  • Sumber musik (piano, keyboard, atau aplikasi paino dengan speaker)
  • (1) Komputer atau laptop

Langkah 1: Bangun Perangkat Keras untuk Detektor Catatan Musik

Siapkan Detektor Catatan Musik
Siapkan Detektor Catatan Musik

Menggunakan Arduino Uno, kabel koneksi, papan tempat memotong roti tanpa solder, dan Modul Deteksi Suara Sensitivitas Tinggi Sensor Mikrofon DEVMO (atau serupa) membuat sirkuit yang ditunjukkan pada gambar ini

Langkah 2: Program Detektor Catatan Musik

Di Arduino IDE, tambahkan kode berikut.

gistfile1.txt

/*
Nama File/Sketsa: MusicalNoteDetector
Versi No.: v1.0 Dibuat 7 Juni 2020
Penulis Asli: Clyde A. Lettsome, PhD, PE, MEM
Deskripsi: Kode/sketsa ini menampilkan perkiraan frekuensi serta not musik yang dimainkan pada keyboard elektronik atau aplikasi piano. Untuk proyek ini, output analog dari
detektor modul suara dikirim ke input analog A0 dari Arduino Uno. Sinyal analog diambil sampelnya dan dikuantisasi (digitisasi). Autokorelasi, pembobotan, dan kode penyetelan digunakan untuk
cari frekuensi dasar menggunakan 3 periode pertama. Perkiraan frekuensi dasar kemudian dibandingkan dengan frekuensi dalam rentang oktaf 3, 4, dan 5 untuk menentukan musik terdekat
frekuensi catatan. Akhirnya catatan tebakan untuk frekuensi terdekat dicetak ke layar.
Lisensi: Program ini adalah perangkat lunak bebas; Anda dapat mendistribusikan ulang dan/atau memodifikasinya di bawah persyaratan GNU General Public License (GPL) versi 3, atau yang lebih baru
versi pilihan Anda, sebagaimana diterbitkan oleh Free Software Foundation.
Catatan: Hak Cipta (c) 2020 oleh C. A. Lettsome Services, LLC
Untuk informasi lebih lanjut kunjungi
*/
#define SAMPLES 128 //Max 128 untuk Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Fs = Berdasarkan Nyquist, harus 2 kali frekuensi tertinggi yang diharapkan.
#define OFFSETSAMPLES 40 //digunakan untuk tujuan kalibrasi
#define TUNER -3 //Sesuaikan hingga C3 adalah 130.50
periode sampling mengambang;
microSeconds panjang yang tidak ditandatangani;
int X[SAMPEL]; //buat vektor ukuran SAMPEL untuk menampung nilai nyata
float autoCorr[SAMPEL]; //buat vektor dengan ukuran SAMPEL untuk menampung nilai imajiner
float tersimpanNoteFreq[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]; //membuat vektor offset
int avgOffSet; //membuat vektor offset
int i, k, periodEnd, periodBegin, period, adjuster, noteLocation, octaveRange;
float maxValue, minValue;
jumlah panjang;
int ambang = 0;
int jumlah Siklus = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte state_machine = 0;
int sampelPerPeriod = 0;
batalkan pengaturan()
{
Serial.begin(115200); //115200 Baud rate untuk Serial Monitor
}
lingkaran kosong()
{
//*****************************************************************
//Bagian Kalibrasi
//*****************************************************************
Serial.println("Calabration. Harap tidak memainkan not apapun selama kalibrasi.");
untuk (i = 0; i < OFFSETSAMPLES; i++)
{
offSet = analogRead(0); //Membaca nilai dari pin analog 0 (A0), kuantisasi dan simpan sebagai suku nyata.
//Serial.println(offSet); //gunakan ini untuk menyesuaikan modul deteksi suara menjadi sekitar setengah atau 512 saat tidak ada suara yang diputar.
sumOffSet = sumOffSet + offSet;
}
sampelPerPeriode = 0;
nilai maks = 0;
//*****************************************************************
//Bersiaplah untuk menerima masukan dari A0
//*****************************************************************
avgOffSet = bulat(sumOffSet / OFFSETSAMPLES);
Serial.println("Menghitung mundur.");
penundaan (1000); //jeda selama 1 detik
Serial.println("3");
penundaan (1000); //jeda selama 1 detik
Serial.println("2");
penundaan (1000); //jeda untuk 1
Serial.println("1");
penundaan (1000); //jeda selama 1 detik
Serial.println("Mainkan catatanmu!");
penundaan (250); //jeda selama 1/4 detik untuk waktu reaksi
//*****************************************************************
//Kumpulkan sampel SAMPEL dari A0 dengan periode sampel Periode pengambilan sampel
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; //Periode dalam mikrodetik
untuk (i = 0; i < SAMPEL; i++)
{
mikrodetik = mikro(); //Mengembalikan jumlah mikrodetik sejak papan Arduino mulai menjalankan skrip saat ini.
X = analogRead(0); //Membaca nilai dari pin analog 0 (A0), kuantisasi dan simpan sebagai suku nyata.
/*sisa waktu tunggu antar sampel jika perlu dalam hitungan detik */
while (micros() < (microSeconds + (samplingPeriod * 1000000))))
{
// tidak melakukan apa-apa, tunggu saja
}
}
//*****************************************************************
//Fungsi Autokorelasi
//*****************************************************************
untuk (i = 0; i < SAMPEL; i++) //i=delay
{
jumlah = 0;
for (k = 0; k < SAMPLES - i; k++) //Mencocokkan sinyal dengan sinyal tertunda
{
jumlah = jumlah + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] adalah sinyal dan X[k+i] adalah versi tertunda
}
autoCorr = jumlah / SAMPEL;
// Mesin Status Deteksi Puncak Pertama
if (state_machine==0 && i == 0)
{
ambang = autoCorr * 0,5;
negara_mesin = 1;
}
else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, cari 1 periode untuk menggunakan siklus pertama
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodeMulai = i-1;
negara_mesin = 2;
numOfCycles = 1;
sampelPerPeriod = (periodBegin - 0);
periode = sampelPeriode;
pengatur = TUNER+(50,04 * exp(-0,102 * sampelPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-adjuster; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, cari 2 periode untuk siklus 1 dan 2
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodeEnd = i-1;
negara_mesin = 3;
numOfCycles = 2;
sampelPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-adjuster; // f = (2*fs)/(2*N)
nilai maks = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, cari 3 periode untuk siklus 1, 2 dan 3
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodeEnd = i-1;
negara_mesin = 4;
numOfCycles = 3;
sampelPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-adjuster; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Analisis Hasil
//*****************************************************************
jika (sampelPerPeriod == 0)
{
Serial.println("Hmm….. Saya tidak yakin. Apakah Anda mencoba menipu saya?");
}
lain
{
//siapkan fungsi pembobotan
jumlah = 0;
jika (frekuensi sinyal !=0)
{
jumlah = 1;
}
jika(sinyalFrekuensi2 !=0)
{
jumlah = jumlah + 2;
}
jika (sinyalFrekuensi3 !=0)
{
jumlah = jumlah + 3;
}
//hitung frekuensi menggunakan fungsi pembobotan
signalFrequencyGuess = ((1/total) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); //menemukan frekuensi berbobot
Serial.print("Catatan yang Anda mainkan kira-kira ");
Serial.print(signalFrequencyGuess); // Cetak tebakan frekuensi.
Serial.println("Hz.");
//menemukan rentang oktaf berdasarkan tebakan
rentang oktaf=3;
while (!(signalFrequencyGuess >= storedNoteFreq[0]-7 && signalFrequencyGuess <= storedNoteFreq[11]+7))
{
untuk(i = 0; i < 12; i++)
{
disimpanNoteFreq = 2 * disimpanNoteFreq;
}
rentang oktaf++;
}
//Temukan catatan terdekat
minNilai = 10000000;
catatanLokasi = 0;
untuk (i = 0; i < 12; i++)
{
if(minValue> abs(signalFrequencyGuess-storedNoteFreq))
{
minValue = abs(signalFrequencyGuess-storedNoteFreq);
catatanLokasi = i;
}
}
//Cetak catatan
Serial.print("Saya pikir Anda bermain ");
jika(catatanLokasi==0)
{
Serial.print("C");
}
lain jika(catatanLocation==1)
{
Serial.print("C#");
}
lain jika (catatanLocation==2)
{
Serial.print("D");
}
lain jika(catatanLocation==3)
{
Serial.print("D#");
}
lain jika (catatanLocation==4)
{
Serial.print("E");
}
lain jika (catatanLocation==5)
{
Serial.print("F");
}
lain jika (catatanLocation==6)
{
Serial.print("F#");
}
lain jika(catatanLocation==7)
{
Serial.print("G");
}
lain jika (catatanLocation==8)
{
Serial.print("G#");
}
lain jika(catatanLocation==9)
{
Serial.print("A");
}
lain jika (catatanLocation==10)
{
Serial.print("A#");
}
lain jika (catatanLocation==11)
{
Serial.print("B");
}
Serial.println(Rentang oktaf);
}
//*****************************************************************
//Berhenti disini. Tekan tombol reset pada Arduino untuk memulai kembali
//*****************************************************************
sementara (1);
}

lihat rawgistfile1.txt yang dihosting dengan ❤ oleh GitHub

Langkah 3: Siapkan Detektor Catatan Musik

Hubungkan Arduino Uno ke PC dengan kode yang ditulis atau dimuat di Arduino IDE. Kompilasi dan unggah kode ke Arduino. Tempatkan sirkuit dekat dengan sumber musik. Catatan: Dalam video pengantar, saya menggunakan aplikasi yang diinstal di tablet bersama dengan speaker PC sebagai sumber musik saya. Tekan tombol reset pada Papan Arduino dan kemudian mainkan nada pada sumber musik. Setelah beberapa detik, Musical Note Detector akan menampilkan not yang dimainkan dan frekuensinya.

Direkomendasikan: