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);
    }
}

 

完整程式碼(連結)

arrow
arrow
    文章標籤
    audio c c++
    全站熱搜

    Lung-Yu,Tsai 發表在 痞客邦 留言(0) 人氣()