PCM編碼:
全名Pulse Code Modulation.一般而言PCM編碼即是最高品質的無損編碼.
WAV編碼:
由微軟定義之檔案格式,祈福和RIFF Resouce Interchange File Formate規範.
因此wav都有一個header.其格式如下圖所示:
透過hex_edit 直接分析檔案可以發現wav僅增加44 byte 的 header info 後即將聲音資訊(pcm)直接完整無損的複製至後方.
首先依照wave format格式定義其檔案結構:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
typedef struct { //The 'RIFF' chunck descriptor unsigned char RIFF_CHUNK_ID[4]; unsigned int RIFF_CHUNK_SIZE; unsigned char RIFF_FORMAT[4]; //The 'fmt' sub-chunck unsigned char FMT_SUB_CHUNK1_ID[4]; unsigned int FMT_SUB_CHUNK1_SIZE; unsigned short FMT_AUDIO_FORMAT; unsigned short FMT_NUM_CHANNELS; unsigned int FMT_SAMPLE_RATE; unsigned int FMT_BYTE_RATE; unsigned short FMT_BLOCK_ALIGN; unsigned short FMT_BITS_PER_SAMPLE; //The 'data' sub-chunk unsigned char DATA_SUB_CHUNK2_ID[4]; unsigned int DATA_SUB_CHUNK2_SIZE; } WAVE_HEADER; const unsigned char fChunkID[] = {'R', 'I', 'F', 'F'}; const unsigned char fFormat[] = {'W', 'A', 'V', 'E'}; const unsigned char fSubchunk1ID[] = {'f', 'm', 't', ' '}; const unsigned char fSubchunk2ID[] = {'d', 'a', 't', 'a'}; |
然後依照各個欄位進行計算處裡並填入正確的位置後,直接透過fwrite寫入檔案.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/************************************* * write_wave_header() configuration: * * - 1 channels, * * - frequency 8000 Hz. * **************************************/ void write_wave_header(FILE **file_ptr, int available_data_size) { int file_length = available_data_size + 44 - 8; int fmt_header_length = 16; short bit_per_sample = 16; short channels = 1; short formatTag = 0x0001; int samplesPerSec = 8000; short blockAlign = (short)(channels * samplesPerSec / 8); int avgBytesPerSec = blockAlign * samplesPerSec; int dataHdrLeth = available_data_size; WAVE_HEADER header; memcpy(header.RIFF_CHUNK_ID, fChunkID, 4); header.RIFF_CHUNK_SIZE = file_length; memcpy(header.RIFF_FORMAT, fFormat, 4); memcpy(header.FMT_SUB_CHUNK1_ID, fSubchunk1ID, 4); header.FMT_SUB_CHUNK1_SIZE = 16; header.FMT_AUDIO_FORMAT = 0x0001; header.FMT_NUM_CHANNELS = channels; header.FMT_SAMPLE_RATE = 8000; header.FMT_BYTE_RATE = avgBytesPerSec; header.FMT_BLOCK_ALIGN = blockAlign; header.FMT_BITS_PER_SAMPLE = 16; memcpy(header.DATA_SUB_CHUNK2_ID, fSubchunk2ID, 4); header.DATA_SUB_CHUNK2_SIZE = available_data_size; fwrite(&header, sizeof(WAVE_HEADER), 1, *file_ptr); } |
成功寫入檔案的header後,將pcm中的資料全部寫入到wav的data中.
1 2 3 4 5 6 7 8 9 |
void write_wave_data(FILE** src_file_ptr,FILE** dst_file_ptr){ unsigned short m_pcmData; fread(&m_pcmData, sizeof(unsigned short), 1, *src_file_ptr); while (!feof(*src_file_ptr)) { fwrite(&m_pcmData, sizeof(unsigned short), 1, *dst_file_ptr); fread(&m_pcmData, sizeof(unsigned short), 1, *src_file_ptr); } } |
完整程式碼(連結)
文章標籤
全站熱搜
留言列表