Monday, 6 April 2015

DELPHI7 :: Pembacaan File WAV di delphi7



Struktur File WAV

Format file wav merupakan bagian dari spesifikasi RIFF milik Microsoft yang digunakan untuk penyimpanan file-file multimedia. File wav dimulai dengan bagian header dan diikuti oleh rentetan data chunk. File wav terdiri dari 3 bagian, yaitu main chunk, format chunk, dan data chunk.
Sinyal suara yang direpresentasikan file wav dalam bentuk discrete, berupa deret bilangan yang merepresentasikan amplitudo dalam domain waktu. Pada bagian file header terdapat informasi tentang file wav tersebut, diantaranya menyatakan nilai sample rate, jumlah channel, dan bit per sample. Dari keterangan pada file header tersebut dapat diketahui berapa sampel yang dicuplik dari sinyal analog tiap detik. Struktur WAV dapat dilihat pada Gambar di bawah ini :

  1. Bagian Main Chunk
    • ChunkID : berisi kata “RIFF” dalam format ASCII.
    • ChunkSize : berisi informasi ukuran chunk.
    • Format : berisi kata “WAVE”.
  2. Bagian Format Chunk
    • SubChunk1ID : berisi kata “fmt”.
    • SubChunk1Size : berisi informasi ukuran subchunk1
    • c. AudioFormat : informasi jenis kompresi data chunk. Misalnya bernilai 1 untuk kompresi PCM.
    • NumChannels : banyaknya channel. Misal: Mono=1, Stereo=2.
    • SampleRate : sample rate dari file wav, misal 8000 untuk 8000Hz, 44100 untuk 44100 Hz.
    • ByteRate : banyaknya byte tiap detik. ByteRate = SampleRate x NumChannels x BitsPerSample / 8.
    • BitsPerSample : ukuran bits untuk tiap sampel.Misal: 8 bit = 8
  3. Bagian Data Chunk
    • SubChunk2ID : berisi kata “data”.
    • SubChunk2Size : berisi informasi ukuran subchunk2. SubChunk2Size = NumSamples x NumChannels x BitsPerSample / 8. NumSamples = (DataByte / NumChannels) / BitsPerSample.
    • Data : Data suara aktual dalam byte, merepresentasi-kan amplitudo tiap sampel dari sinyal.

Proses Pembacaan File WAV di Delphi 7:

Pada dasarnya bahasa pemrograman delphi sudah mempunyai kelas untuk dapat membaca suatu file yang berekstensi *.wav. Membuat struktur data dan variabel global untuk digunakan pada prosedur pembacaan file wav. Berikut ini merupakan source code program pembacaan file wav pada bahasa pemrograman delphi 7 :
  1. Written By Adhitya A P (0510960002)  
  2. Student of Computer Science in Brawijaya University  
  3. Indonesia}  
  4.   
  5. unit Unit1;  
  6.   
  7. interface  
  8.   
  9. uses  
  10. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  11. Dialogs, StdCtrls, TeEngine, Series, ExtCtrls, TeeProcs, Chart;  
  12.   
  13. type  
  14. TWaveHeader = packed record  
  15.  { harus bernilai 'RIFF' }  
  16.  Marker_RIFF: array [0..3of char;  
  17.  ChunkSize: cardinal;  
  18.   
  19.  { harus bernilai 'WAVE' }  
  20.  Marker_WAVE: array [0..3of char;  
  21.   
  22.  { harus bernilai 'fmt ' }  
  23.  Marker_fmt: array [0..3of char;  
  24.  SubChunkSize: cardinal;  
  25.   
  26.  { 
  27.    Audio Format see mmsystem.pas 
  28.    1 : WAVE_FORMAT_PCM 
  29.  }  
  30.  FormatTag: word;  
  31.   
  32.  { nChannels : 1 jika mono, 2 jika stereo }  
  33.  NumChannels: word;  
  34.  SampleRate: longint;  
  35.  BytesPerSecond: longint;  
  36.  BytesPerSample: word;  
  37.  BitsPerSample: word;  
  38.   
  39.  { Harus bernilai 'data' }  
  40.  Marker_data: array [0..3of char;  
  41.   
  42.  { Jumlah seluruh sampel dalam byte }  
  43.  DataBytes: longint;  
  44. end;  
  45.   
  46. TChannel = record  
  47.  { 
  48.    tiap sample dinyatakan sebagai signed integer 
  49.    berukuran 16-bit (2 byte). 
  50.    tipe data ini pada delphi adalah smallint 
  51.    yang memiliki nilai dalam jangkauan -32767..32768 
  52.  }  
  53.  Data : array of smallint;  
  54. end;  
  55.   
  56. type  
  57. TForm1 = class(TForm)  
  58.  Memo1: TMemo;  
  59.  Button1: TButton;  
  60.  Button2: TButton;  
  61.  Chart1: TChart;  
  62.  Series1: TFastLineSeries;  
  63.  Chart2: TChart;  
  64.  Series2: TFastLineSeries;  
  65.  procedure Button1Click(Sender: TObject);  
  66.  procedure Button2Click(Sender: TObject);  
  67. private  
  68.  { Private declarations }  
  69.  wavehdr : TWaveHeader;  
  70.  wavedata : array [0..1of TChannel;  
  71.  numsamples : integer;  
  72. public  
  73.  { Public declarations }  
  74.  procedure GetInfoWav(filename : string);  
  75. end;  
  76.   
  77. var  
  78. Form1: TForm1;  
  79. nFrame : Integer;  
  80. implementation  
  81.   
  82. {$R *.dfm}  
  83.   
  84. procedure TForm1.GetInfoWav(filename : string);  
  85. var  
  86. tmpstr : string;  
  87. i : integer;  
  88. Stream : TFileStream;  
  89. begin  
  90. Stream := TFileStream.Create(filename, fmOpenRead);  
  91.   
  92. FillChar(wavehdr, sizeof(wavehdr), 0);  
  93. Stream.Read(wavehdr, sizeof(wavehdr));  
  94.   
  95. { Log Header data }  
  96. with memo1.Lines do begin  
  97.  Add('Bagian Main Chunk');  
  98.  Add('Header size : '+inttostr(sizeof(wavehdr)));  
  99.  tmpstr := wavehdr.Marker_RIFF;  
  100.  Add('Chunk ID : '+tmpstr+''' ');  
  101.  Add('Chunk size : '+inttostr(wavehdr.ChunkSize));  
  102.  tmpstr := wavehdr.Marker_WAVE;  
  103.  Add('Format : '+tmpstr+''' ');  
  104.  tmpstr := wavehdr.Marker_fmt;  
  105.  Add('');  
  106.  Add('Bagian Format Chunk');  
  107.  Add('SubChunk ID : '+tmpstr+''' ');  
  108.  Add('SubChunk size : '+inttostr(wavehdr.SubChunkSize));  
  109.  Add('Audio Format : '+inttostr(wavehdr.FormatTag));  
  110.  Add('Num Channels : '+inttostr(wavehdr.NumChannels));  
  111.  Add('Sample rate : '+inttostr(wavehdr.SampleRate));  
  112.  Add('Bytes rate : '+inttostr(wavehdr.BytesPerSecond));  
  113.  Add('Bits per sample : '+inttostr(wavehdr.BitsPerSample));  
  114.  numsamples := (wavehdr.DataBytes div wavehdr.NumChannels) div wavehdr.BytesPerSample;  
  115.  tmpstr := wavehdr.Marker_data;  
  116.  Add('');  
  117.  Add('Bagian Data Chunk');  
  118.  Add('SubChunk2 ID : '+tmpstr+''' ');  
  119.  Add('SubChunk2 Size : '+IntToStr(Round(wavehdr.NumChannels*numsamples*wavehdr.BytesPerSample/8)));  
  120.  Add('Data Length : '+inttostr(wavehdr.DataBytes));  
  121. end;  
  122.   
  123. { Log data amplitudo }  
  124. case wavehdr.NumChannels of  
  125.    1:begin  
  126.      SetLength(wavedata[0].Data, numsamples);  
  127.      Stream.Read(wavedata[0].Data[0], numsamples);  
  128.    end;  
  129.   
  130.    2:begin  
  131.      SetLength(wavedata[0].Data, numsamples);  
  132.      SetLength(wavedata[1].Data, numsamples);  
  133.      for i := 0 to high(wavedata[0].Data) do begin  
  134.        Stream.Read(wavedata[0].Data[i], 2);  
  135.        Stream.Read(wavedata[1].Data[i], 2);  
  136.        //Memo1.Lines.Add('Nilai ke-'+IntToStr(i+1)+' = \tLeft : '+IntToStr(round(wavedata[0].Data[i]))+' Right : '+IntToStr(round(wavedata[1].Data[i])));  
  137.      end;  
  138.    end;  
  139. end;  
  140.   
  141. Memo1.Lines.Add('Nilai Amplitudo : ');  
  142. for i := 0 to high(wavedata[0].Data)do  
  143. Memo1.Lines.Add('Nilai ke-'+IntToStr(i+1)+' = \tLeft : '+IntToStr(round(wavedata[0].Data[i]))+' Right : '+IntToStr(round(wavedata[1].Data[i])));  
  144. end;  
  145. Memo1.Lines.Add('');  
  146.   
  147. { inisialisasi ulang }  
  148. Stream.Free;  
  149. end;  
  150.   
  151. //tombol proses pembacaan  
  152. procedure TForm1.Button1Click(Sender: TObject);  
  153. var i: Integer;  
  154. begin  
  155. Memo1.Clear;  
  156. GetInfoWav('arif10.wav');  
  157.   
  158. //pembuatan grafik  
  159. Series1.Clear;  
  160. for i:=0 to high(wavedata[0].Data) do  
  161.  Series1.AddXY(i, round(wavedata[0].Data[i]), '', clTeeColor);  
  162.   
  163.   
  164. Series2.Clear;  
  165. for i:=0 to high(wavedata[0].Data) do  
  166.  Series2.AddXY(i, round(wavedata[1].Data[i]), '', clTeeColor);  
  167. end;  
  168.   
  169. //tombol bersihkan layar  
  170. procedure TForm1.Button2Click(Sender: TObject);  
  171. begin  
  172. Memo1.Clear;  
  173. Series1.Clear;  
  174. Series2.Clear;  
  175. end;  
  176.   
  177. end.  

Hasil tampilan program :

Download source code lengkapnya disini

No comments:

Post a Comment