經過前幾次BMP及GIF的作業之後,對於這次讀WAV的檔案資料就會先假設 : 是不是WAV也跟BMP及GIF的讀檔一樣呢?的確。而要先讀檔案的頭檔就要先找到他的BYTE是怎麼分配的,Resource Interchange File Format :wave wav byte的資料在維基百科好難找,好不容易才找到有說明所有頭檔byte的網頁。不過還是有許多討論區發表過類似的文章Delphi.ktop,查資料的能力真的要好,不然時間都花在上面真的很吃不消。
=================================
bytes # contains
0-3 4 "RIFF" in ASCII
4-7 4 Total bytes minus 8
8-15 4+4 "WAVE fmt" Eigth character is a space
16-19 4 16 for PCM format
20-21 2 for PCM format
22-23 2 channels
24-27 4 sampling frequency
28-31 4 bytes per second
32-33 2 bytes by capture
34-35 2 bits per sample
36-39 4 "data"
40-43 4 int4 bytes in data
===================================
頭檔byte總算到手,接下來把頭檔讀入在顯示出來就不是難事了。以下是我程式的設計界面與執行結果。程式是集合了前幾次的作業慢慢堆出來的,也修改了前次的介面讓他更乾淨俐落。合併BMP的灰階影像元件,新增BMP影像清除功能及簡易說明。這次的頭檔讀入我開始嘗試使用資料結構的方式,因為44個BYTE有點多,我看了都懶了,因此才決定使用資料結構的方式讀入標頭資料,不在是一直用fseek然後再fread了。
typedef struct {
char chuid[4];
byte wavsize[4];
char rifftype[4];
char sing[4];
byte flen[4];
byte ftag[2];
byte chan[2];
byte samr[4];
byte bsec[4];
byte bla[2];
byte bisa[2];
byte data[4];
byte len[4];
}WAV_header;
頭檔顯示成功!!雖然達到目標但這只是半成品而已,程式上面的黑色框框是我準備要來放音訊波形的地方,這裡讓我思考了很久,第一是要如何取得音訊的資料。第二是用取得資料後如何畫成波形。由上面的資料網頁可以得知,在44個byte之後就是所有音頻取樣的資料了,所以在這我想到用陣列來存放音頻的取樣資料。再來就剩下畫圖了,老實說我對BCB的元件還不熟,上網查了很久,有些人說用paintbox元件有些人說用CHART元件,但有些人的程就直接畫在FORM上。看完後我嘗試用CHART作波形,但由於他是本身就寫好專門畫的元件,雖然介面很漂亮也有3D的樣式,但感覺拿來畫音頻的波有點不適合,更重要的是他的X軸我不會設定,結果所有的線都擠成一團,看不出來波形,所以我放棄了CHART。
再來我轉戰paintbox他就好像影像元件,用Canvas->MoveTo和Canvas->LineTo 就可以來話波形了,看起來非常的簡單。但由於paintbox只要我一換視窗畫好的波形就不見了!!這令我很懊惱,想想他既然像Image元件,Image也有Canvas->MoveTo和Canvas->LineTo 所以就決定用他了。
執行完發現這圖形似乎怪怪的 就算把X放大 他也只會縮成一個破碎的長方形。這問題也讓我耗費了不少時間,原來是我取樣資料的資料形態設錯了!!比起4byte 的int還是2byte的short來的好。如此以來就算不縮放X,Y軸波形還是看得出來。
再來我試著讓所有的波形可以一次看到就不斷的放大X軸,結果發現後面似乎是沒有資料的,可是陣列卻開到了這麼大。我是以總取樣個數來當他的柱標值,但卻發生錯誤。後來發現用總取樣個數來當陣列總數是沒錯的,上面的資料網頁告訴我,錯的是我沒把SizeOfData除BlockAlignment來當總取樣個數,難怪會如此的龐大。
接著我想讓它的波形維持某個適當的大小,可以藉由捲軸來看想看的地方。SCROLLBAR元件研究許久我還是不會用,最後想到的方式是把Image放進SCROLLBOX裡然後讓Image的width可以放大到和總取樣各數相同,這樣才達成了我的最終目標。麻煩的是Image的原件必須先自己delete後再new一個新的出來設定,不然他不會乖乖的把width拉長,重複開檔也會一直複寫上去。
耗費了長達12小時的奮鬥,終於完成這個程式,有非常大的成就感,雖然這只是微不足道的小東西。但是在寫程式中學習到的卻是非常可貴的。
沒有留言:
張貼留言