將PCM數(shù)據(jù)轉(zhuǎn)換成WAV文件其實只是加個文件頭。但要做給普通用戶用,界面比較費時間。增加了單聲道、雙聲道選擇,樣本寬度,提供更多采樣率,并允許輸入采樣率。
實現(xiàn)原理:
wav文件通常包含4段:RIFF、格式段、FACT段和數(shù)據(jù)段。 PCM數(shù)據(jù)就放在數(shù)據(jù)段。只要格式段設(shè)置的格式與數(shù)據(jù)段的數(shù)據(jù)一致,播放程序就可以正確解析。 下面這個數(shù)組的數(shù)據(jù)其實就是一個最小的wav文件。
static const unsigned char wav_template[] = { // RIFF WAVE Chunk 0x52, 0x49, 0x46, 0x46, // "RIFF" 0x30, 0x00, 0x00, 0x00, // 總長度 整個wav文件大小減去ID和Size所占用的字節(jié)數(shù) 0x57, 0x41, 0x56, 0x45, // "WAVE" // Format Chunk 0x66, 0x6D, 0x74, 0x20, // "fmt " 0x10, 0x00, 0x00, 0x00, // 塊長度 0x01, 0x00, // 編碼方式 0x01, 0x00, // 聲道數(shù)目 0x80, 0x3E, 0x00, 0x00, // 采樣頻率 0x00, 0x7D, 0x00, 0x00, // 每秒所需字節(jié)數(shù)=采樣頻率*塊對齊字節(jié) 0x02, 0x00, // 數(shù)據(jù)對齊字節(jié)=每個樣本字節(jié)數(shù)*聲道數(shù)目 0x10, 0x00, // 樣本寬度 // Fact Chunk 0x66, 0x61, 0x63, 0x74, // "fact" 0x04, 0x00, 0x00, 0x00, // 塊長度 0x00, 0xBE, 0x00, 0x00, // Data Chunk 0x64, 0x61, 0x74, 0x61, // "data" 0x00, 0x00, 0x00, 0x00, // 塊長度 };
這個wav文件的數(shù)據(jù)長度為0。我們要增加PCM數(shù)據(jù)只要完成以下工作:
在數(shù)據(jù)段尾增加PCM數(shù)據(jù);
修改數(shù)據(jù)段的塊長度,修改RIFF段的總長度;
正確設(shè)置格式段的PCM參數(shù)。
樣本長度可能不是8的整數(shù)倍,這時wav文件還是要求樣本按照字節(jié)對齊。在一個樣本中數(shù)據(jù)是左對齊的,右側(cè)空位用0填充。 pcm2wav只考慮了樣本長度是16位的情況。
如果有多個聲道,wav文件要求先放樣本1的各聲道數(shù)據(jù),再放樣本2的各聲道數(shù)據(jù),依此類推。 因為我沒有碰到過處理多聲道數(shù)據(jù)的需求,所以pcm2wav只考慮了單聲道。