pcm 转 wav 工具

来源:互联网 发布:建设工程监理软件 编辑:程序博客网 时间:2024/06/18 01:00

在做音频测试时经常需要采集原始数据进行分析,结果需要给其他人去听效果,播放pcm 需要知道采样率 ,数据位宽,声道等信息,每次播放设置这些参数比较麻烦,最好就是直接给pcm 数据直接加上wav 的头信息转换成wav 文件,这样就可以在常见的播放器上播放了,wav格式的一个优势就是没有经过任何压缩处理,不会出现信息的丢失,保证能过的一样的效果。
源程序如下:

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>#include <getopt.h>#include <sys/signal.h> struct WAVFLIEHEAD{char RIFFNAME[4];unsigned int nRIFFLength;char WAVNAME[4];char FMTNAME[4];unsigned int nFMTLength;unsigned short nAudioFormat;unsigned short  nChannleNumber;unsigned int nSampleRate;unsigned int nBytesPerSecond;unsigned short nBytesPerSample;unsigned short   nBitsPerSample;char   DATANAME[4];unsigned int  nDataLength;};int main(int argc, char const *argv[]){    unsigned short rate;    int option_index, c;        static const char short_options[] = "hC:P:r:v:s:b:p:";        static const struct option long_options[] = {            {"help",no_argument,0,'h'},            {"wav file name",required_argument,0,'C'},            {"pcm file name",required_argument,0,'P'},            {"rate",required_argument,0,'r'},            {0, 0, 0, 0}        };    char file_name_wav[100]={0,};    char file_name_pcm[100]={0,};    while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1)  {            switch(c) {                case 'h':                    printf("help\n");                    return 0;                case 'C':                    strcpy(file_name_wav,optarg);                    break;                case 'P':                    strcpy(file_name_pcm,optarg);                    break;                case 'r':                    rate = strtol(optarg, NULL, 0);                    break;                default:                    printf("unsupport cmd,try -h for help\n");                    return 1;            }        }struct WAVFLIEHEAD DestionFileHeader;DestionFileHeader.RIFFNAME[0] = 'R';DestionFileHeader.RIFFNAME[1] = 'I';DestionFileHeader.RIFFNAME[2] = 'F';DestionFileHeader.RIFFNAME[3] = 'F';DestionFileHeader.WAVNAME[0] = 'W';DestionFileHeader.WAVNAME[1] = 'A';DestionFileHeader.WAVNAME[2] = 'V';DestionFileHeader.WAVNAME[3] = 'E';DestionFileHeader.FMTNAME[0] = 'f';DestionFileHeader.FMTNAME[1] = 'm';DestionFileHeader.FMTNAME[2] = 't';DestionFileHeader.FMTNAME[3] = 0x20;DestionFileHeader.nFMTLength =16;  //  ��ʾ FMT �ij���DestionFileHeader.nAudioFormat = 1; //�����ʾa lawPCMDestionFileHeader.DATANAME[0] = 'd';DestionFileHeader.DATANAME[1] = 'a';DestionFileHeader.DATANAME[2] = 't';DestionFileHeader.DATANAME[3] = 'a';DestionFileHeader.nBitsPerSample = 16;DestionFileHeader.nBytesPerSample =2;    //DestionFileHeader.nSampleRate =rate;   //DestionFileHeader.nBytesPerSecond = rate * DestionFileHeader.nBytesPerSample;DestionFileHeader.nChannleNumber = 1;int nFileLen = 0;int nSize = sizeof(DestionFileHeader);FILE *fp_s = NULL;FILE *fp_d = NULL;fp_s = fopen(file_name_pcm, "rb");if (fp_s == NULL)  return -1;fp_d = fopen(file_name_wav, "wb+");if (fp_d == NULL)  return -2;int nWrite =fwrite(&DestionFileHeader, 1, nSize, fp_d);if (nWrite != nSize){  fclose(fp_s);  fclose(fp_d);  return -3;}while( !feof(fp_s)){  char readBuf[4096];  int nRead = fread(readBuf, 1,4096, fp_s);  if (nRead >0)  {   fwrite(readBuf,1, nRead, fp_d);  }  nFileLen += nRead;}fseek(fp_d, 0L, SEEK_SET);DestionFileHeader.nRIFFLength = nFileLen - 8 +nSize;DestionFileHeader.nDataLength = nFileLen;nWrite =fwrite(&DestionFileHeader, 1, nSize, fp_d);if (nWrite != nSize){  fclose(fp_s);  fclose(fp_d);  return -4;}fclose(fp_s);fclose(fp_d);return nFileLen;}

我在Ubuntu上做测试,所有转换也就在Ubuntu上进行了,就在上边编译工具好让他能够运行在系统里面。文件名假定位 pcm_to_wav.c
编译命令就是:

gcc  pcm_to_wav.c -o pcm_to_wav

工具使用设置了三个参数:
-C 转换成的wav文件的文件名
-P 待转换的pcm 文件的文件名
-r pcm 的波特率
因为我自己一般都是使用16bit 位宽的,如果有其他位宽需求可以增加参数.

工具使用命令:

pcm_to_wav -C wav_out.wav -P to_wav.dat -r 16000