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

/*
 *=================================================================
 * 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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-01 12:05:10

读取Wave格式语音头信息的实现的相关文章

C# 采用HttpWebRequest 自定义头信息 上传文件

刚实习的时候遇到一个问题:上传文件的URL有特定格式限制,需要按格式定义头信息,才能上传成功.查资料时候当时好像是java版本的,C#代码贴上. //uploadFile:上传文件名 groupId:GUID public string FileUpload(string uploadFile, string groupId) { //从流中读取字节块并将该数据写入给定缓冲区buffer中 FileStream fileStream = new FileStream(uploadFile, Fi

HTTP头信息(转)--1

转自:http://www.cnblogs.com/9988/archive/2012/03/21/2409086.html 我用抓包软件抓了http的包,发现accept大多数有两种情况. 第一种:Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, a

http响应头信息

HTTP 响应头信息 HTTP请求头提供了关于请求,响应或者其他的发送实体的信息. 在本章节中我们将具体来介绍HTTP响应头信息. 应答头 说明 Allow 服务器支持哪些请求方法(如GET.POST等). Content-Encoding 文档的编码(Encode)方法.只有在解码之后才可以得到Content-Type头指定的内容类型.利用gzip压缩文档能够显著地减少HTML文档的下载时间.Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netsca

QT初体验1:如何学习QT之个人浅见,以及如何读取文本文件,在调试信息中输出。

2017年11月初,随着工作岗位的调动,我转到了研发岗,开始了漫漫程序员的成长之路.首先介绍下个人知识储备,大一学习过C语言,没有工程经验,所学是为了期末考试+2级考试,考完在大学+硕士期间没有用到编程. 来到新的工作岗位,心情是既激动又忐忑的,作为一名青铜段位程序员,我得好好规划下学习.成长的路径. 我选择的方法是,跟着项目走,工作中不可能给你大把时光来造作,去把厚厚的C++ Primer or C++ Primer Plus给通读一遍.带着任务去学习,学的最快.具体而言,我的学习思路是: 1

WSDL项目---添加头信息和附件

用于底层协议的SOAP请求是HTTP,可以添加两个自定义HTTP头(例如用于身份验证或会话)和附件. 让我们看一下这两个. 1. 自定义HTTP标头 直接添加自定义HTTP头: 我们已经添加了自定义内容类型头将覆盖标准的内容类型用于SOAP请求(“text / xml;charset = utf - 8”). 发送请求,查看器显示原始的请求 当然你可以根据需要添加任意数量的头信息,可以包含扩展属性值. 相应的响应标签显示了所有HTTP头信息: 2. 附件和内联文件 SoapUI支持以下技术处理文

读取siftgeo格式文件的matlab程序

% This function reads a siftgeo binary file %读取siftgeo格式的二进制文件 % % Usage: [v, meta] = siftgeo_read (filename, maxdes) % filename the input filename % maxdes maximum number of descriptors to be loaded 要加载的描述子最大数量 % (default=unlimited)%默认无限制 % % Return

Android 如何用HttpClient 以Post方式提交数据并添加http头信息

转自:http://www.linuxidc.com/Linux/2011-09/42772.htm Android 如何 post json格式的数据,并附加http头,接受返回数据,请看下面的代码: 1 private void HttpPostData() { 2 try { 3 HttpClient httpclient = new DefaultHttpClient(); 4 String uri = "http://www.yourweb.com"; 5 HttpPost

隐藏web服务的头信息

一.隐藏nginx头信息 什么是header信息?header信息是访客访问你的网站时,web服务返回给客户端的一段信息,包含了网页的一些基本情况.那么为什么要修改 header信息呢?主要是为了防止被居心不良的人利用来获取漏洞信息,例如:通过最最简单的获取header信息发现你的web服务器版本是 nginx/0.7.60,现在又已知这个版本的nginx有某个漏洞,那么就可以利用这个漏洞来攻击你了.互联网信息更新非常快,web服务程序的更新 也是很频繁,我们很多时候由于种种原因不能及时打上补丁

如何将Pcm格式的音频文件转换成Wave格式的文件

最近在做一款变声App,其中就用到了将pcm格式转wave格式,下面贴出源代码,希望带有需求的童鞋有帮助!!!这里是c++语言写的,也可以用java实现.当然java调用native函数要用到jni技术.具体jni技术自己到网路上找找资料. Cpp文件Pcm2Wave.cpp #include <stdlib.h> #include <string.h> #include <stdio.h> #include "wave.h" #include &q