zoukankan      html  css  js  c++  java
  • 网上找的一个读取wave文件的代码片段

     1 struct RIFF_HEADER
     2 {
     3      char szRiffID[4];   // 'R','I','F','F'
     4      DWORD dwRiffSize;
     5      char szRiffFormat[4]; // 'W','A','V','E'
     6 };
     7 
     8 struct WAVE_FORMAT
     9 {
    10      WORD wFormatTag;
    11      WORD wChannels;
    12      DWORD dwSamplesPerSec;
    13      DWORD dwAvgBytesPerSec;
    14      WORD wBlockAlign;
    15      WORD wBitsPerSample;
    16 };
    17 struct waveHead
    18 {
    19      RIFF_HEADER riff;
    20      char   szFmtID[4]; // 'f','m','t',' '
    21      DWORD   dwFmtSize;
    22      WAVE_FORMAT wavFormat;
    23 };
    24 
    25 struct FACT_BLOCK
    26 {
    27      char   szFactID[4]; // 'f','a','c','t'
    28      DWORD   dwFactSize;
    29 };
    30 
    31 struct DATA_BLOCK
    32 {
    33      char szDataID[4]; // 'd','a','t','a'
    34      DWORD dwDataSize;
    35 };
    36 
    37 #define WAVE_FORMAT_PCM 0x0001 
    38 #define WAVE_FORMAT_ADPCM 0x0002
    39 
    40          else if (m_iSoundType == wavesound)
    41          {
    42              waveHead aHeader;
    43              fseek(m_soundf, 0, SEEK_SET);
    44              fread(&aHeader, 1, sizeof(waveHead), m_soundf);
    45              if (aHeader.wavFormat.wFormatTag != WAVE_FORMAT_PCM)
    46              {
    47                  PGELOG(LOG_ERROR, "不支持的Wave格式:%s", caFile);
    48                  fclose(m_soundf);
    49                  m_soundf = 0;
    50                  return -1;
    51              }
    52              memcpy(&m_wformat, &(aHeader.wavFormat), sizeof(WAVE_FORMAT));
    53              m_wformat.cbSize = 0;
    54              //if (aHeader.dwFmtSize == 18)
    55              //fread(&(m_wformat.cbSize), 1, sizeof(WORD), m_soundf);
    56              fseek(m_soundf, aHeader.dwFmtSize-16, SEEK_CUR);
    57              FACT_BLOCK fact;
    58              DATA_BLOCK data;
    59              fread(&fact, 1, sizeof(FACT_BLOCK), m_soundf);
    60              if (*((DWORD*)fact.szFactID) == *((DWORD*)"fact"))
    61              {
    62                  fseek(m_soundf, fact.dwFactSize, SEEK_CUR);
    63                  fread(&data, 1, sizeof(DATA_BLOCK), m_soundf);
    64              }
    65              else if (*((DWORD*)fact.szFactID) == *((DWORD*)"data"))
    66                  memcpy(&data, &fact, sizeof(DATA_BLOCK));
    67              m_iDataStart = ftell(m_soundf);
    68              m_iDataSize = data.dwDataSize;
    69 fread(m_pWaveData, 1, m_iDataSize, m_soundf);
    70          }

    附上wave文件格式:

    下面我们具体地分析 WAVE 文件的格式

    endian

    field name

    Size

     
    big ChunkID 4 文件头标识,一般就是" RIFF" 四个字母
    little ChunkSize 4 整个数据文件的大小,不包括上面ID和Size本身
    big Format 4 一般就是" WAVE" 四个字母
    big SubChunk1ID 4 格式说明块,本字段一般就是"fmt "
    little SubChunk1Size 4 本数据块的大小,不包括ID和Size字段本身
    little AudioFormat 2 音频的格式说明
    little NumChannels 2 声道数
    little SampleRate 4 采样率
    little ByteRate 4 比特率,每秒所需要的字节数
    little BlockAlign 2 数据块对齐单元
    little BitsPerSample 2 采样时模数转换的分辨率
    big SubChunk2ID 4 真正的声音数据块,本字段一般是"data"
    little SubChunk2Size 4 本数据块的大小,不包括ID和Size字段本身
    little Data N 音频的采样数据

    以下是对各个字段的详细解说:

    ChunkID 4bytes ASCII 码表示的“RIFF”。(0x52494646)
    ChunkSize 4bytes 36+SubChunk2Size,或是 
    4 + ( 8 + SubChunk1Size ) + ( 8 + SubChunk2Size ), 
    这是整个数据块的大小(不包括ChunkID和ChunkSize的大小)
    Format 4bytes ASCII 码表示的“WAVE”。(0x57415645)
         
    SubChunk1ID   新的数据块(格式信息说明块) 
    ASCII 码表示的“fmt ”——最后是一个空格。(0x666d7420)
    SubChunk1Size 4bytes 本块数据的大小(对于PCM,值为16)。
    AudioFormat 2bytes PCM = 1 (比如,线性采样),如果是其它值的话,则可能是一些压缩形式
    NumChannels 2bytes 1 => 单声道  |  2 => 双声道
    SampleRate 4bytes 采样率,如 8000,44100 等值
    ByteRate 4bytes 等于: SampleRate * numChannels * BitsPerSample / 8
    BlockAlign 2bytes 等于:NumChannels * BitsPerSample / 8
    BitsPerSample 2bytes 采样分辨率,也就是每个样本用几位来表示,一般是 8bits 或是 16bits
         
    SubChunk2ID 4bytes 新数据块,真正的声音数据 
    ASCII 码表示的“data ”——最后是一个空格。(0x64617461)
    SubChunk2Size 4bytes 数据大小,即,其后跟着的采样数据的大小。
    Data N bytes 真正的声音数据

    对于Data块,根据声道数和采样率的不同情况,布局如下(每列代表8bits):

    1. 8 Bit 单声道:

    采样1 采样2
    数据1 数据2

    2. 8 Bit 双声道

    采样1   采样2  
    声道1数据1 声道2数据1 声道1数据2 声道2数据2

    1. 16 Bit 单声道:

    采样1   采样2  
    数据1低字节 数据1高字节 数据1低字节 数据1高字节

    2. 16 Bit 双声道

    采样1      
    声道1数据1低字节 声道1数据1高字节 声道2数据1低字节 声道2数据1高字节
    采样2      
    声道1数据2低字节 声道1数据2高字节 声道2数据2低字节 声道2数据2高字节

    下面我们看一个具体的例子,声音文件如下:

    52 49 46 46 24 08 00 00 57 41 56 45 
    66 6d 74 20 10 00 00 00 01 00 02 00 
    22 56 00 00 88 58 01 00 04 00 10 00 
    64 61 74 61 00 08 00 00 00 00 00 00 
    24 17 1e f3 3c 13 3c 14 16 f9 18 f9 
    34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d 

    对应的分析如下图所示:

    untitled

    自己测试了下暂时还没有弄通。

  • 相关阅读:
    新建MDK工程
    winform如何打开电脑自带小软件
    Winform界面适应不同分辨率
    c#如何为pictureBox控件写单击事件
    winform如何获取记事本内容显示在listBox控件中
    winform如何单击X按钮弹出对话框
    win10系统如何使用自带的备份功能
    模拟iis账号权限
    (转发)在ASP.NET MVC中以post方式传递数组参数的示例
    .net开发windows服务小结 (转发)
  • 原文地址:https://www.cnblogs.com/wainiwann/p/3059011.html
Copyright © 2011-2022 走看看