iOS将PCM数据文件转换为WAV文件

最近学习写wav文件,搞了很久,踩了不少坑。将PCM数据文件转换为WAV文件其实就是在PCM数据前加上WAV的头。只需要设置好码率,声道数,采样位数就可以了。从别人移植过来一段C代码,发现在iOS各种设备平台上还有兼容性的问题,简单的修改了一下,经过几次测试,发现没什么问题了,分享给大家。

//wav头的结构如下所示:

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) //为转换建立一个新文件

{

printf("create wav file error\n");

return -1;

}

//以下是创建wav头的HEADER;但.dwsize未定,因为不知道Data的长度。

strncpy(pcmHEADER.fccID,"RIFF",4);

strncpy(pcmHEADER.fccType,"WAVE",4);

fseek(fpCpy,sizeof(HEADER),1); //跳过HEADER的长度,以便下面继续写入wav文件的数据;

//以上是创建wav头的HEADER;

if(ferror(fpCpy))

{

printf("error\n");

}

//以下是创建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;

//以上是创建wav头的FMT;

fwrite(&pcmFMT,sizeof(FMT),1,fpCpy); //将FMT写入.wav文件;

//以下是创建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中读入数据

while(!feof(fp)) //在.pcm文件结束前将他的数据转化并赋给.wav;

{

pcmDATA.dwSize+=2; //计算数据的长度;每读入一个数据,长度就加一;

fwrite(&m_pcmData,sizeof(int16_t),1,fpCpy); //将数据写入.wav文件;

fread(&m_pcmData,sizeof(int16_t),1,fp); //从.pcm中读入数据

}

fclose(fp); //关闭文件

pcmHEADER.dwSize = 0;  //根据pcmDATA.dwsize得出pcmHEADER.dwsize的值

rewind(fpCpy); //将fpCpy变为.wav的头,以便于写入HEADER和DATA;

fwrite(&pcmHEADER,sizeof(HEADER),1,fpCpy); //写入HEADER

fseek(fpCpy,sizeof(FMT),1); //跳过FMT,因为FMT已经写入

fwrite(&pcmDATA,sizeof(DATA),1,fpCpy);  //写入DATA;

fclose(fpCpy);  //关闭文件

return 0;

}

你可能感兴趣的:(iOS将PCM数据文件转换为WAV文件)