【音訊】wave格式解析
阿新 • • 發佈:2018-11-04
本文目的:
1、瞭解wave格式組成,瞭解wave頭各個部分組成
wav 格式,是微軟開發的一種檔案格式規範,整個檔案分為兩部分,第一部分是“檔案頭”,記錄重要的引數資訊,對於音訊而言,就包括:取樣率、通道數、位寬等等;第二部分是“資料塊”,即一幀一幀的二進位制資料,對於音訊而言,就是原始的 PCM 資料。
所以wav格式 = Header(44 bytes) + data
Offset | Size | Name | Description |
---|---|---|---|
0 | 4 | ChunkID | ASCII碼”0x52494646”對應字母”RIFF” |
4 | 4 | ChunkSize | 塊大小是指除去ChunkID與ChunkSize的剩餘部分有多少位元組資料。注意:小尾位元組序數。Value=36+SubChunk2SizeValue=36+SubChunk2Size 或者Value=4+(8+SubChunk1Size)+(8+SubChunk2Size)。Value=4+(8+SubChunk1Size)+(8+SubChunk2Size)。 |
8 | 4 | Format | ASCII碼”0x57415645”對應字母”WAVE”。該塊由兩個子快組成,一個“fmt”chunk用於詳細說明資料格式,一個“data”chunk包含實際的樣本資料。 |
12 | 4 | Subchunk1ID | ASCII碼”0x666d7420”對應字母”fmt “。 |
16 | 4 | Subchunk1Size | 如果檔案採用PCM編碼,則該子塊剩餘位元組數為16。 |
20 | 2 | AudioFormat | 如果檔案採用PCM編碼(線性量化),則AudioFormat=1。AudioFormat代表不同的壓縮方式。 |
22 | 2 | NumChannels | 聲道數,單聲道(Mono)為1, 雙聲道(Stereo)為 2。 |
24 | 4 | SampleRate | 取樣率,例:44.1kHz,48kHz。 |
28 | 4 | ByteRate | 傳輸速率,單位:Byte/s。Value==SampleRate∗NumChannels∗BitsPerSample/8Value==SampleRate∗NumChannels∗BitsPerSample/8 |
32 | 2 | BlockAlign | 一個樣點(包含所有聲道)的位元組數。Value==NumChannels∗BitsPerSample/8Value==NumChannels∗BitsPerSample/8 |
34 | 2 | BitsPerSample | 每個樣點對應的位數。 |
2 | ExtraParamSize | 如果採用PCM編碼,該值不存在。 | |
X | ExtraParams | 用於儲存其他引數。如果採用PCM編碼,該值不存在。 | |
36 | 4 | Subchunk2ID | ASCII碼”0x64617461”對應字母”data”。 |
40 | 4 | Subchunk2Size | 實際樣本資料的大小(單位:位元組)。Value==NumSamples∗NumChannels∗BitsPerSample/8Value==NumSamples∗NumChannels∗BitsPerSample/8 |
44 | * | Data | 實際的音訊資料 。 |
簡單地分析一下這個 wav 格式頭,它主要分為三個部分:
第一部分,屬於最“頂層”的資訊塊,通過“ChunkID”來表示這是一個 “RIFF”格式的檔案,“ChunkSize”則記錄了整個 wav 檔案的位元組數,"Format"包含了“WAVE”標識這是一個 wav 檔案。
第二部分,屬於“fmt”資訊塊,主要記錄了本 wav 音訊檔案的詳細音訊引數資訊,例如:通道數、取樣率、位寬等等(含義請參考我的第一篇文章
第三部分,屬於“data”資訊塊,由“Subchunk2Size”這個欄位來記錄後面儲存的二進位制原始音訊資料的長度。
現在的wave支援哪些格式:
AudioFormat | Description |
---|---|
0 (0x0000) | Unknown |
1 (0x0001) | PCM/uncompressed |
2 (0x0002) | Microsoft ADPCM |
6 (0x0006) | ITU G.711 a-law |
7 (0x0007) | ITU G.711 µ-law |
17 (0x0011) | IMA ADPCM |
20 (0x0016) | ITU G.723 ADPCM (Yamaha) |
49 (0x0031) | ITU G.721 ADPCM |
80 (0x0050) | MPEG |
65,536 (0xFFFF) | Experimental |
將PCM檔案轉換為WAVE格式(其實就是在PCM前面加上了44個位元組的頭):
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
typedef struct WAVE_HEADER{
char fccID[4];
unsigned long dwSize;
char fccType[4];
}WAVE_HEADER;
typedef struct WAVE_FMT{
char fccID[4];
unsigned long dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct WAVE_DATA{
char fccID[4];
unsigned long dwSize;
}WAVE_DATA;
if(channels==0||sample_rate==0){
channels = 2;
sample_rate = 44100;
}
int bits = 16;
WAVE_HEADER pcmHEADER;
WAVE_FMT pcmFMT;
WAVE_DATA pcmDATA;
unsigned short m_pcmData;
FILE *fp,*fpout;
fp=fopen(pcmpath, "rb");
if(fp == NULL) {
printf("open pcm file error\n");
return -1;
}
fpout=fopen(wavepath, "wb+");
if(fpout == NULL) {
printf("create wav file error\n");
return -1;
}
//WAVE_HEADER
memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));
memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));
fseek(fpout,sizeof(WAVE_HEADER),1);
//WAVE_FMT
pcmFMT.dwSamplesPerSec=sample_rate;
pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);
pcmFMT.uiBitsPerSample=bits;
memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));
pcmFMT.dwSize=16;
pcmFMT.wBlockAlign=2;
pcmFMT.wChannels=channels;
pcmFMT.wFormatTag=1;
fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout);
//WAVE_DATA;
memcpy(pcmDATA.fccID,"data",strlen("data"));
pcmDATA.dwSize=0;
fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
fread(&m_pcmData,sizeof(unsigned short),1,fp);
while(!feof(fp)){
pcmDATA.dwSize+=2;
fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);
fread(&m_pcmData,sizeof(unsigned short),1,fp);
}
pcmHEADER.dwSize=44+pcmDATA.dwSize;
rewind(fpout);
fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);
fclose(fp);
fclose(fpout);
return 0;
}
呼叫方法:
simplest_pcm16le_to_wave("NocturneNo2inEflat_44.1k_s16le.pcm",2,44100,"output_nocturne.wav");
參考:
http://soundfile.sapp.org/doc/WaveFormat/