读取Wave格式语音头信息的实现

来源:互联网 发布:广西广电网络企业邮箱 编辑:程序博客网 时间:2024/05/21 01:55
/* *================================================================= * FNAME: test.cc * DESCP: <+Brief Descripation+> * CREAT: 2015-08-18 15:39:21 * LC_AT: 2015-08-18 15:45:57 * VERNO: 1.0.4 * CNOTE: <+Latest Change+> *================================================================= */#include <stdio.h>#include <stdlib.h>#include <string.h>#define FOURCC_RIFF "RIFF"#define FOURCC_WAVE "WAVE"#define FOURCC_FMT  "fmt "#define FOURCC_DATA "data"#define SUPPORTED_SAMPLE_RATE_8K 8000#ifndef WAVE_FORMAT_PCM#define WAVE_FORMAT_PCM     0x0001#define WAVE_FORMAT_ALAW    0x0006#define WAVE_FORMAT_MULAW   0x0007#endif//#ifdef  DEBUG//#define   tDebug printf//#else      /* -----  not DEBUG  ----- *///#define   tDebug //printf//#endif     /* -----  not DEBUG  ----- */#define tDebug printf/** * @brief *      获取语音文件的头信息(包含 采样点数,语音文件的编码格式,声轨数目) * @param fpWav * @param nSampleNum * @param nChanns * @param nWavType * @return *    0, WAVE文件头正常,且此时文件指针(fpWav)指向实际声音数据的起始位置 *   -1, 不是RIFF格式的文件 *   -2, 文件是RIFF格式的非WAVE文件 *   -3, 此WAVE文件的编码格式不是 PCM,ALAW,ULAW *   -4, 此WAVE文件的音轨数不是 1 也不是 2 *   -5, 此WAVE文件的采样率不是 8K *   -6, 此WAVE文件的采样点的大小不是 8bit 也不是16bit *   -7, 此WAVE文件的具体格式 不是 8K_16BIT_PCM 也不是 8K_8BIT_ALAW */int GetWaveHeader(FILE *fpWav, int &nSampleNum, short &nChanns, short &nWavType){  nSampleNum = -1;  nWavType = -1;  char magic[4] = {0};  fseek(fpWav, 0L, SEEK_SET); //确保输入的文件指针 fpWav 的位置是文件的初始位置  fread((void*) magic, 4, 1, fpWav);  if (0 != strncmp(FOURCC_RIFF, magic, 4)) {    tDebug("[Tip] Input file is not in RIFF format\n");    return -1;  }  int lng = 0;  fread((void*) &lng, 4, 1, fpWav);  fread((void*) magic, 4, 1, fpWav);  if (0 != strncmp(FOURCC_WAVE, magic, 4)) {    tDebug("[Tip] Input file is not in WAVE format\n");    return -2;  }  //look for FOURCC_FMT/FOURCC_DATA before end of file  int len = 0;  short blockAlign = 0, sampleSize = 0;  while (0 == feof(fpWav)) //not reach the end of this file  {    fread((void*) magic, 4, 1, fpWav); //read ChunkID    fread((void*) &len, 4, 1, fpWav); //read ChunkSize    if (0 == strncmp(FOURCC_DATA, magic, 4))    {//reach DATA Chunk,exit the while loop      nSampleNum = len / (sampleSize / 8); // 声音数据的采样点数目      break;    }    if (0 == strncmp(FOURCC_FMT, magic, 4))    { //reach Fmt Chunk,and parse format informations      fread(&nWavType, 2, 1, fpWav); // 读取数据类型,例如: PCM, ALaw,Mulaw等      if (nWavType != WAVE_FORMAT_PCM && nWavType != WAVE_FORMAT_MULAW        && nWavType != WAVE_FORMAT_ALAW)      {        tDebug("[Tip] Only standard PCM and ALAW supported.\n");        return -3;      }      fread(&nChanns, 2, 1, fpWav); //Number of Channels, 单通道或双通道      if (nChanns != 1 && nChanns != 2)      {        tDebug("[Tip] Wave file's channels is %d,NOT SUPPORTED\n", nChanns);        nChanns = -1;        return -4;      }      fread(&lng, 4, 1, fpWav); // Sample Rate , 采样率      if (lng != SUPPORTED_SAMPLE_RATE_8K)      {        tDebug("[Tip] Wave file's SampleRate(SR) is %d, NOT SUPPORTED! \n", lng);        return -5;      }      fread(&lng, 4, 1, fpWav); //  每秒的字节数。例如:8k16bit时为 8000×2=16000      fread(&blockAlign, 2, 1, fpWav); // Block align , Chunk 的对齐单位      fread(&sampleSize, 2, 1, fpWav); // Data size ,一个采样点的大小(比特数)      if (sampleSize != 16 && sampleSize != 8)      {        tDebug("[Tip] Only 8/16 bit audio supported!\n");        return -6;      }      // 类型检查      if ((nWavType == WAVE_FORMAT_PCM && sampleSize != 16)       || ((nWavType == WAVE_FORMAT_MULAW || nWavType == WAVE_FORMAT_ALAW)        && sampleSize != 8))      {        tDebug("[Tip] Only 8K_16BIT_PCM and 8K_8BIT_ALAW supported!\n");        return -7;      }      // 如果是扩展的RIFF格式,则"fmt "块的大小可能大于16字节      len -= 16;    }//end of if (0 == strncmp(FOURCC_FMT, magic, 4))    //fmt子块多余的信息,我们不感兴趣. 直接跳过剩余的fmt字节    for (char c; len > 0; len--)    {      fread(&c, 1, 1, fpWav);    }  }  return 0;}
0 0
原创粉丝点击