最近學(xué)習(xí)寫wav文件,搞了很久,踩了不少坑。將PCM數(shù)據(jù)文件轉(zhuǎn)換為WAV文件其實就是在PCM數(shù)據(jù)前加上WAV的頭。只需要設(shè)置好碼率,聲道數(shù),采樣位數(shù)就可以了。從別人移植過來一段C代碼,發(fā)現(xiàn)在iOS各種設(shè)備平臺上還有兼容性的問題,簡單的修改了一下,經(jīng)過幾次測試,發(fā)現(xiàn)沒什么問題了,分享給大家。
//wav頭的結(jié)構(gòu)如下所示:
typedef struct {
char fccID[4];
int32_t dwSize;
char fccType[4];
} HEADER;
typedef struct {
char fccID[4];
int32_t dwSize;
int16_t wFormatTag;
int16_t wChannels;
int32_t dwSamplesPerSec;
int32_t dwAvgBytesPerSec;
int16_t wBlockAlign;
int16_t uiBitsPerSample;
}FMT;
typedef struct {
char fccID[4];
int32_t dwSize;
}DATA;
int convertPcm2Wav(char *src_file, char *dst_file, int channels, int sample_rate)
{
int bits = 16;
//以下是為了建立.wav頭而準備的變量
HEADER pcmHEADER;
FMT pcmFMT;
DATA pcmDATA;
unsigned short m_pcmData;
FILE *fp,*fpCpy;
if((fp=fopen(src_file, "rb")) == NULL) //讀取文件
{
printf("open pcm file %s error\n", src_file);
return -1;
}
if((fpCpy=fopen(dst_file, "wb+")) == NULL) //為轉(zhuǎn)換建立一個新文件
{
printf("create wav file error\n");
return -1;
}
//以下是創(chuàng)建wav頭的HEADER;但.dwsize未定,因為不知道Data的長度。
strncpy(pcmHEADER.fccID,"RIFF",4);
strncpy(pcmHEADER.fccType,"WAVE",4);
fseek(fpCpy,sizeof(HEADER),1); //跳過HEADER的長度,以便下面繼續(xù)寫入wav文件的數(shù)據(jù);
//以上是創(chuàng)建wav頭的HEADER;
if(ferror(fpCpy))
{
printf("error\n");
}
//以下是創(chuàng)建wav頭的FMT;
pcmFMT.dwSamplesPerSec=sample_rate;
pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);
pcmFMT.uiBitsPerSample=bits;
strncpy(pcmFMT.fccID,"fmt ", 4);
pcmFMT.dwSize=16;
pcmFMT.wBlockAlign=2;
pcmFMT.wChannels=channels;
pcmFMT.wFormatTag=1;
//以上是創(chuàng)建wav頭的FMT;
fwrite(&pcmFMT,sizeof(FMT),1,fpCpy); //將FMT寫入.wav文件;
//以下是創(chuàng)建wav頭的DATA; 但由于DATA.dwsize未知所以不能寫入.wav文件
strncpy(pcmDATA.fccID,"data", 4);
pcmDATA.dwSize=0; //給pcmDATA.dwsize 0以便于下面給它賦值
fseek(fpCpy,sizeof(DATA),1); //跳過DATA的長度,以便以后再寫入wav頭的DATA;
fread(&m_pcmData,sizeof(int16_t),1,fp); //從.pcm中讀入數(shù)據(jù)
while(!feof(fp)) //在.pcm文件結(jié)束前將他的數(shù)據(jù)轉(zhuǎn)化并賦給.wav;
{
pcmDATA.dwSize+=2; //計算數(shù)據(jù)的長度;每讀入一個數(shù)據(jù),長度就加一;
fwrite(&m_pcmData,sizeof(int16_t),1,fpCpy); //將數(shù)據(jù)寫入.wav文件;
fread(&m_pcmData,sizeof(int16_t),1,fp); //從.pcm中讀入數(shù)據(jù)
}
fclose(fp); //關(guān)閉文件
pcmHEADER.dwSize = 0; //根據(jù)pcmDATA.dwsize得出pcmHEADER.dwsize的值
rewind(fpCpy); //將fpCpy變?yōu)?wav的頭,以便于寫入HEADER和DATA;
fwrite(&pcmHEADER,sizeof(HEADER),1,fpCpy); //寫入HEADER
fseek(fpCpy,sizeof(FMT),1); //跳過FMT,因為FMT已經(jīng)寫入
fwrite(&pcmDATA,sizeof(DATA),1,fpCpy); //寫入DATA;
fclose(fpCpy); //關(guān)閉文件
return 0;
}