• Tidak ada hasil yang ditemukan

HASIL DAN PEMBAHASAN

4.1 Pengujian Program Pengenalan Nada Alat Musik Suling Menggunakan Fungsi Jarak Chebyshev

4.1.1. Tombol Pengenalan

Tombol Pengenalan hanya dapat ditekan setelah user mengisi pengaturan pengenalan. Untuk mengetahui pengaturan pengenalan sudah diisi atau belum maka dilakukan pengecekan dengan menjalankan metode berikut:

///////////COMBOBOX CHECKER///////////////////////////////// int Alpha=0;

int NoAlpha=0;//for database call if (m_alpha==_T("1000"))

{Alpha=1000; NoAlpha=12;} ....

else

{MessageBox(_T("Pilihlah nilai Alpha yang akan digunakan terlebih dahulu."),_T("Peringatan"),MB_OK|MB_ICONEXCLAMATION);

return;}

Jika pada saat pengecekan berlangsung dan didapatkan pengaturan pengenalan yang belum terisi, maka program akan memberikan pesan seperti pada Gambar 4.5 dan Gambar 4.6. Tetapi jika pengaturan telah terisi, maka program akan melanjutkan ke proses selanjutnya.

Gambar 4.5. Pesan Bila Pengaturan Alpha Tidak Terisi

Gambar 4.6. Pesan Bila Pengaturan FFT Tidak Terisi

Selanjutnya program akan memberikan waktu kepada user untuk bersiap memainkan alat musik suling recordernya selama 3 detik dengan metode:

m_statimag.SetBitmap(stat2); Sleep(1000);

///

//////////////////////////////////////////////////////////// int NpointFFT=0;

int NoFast=0;//for database call if (m_fftpoint==_T("16")) {NpointFFT=16; NoFast=0;} else if(m_fftpoint==_T("32")) {NpointFFT=32; NoFast=1;} else if(m_fftpoint==_T("64")) {NpointFFT=64; NoFast=2;} else if(m_fftpoint==_T("128")) {NpointFFT=128; NoFast=3;} else

{MessageBox(_T("Pilihlah nilai point of FFT yang akan digunakan terlebih dahulu."),_T("Peringatan"),MB_OK|MB_ICONEXCLAMATION);

return;}

User dapat mengetahui waktu yang tersisa melalui tampilan status yang ada pada tampilan program seperti pada Gambar 4.7.

Gambar 4.7. Tampilan STATUS Menunggu Perekaman

Proses Perekaman akan dimulai jika tampilan status yang terdapat pada tampilan utama program terlihat seperti Gambar 4.8.

Gambar 4.8. Tampilan STATUS Mulai Perekaman

Persiapan untuk proses perekaman diawali dengan menginisialisasikan parameter perekaman dengan metode berikut:

///////////perekaman//////////////////////////////////////////// UpdateData(true);

unsigned int samplerate = 2400; int bit = 16; const int NUMPTS = 4800; short *waveIn;

int datarekam[4800]; ///4800=2 detik dengan 1 detiknya 2400sample HWAVEIN hWaveIn; WAVEHDR WaveInHdr; MMRESULT result; WAVEFORMATEX pFormat; pFormat.wFormatTag=WAVE_FORMAT_PCM; pFormat.nChannels=1; pFormat.nSamplesPerSec=samplerate; pFormat.wBitsPerSample=bit; pFormat.nAvgBytesPerSec=samplerate * pFormat.wBitsPerSample /8; pFormat.nBlockAlign=pFormat.nChannels * pFormat.wBitsPerSample /8; pFormat.cbSize=0; m_statimag.SetBitmap(stat3); Sleep(1000); /// m_statimag.SetBitmap(stat4); Sleep(1000);

Metode diatas digunakan untuk mengkonfigurasi data dari sinyal suara yang akan direkam. Pada metode tersebut, konfigurasi dilakukan dengan menentukan parameter perekaman, seperti sample rate, format suara, channel, bit per sample, AvgBytesPerSec, dan BlockAlign.

AvgBytesPerSec merupakan rata-rata kecepatan transfer data dalam byte untuk tiap detik. Nilai ini digunakan untuk menentukan ukuran dari buffer. Persamaan 4.1 merupakan rumusan untuk menentukan nilai AvgBytesPerSec.

𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴𝐴 =𝐴𝐴𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝐴𝐴𝐴𝐴𝑆𝑆𝐴𝐴𝐴𝐴π‘₯π‘₯𝑏𝑏𝑏𝑏𝐴𝐴𝑆𝑆𝐴𝐴𝐴𝐴𝐴𝐴𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝐴𝐴/8 (4.1) BlockAlign merupakan nilai dari ukuran data dalam byte untuk tiap sample. Persamaan 4.2 merupakan rumusan untuk nilai BlockAlign.

𝐴𝐴𝑆𝑆𝐡𝐡𝐴𝐴𝐡𝐡𝐴𝐴𝑆𝑆𝑏𝑏𝐴𝐴𝐡𝐡 =πΆπΆβ„Žπ‘†π‘†π΅π΅π΅π΅π΄π΄π‘†π‘†π΄π΄π‘ π‘ π‘†π‘†π΄π΄π‘†π‘†π‘₯π‘₯𝑏𝑏𝑏𝑏𝐴𝐴𝑆𝑆𝐴𝐴𝐴𝐴𝐴𝐴𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝑆𝐴𝐴/8(𝑏𝑏𝐴𝐴𝐴𝐴𝐴𝐴) (4.2)

Metode diatas digunakan untuk menentukan struktur dari buffer. Buffer adalah memori yang disiapkan sebagai tempat penyimpanan sementara data hasil perekaman suara. Pada metode di atas, pengaturan persiapan buffer terdiri atas:

a. Pengalokasian memori penyimpan data hasil perekaman suara berupa pointer dengan menuliskan wavein = new short [NUMPTS].

b. Pendeklarasian variabel pointer dilakukan dengan menuliskan

waveinhdr.lpdata = (LPSTR) wavein.

c. Penentuan panjang buffer dilakukan dengan menuliskan

waveinhdr.dwbufferlength = NUMPTS * pformat.wbitspersample / 8. d. Penginisialisasian awal data yang terdapat pada buffer dilakukan dengan

menuliskan waveinhdr.dwbytesrecorded=0. Nilai 0 mengartikan buffer dalam keadaan kosong pada saat awal perekaman.

e. Penginisialisasian variabel dwuser dilakukan dengan menuliskan

waveinhdr.dwuser=0L. Nilai 0L sama artinya dengan nilai 0. //pengaturan header buffer perekaman

waveIn = new short [NUMPTS];

WaveInHdr.lpData = (LPSTR) waveIn;

WaveInHdr.dwBufferLength = NUMPTS * pFormat.wBitsPerSample / 8; WaveInHdr.dwBytesRecorded=0;

WaveInHdr.dwUser=0L; WaveInHdr.dwFlags=0L; WaveInHdr.dwLoops=0L;

f. Penginisialisasian variabel dwflags dilakukan dengan menuliskan waveinhdr.dwflags=0L. Nilai 0L dimaksudkan bahwa tidak menggunakan flag sebagai informasi tambahan pada buffer.

g. Penginisialisasian variabel dwloops dilakukan dengan menuliskan

waveinhdr.dwloops=0L. Nilai 0L dimaksudkan bahwa pengulangan proses perekaman tidak dilakukan, hanya 1 kali proses perekaman.

Membuka perangkat suara dengan metode berikut:

Mempersiapkan buffer untuk penyimpanan sementara data hasil perekaman dengan metode berikut:

Memulai proses perekaman dengan metode berikut:

dan menunggu sampai perekaman selesai dengan metode seperti dibawah dan tampilan status seperti pada Gambar 4.9.

Gambar 4.9. Tampilan STATUS Perekaman Selesai

Mengambil data pada buffer untuk disimpan pada variabel dengan metode berikut:

Mem-plot data hasil rekaman pada grafik dengan metode berikut: ///////////Ploting rekam//////////////////

double SampleDataArray1[4800]; for(int i=0 ; i<2000 ; i++)

SampleDataArray1[ i ] = datarekam[i*2];

Scope.Channels[0].Data.SetYData(SampleDataArray1,2000); //ambil data perekaman

for(long i=0;i<NUMPTS;i++) {datarekam[i]=*waveIn; waveIn++;}

do {} while (waveInUnprepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR))==WAVERR_STILLPLAYING);

waveInReset(hWaveIn); waveInStart(hWaveIn);

waveInAddBuffer(hWaveIn,&WaveInHdr,sizeof(WAVEHDR));

Setelah proses perekaman, program akan memproses data hasil perekaman untuk pemilihan data tengah dari deretan data hasil perekaman. Proses yang disebut frame blocking ini menggunakan metode:

Selanjutnya data hasil frame blocking akan melalui proses windowing untuk menghilangkan noise suara yang ikut terekam dalam proses perekaman. Dalam program pengenalan ini alpha yang digunakan untuk mengatur windowing bervariasi dan user dapat menggunakan 4 varian alpha yang terdapat pada combo box. pengecekan hasil pilihan dari user sudah dilakukan sebelum proses perekaman berlangsung. Windowing yang digunakan adalah Kaiser window dimana menggunakan beta untuk komputasinya. Perolehan nilai beta tergantung dari alpha yang dipilih user. Dalam perhitungan nilai beta menggunakan metode:

Setelah nilai beta diperoleh maka proses Kaiser dapat dilakukan. Metode yang digunakan dalam proses Kaiser windowing menggunakan metode yang didapat dari koders.com. Metode tersebut dimodifikasi sehingga menjadi:

///////////kaiser window/////////////////////////////////////// // diambil dari ::koders.com /// // filename ::window.cpp /// /////////////////////////////////////////////////////////////// //brief bessel function for kaiser window

const double t=1.e-08; double y=0.5*Beta; double e=1.0; double de=1.0; double xi; double sde;

for (int i=1;i<26;i++){ xi=i; de *= y/xi; ///pilihan Beta if (Alpha>50) {Beta=0.1102*(Alpha-8.7);} else if (Alpha<21) {Beta=0;} else {Beta=0.5842* pow((Alpha-21),0.4)+0.07886*(Alpha-21);} ////////////frame blocking////////////////////////////////////// //pilih data

int LFrame=128;//banyak data yang dipilih

int StartFrame=(4800/2)-LFrame;//mulai frame dari StartFrame int NadFB[128]; int f=StartFrame; //fungsi frame for(long i=0;i<LFrame;i++) {NadFB[i]=datarekam[f+i];} ////////////////////////////////////////////////////////////////

Setelah proses windowing selesai dilakukan maka program akan menjalankan proses normalisasi dengan metode:

Selanjutnya program menjalankan inisialisasi variabel yang akan digunakan dalam proses FFT sebagai berikut:

///////////Normalisasi///////////////////////////////////////// double MaksNadWin=0;

double Norml[128];

for(int i=0 ;i<128;i++){

MaksNadWin=max(MaksNadWin,abs(NadWin[i]));} for(int i=0 ;i<128;i++){

Norml[i]=NadWin[i]/MaksNadWin;} ////////////////////////////////////////////////////////////// sde = de*de; e += sde; if((e*t-sde)>0)break;} double bessel1=e;

//brief kaiser window

double KaiserWin[128];//KaiserWin[panjang window atau LFrame] double bes=1.0/bessel1;

long odd=LFrame%2; double xo;

double xind=(LFrame-1)*(LFrame-1); for (int i=0;i<LFrame;i++){

if(odd) xo=i+0.5; else xo=i; xo=4*xo*xo; //bessel2 y=0.5*(Beta*sqrt(1.-xo/xind)); e=1.0; de=1.0; for (int g=1;g<26;g++){ xi=g; de *= y/xi; sde = de*de; e += sde; if((e*t-sde)>0)break;} double bessel2=e; KaiserWin[i]=bessel2*bes; } double window[128]; //left side window int cp=LFrame/2;

for (int i=0;i<cp;i++){

window[i]=KaiserWin[cp-i-1];} for (int i=0;i<cp;i++){

window[cp+i]=KaiserWin[i];} //end of kaiser window

double NadWin[128];

for(int i=0;i<LFrame;i++){

Proses FFT dibutuhkan data complex untuk perhitungannya, sedangkan data yang dihasilkan proses normalisasi 1 adalah data real. Program menjalankan proses untuk mengonversi data real menjadi data complex sehingga dapat dilakukan proses perhitungan FFT dengan metode:

Selanjutnya data yang sudah dikonversi menjadi data complex diproses dengan metode FFT yang didapat dari metode Danielson Lanzcos routine sebagai berikut:

//////////////////////////FFT//////////////////////////// // diambil dari ::codeprojects.com // // thread name ::how to make fft // // di posting oleh ::Joao Martins // ///////////////////////////////////////////////////////// //binary inversion (note that the indexes

//start from 0 witch means that the

//real part of the complex is on the even-indexes //and the complex part is on the odd-indexes) n=sample_rate << 1; j=0; for (i=0;i<n/2;i+=2) { if (j > i) { SWAP(vector[j],vector[i]); SWAP(vector[j+1],vector[i+1]); if((j/2)<(n/4)){ SWAP(vector[(n-(i+2))],vector[(n-(j+2))]); SWAP(vector[(n-(i+2))+1],vector[(n-(j+2))+1]); }} m=n >> 1; while (m >= 2 && j >= m) { j -= m; m >>= 1;} j += m;}

//new complex array of size n=2*sample_rate //if(vector!=NULL)

// delete [] vector;

vector=new double [2*sample_rate]; nadFFT=new double [sample_rate];

//put the real array in a complex array //the complex part is filled with 0's

//the remaining vector with no data is filled with 0's if (NpointFFT==16) {for(n=0; n < 16 ;n++) {if(n < 16) vector[2*n]=Norml[n]; else vector[2*n]=0; vector[2*n+1]=0;}} ... else

{MessageBox(_T("tidak dapat mengonvert ke bilangan

complex"),_T("Peringatan"),MB_OK|MB_ICONEXCLAMATION); return;}

Data hasil perhitungan proses FFT merupakan data yang masih complex dan tidak dapat digunakan untuk proses fungsi jarak. data complex harus dikonversi menjadi data real sehingga dapat diproses dalam proses fungsi jarak. program menjalankan metode konversi yang dimodifikasi dengan penambahan fungsi normalisasi sebagai berikut:

Setelah data real diperoleh maka program menjalankan metode dibawah ini untuk menampilkan grafik hasil FFT nada suara uji.

/////////////////////PLOTING FFT///////////////////// switch(NoFast){ case 0: SFourier.Channels[0].Data.SetYData(Norml2,16); break; ... default:

MessageBox(_T("Tidak dapat memplotting hasil FFT") ,_T("Gagal") ,MB OK|MB ICONEXCLAMATION);}

double MaksNadFFT=0; double *Norml2; if (NpointFFT==16) {

for(i=0; i<=(32); i+=2)

nadFFT[i/2]=sqrt((pow(vector[i],2)+pow(vector[i+1],2))); Norml2=new double[16];

for(int i=0 ;i<16;i++){ ///////Normalisasi 2//////// MaksNadFFT=max(MaksNadFFT,abs(nadFFT[i]));} for(int i=0 ;i<16;i++){

Norml2[i]=nadFFT[i]/MaksNadFFT;}} .... //Danielson-Lanzcos routine mmax=2; while (n > mmax) { istep=mmax << 1; theta=(2*pi/mmax); wtemp=sin(0.5*theta); wpr = -2.0*wtemp*wtemp; wpi=sin(theta); wr=1.0; wi=0.0; for (m=1;m<mmax;m+=2) { for (i=m;i<=n;i+=istep) { j=i+mmax; tempr=wr*vector[j-1]-wi*vector[j]; tempi=wr*vector[j]+wi*vector[j-1]; vector[j-1]=vector[i-1]-tempr; vector[j]=vector[i]-tempi; vector[i-1] += tempr; vector[i] += tempi; } wr=(wtemp=wr)*wpr-wi*wpi+wr; wi=wi*wpr+wtemp*wpi+wi; } mmax=istep; }

Selanjutnya program menjalankan proses menghitung jarak menggunakan metode:

Variabel ref2 merupakan pointer variabel yang akan dibandingkan didapat melalui pemanggilan data referensi melalui metode:

Dalam proses penentuan nada hasil jarak terpendek dibandingkan dengan perolehan jarak dari masing-masing nada referensi. Jika jarak terpendek sama nilainya dengan salah satu jarak pada nada referensi, maka nada dikenali adalah salah satu nada sesuai dengan nada referensi. Penentuan nada ini menggunakan metode:

Hasil penentuan akan muncul pada tampilan STATUS program pengenalan nada alat musik suling recorder seperti pada Tabel 4.1.

Berdasarkan pengujian, tombol PENGENALAN telah bekerja dengan baik. Saat tombol PENGENALAN ditekan, program telah merekam, menampilkan grafik rekaman, menampilkan grafik hasil FFT, menampilkan hasil jarak masing-masing nada, dan mengenali nada. Gambar 4.10 memperlihatkan contoh tampilan setelah tombol PENGENALAN ditekan, dengan nada yang dimainkan adalah nada Sol/ G’, pengaturan berupa alpha pada windowing sebesar 1000, dan FFT sebesar 128 point. Grafik pertama adalah hasil sampling nada suara uji, grafik kedua adalah hasil FFT nada suara uji, dan tampilan STATUS sesuai dengan nilai jarak minimum yang berada pada text box jarak Sol(G’). ////////////////////PENENTUAN NADA//////////////////////// double jarakminimum=1; for(i=0;i<7.2;i++) {jarakminimum=min(jarakminimum,jarak[i]);} if (jarakminimum>0.70) {m_statimag.SetBitmap(nadaNN);} else if (jarakminimum==jarak[0]) {m_statimag.SetBitmap(nadaC);} .... if(d==0) {ref2=NadaCRef6;} .... for(k=0;k<32;k++){dist[k]=Norml2[k]-ref2[k];} for(k=0;k<32;k++){jarak[d]=max(jarak[d],dist[k]);}

Tabel 4.1. Tampilan STATUS Nada Yang Dikenali

No. STATUS Keterangan

1. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Do/ C’.

2. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Re/ D’.

3. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Mi/ E’.

4. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Fa/ F’.

5. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Sol/ G’.

6. Nada yang dikenali dari jarak

minimum yang didapat adalah nada La/ A’.

7. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Si/ B’.

8. Nada yang dikenali dari jarak

minimum yang didapat adalah nada Do tinggi/ C”.

Gambar 4.10. Tampilan Setelah Penekanan Tombol PENGENALAN.

Dokumen terkait