[分享] WAV文件格式的详细解析 + 代码

37°男人   2013-4-17 21:44 楼主
WAV文件格式
     WAVE文件是非常简单的一种RIFF文件,它的格式类型为"WAVE"。RIFF块包含两个子块,这两个子块的ID分别是"fmt"和"data",其中"fmt"子块由结构PCMWAVEFORMAT所组成,其子块的大小就是sizeofof(PCMWAVEFORMAT),数据组成就是PCMWAVEFORMAT结构中的数据。

标志符(RIFF)
数据大小
格式类型("WAVE")
"fmt"
Sizeof(PCMWAVEFORMAT)
PCMWAVEFORMAT
"data"
声音数据大小
声音数据

typedef struct _TWavHeader
{
        int rId;    //标志符(RIFF
        int rLen;   //数据大小,包括数据头的大小和音频文件的大小
        int wId;    //格式类型("WAVE"
        int fId;    //"fmt"
        int fLen;   //Sizeof(WAVEFORMATEX)
        short wFormatTag;       //编码格式,包括WAVE_FORMAT_PCMWAVEFORMAT_ADPCM
        short nChannels;        //声道数,单声道为1,双声道为2
        int nSamplesPerSec;   //采样频率
        int nAvgBytesPerSec;  //每秒的数据量
        short nBlockAlign;      //块对齐
        short wBitsPerSample;   //WAVE文件的采样大小
        int dId;              //"data"
        int wSampleLength;    //音频数据的大小
}TWavHeader;
  1. /*
  2. * File name:                resolving.c
  3. * Author:                     xubinbin (xubbwd@gmail.com)
  4. * Version:                   ver.1.0
  5. * Date:                         2013.04.17
  6. * Description:                The type wav file header parameter parsing.
  7. */

  8. #include
  9. #include

  10. #define SIZE_LONG                       4
  11. #define SIZE_SHORT                      2
  12. #define SIZE_ID                         4
  13. #define BITS_PER_BYTE                   8

  14. #define WAVE_FORMAT_PCM                 (0x0001)

  15. #define FILE_NAME                                                 "aplay_test.wav"


  16. typedef struct _fa_wavfmt_t
  17. {
  18.         unsigned short  format;
  19.         unsigned short  channels;                                        //音频通道数                   1:单声道  2:立体声
  20.         unsigned long   samplerate;                                        //声音采样频率
  21.         unsigned short  bytes_per_sample;                        //每帧数据大小(单声道)
  22.         unsigned short  block_align;
  23.         unsigned long   data_size;                                        //数据总长度
  24. }fa_wavfmt_t;



  25. /*
  26. * Function:             fa_read_u32
  27. * Description:           read from the file stream 4 bytes data
  28. */
  29. static unsigned long fa_read_u32(FILE *fp)
  30. {
  31.         unsigned long cx;
  32.         unsigned char temp[SIZE_LONG];

  33.         fread(temp, sizeof(*temp), SIZE_LONG, fp);
  34.         cx =  (unsigned long)temp[0];
  35.         cx |= (unsigned long)temp[1] << 8;
  36.         cx |= (unsigned long)temp[2] << 16;
  37.         cx |= (unsigned long)temp[3] << 24;
  38.         return cx;
  39. }

  40. /*
  41. * Function:             fa_read_u16
  42. * Description:           read from the file stream 2 bytes data
  43. */
  44. static unsigned short fa_read_u16(FILE *fp)
  45. {
  46.         unsigned short cx;
  47.         unsigned char  temp[SIZE_SHORT];

  48.         fread(temp, sizeof(*temp), SIZE_SHORT, fp);
  49.         cx = temp[0] | (temp[1] * 256);
  50.         return cx;
  51. }

  52. void printf_fun(fa_wavfmt_t *fmt)
  53. {
  54.     printf("************************************************************\n");
  55.     printf("*                                                          *\n");
  56.     printf("*   Copyright (C) 2013 xubinbin 徐彬彬 (Beijing China)     *\n");
  57.     printf("*                    Free Software                         *\n");
  58.     printf("*             Email: xubbwd@gmail.com                      *\n");
  59.     printf("*                                                          *\n");
  60.     printf("************************************************************\n\n");
  61.     printf("##############################################################\n");
  62.         printf("######                format                        = %d                ######\n",fmt->format);
  63.         printf("######                channels                = %d                ######\n",fmt->channels);
  64.          printf("######                samplerate                = %ld                ######\n",fmt->samplerate);
  65.         printf("######                bytes_per_sample         = %d                ######\n",fmt->bytes_per_sample);
  66.         printf("######                block_align                = %d                ######\n",fmt->block_align);
  67.         printf("######                data_size                = %ld        ######\n",fmt->data_size);
  68.     printf("##############################################################\n");
  69.         return;
  70. }
  71.         
  72. int main()
  73. {
  74.         long            nskip, x_size;
  75.     unsigned short  format;
  76.         unsigned short  channels, block_align;
  77.         unsigned long   samplerate;
  78.         unsigned long   bits_per_sample;
  79.         unsigned long   bytes_per_sample;
  80.         unsigned long   data_size;
  81.         unsigned char   temp[SIZE_ID];
  82.         fa_wavfmt_t     fmt;

  83.         FILE * fp = NULL;
  84.         if ((fp = fopen(FILE_NAME, "rb")) == NULL) {
  85.                 printf("input file can not be opened;\n");
  86.                 return 0;
  87.     }
  88.         
  89.         /*wav的文件标识符为RIFF,对标识符进行判断*/
  90.         fread(temp, sizeof(*temp), SIZE_ID, fp);
  91.         if (memcmp(temp, "RIFF", (size_t)SIZE_ID)!=0) {
  92.                 fprintf(stderr, "file is not WAVE format!\n");
  93.                 return -1;
  94.         }
  95.         fread(temp, sizeof(*temp), SIZE_LONG, fp);
  96.         
  97.         /*文件的格式类型为WAVE*/
  98.         fread(temp, sizeof(*temp), SIZE_ID, fp);
  99.         if (memcmp(temp, "WAVE", (size_t)SIZE_ID)!=0) {
  100.                 fprintf(stderr, "file is not WAVE format!\n");
  101.                 return -1;
  102.         }
  103.         
  104.         /* fmt标志,最后一位为空 */
  105.         fread(temp, sizeof(*temp), SIZE_ID, fp);
  106.     /* skip chunks except for "fmt " or "data" */
  107.         while (memcmp(temp, "fmt ", (size_t)SIZE_ID)!=0) {
  108.                 nskip = fa_read_u32(fp);
  109.                 if (nskip!=0) {
  110.                         fseek(fp, nskip, SEEK_CUR);
  111.                 }
  112.         }

  113.         /*sizeof(PCMWAVEFORMAT)*/
  114.         x_size = fa_read_u32(fp);
  115. //        printf("LINE[%d]#### %ld\n",__LINE__,x_size);
  116.         /*  1(WAVE_FORMAT_PCM) 格式类别,1表示为PCM形式的声音数据*/
  117.         format = fa_read_u16(fp);
  118.         x_size -= SIZE_SHORT;
  119.         if (WAVE_FORMAT_PCM != format) {
  120.                 fprintf(stderr, "error! unsupported WAVE file format.\n");
  121.                 return -1;
  122.         }

  123.         /*声音通道数*/
  124.         channels = fa_read_u16(fp);
  125.         x_size -= SIZE_SHORT;
  126.         /*声音采样率*/
  127.         samplerate = fa_read_u32(fp);
  128.         x_size -= SIZE_LONG;

  129.         fa_read_u32(fp);                                            /* skip bytes/s          每秒数据量                   */
  130.         block_align     = fa_read_u16(fp);                          /* skip block align  数据块的调整数                 */
  131.         bits_per_sample = fa_read_u16(fp);                          /* bits/sample                  每样本的数据位数        */
  132.         bytes_per_sample= (bits_per_sample + BITS_PER_BYTE - 1)/BITS_PER_BYTE;
  133.         block_align     = bytes_per_sample * channels;

  134.         x_size -= SIZE_LONG + SIZE_SHORT + SIZE_SHORT;              /* skip additional part of "fmt " header */
  135. //        printf("LINE[%d]#### %ld\n",__LINE__,x_size);
  136.         if (x_size!=0) {
  137.                 fseek(fp, x_size, SEEK_CUR);
  138.         }

  139.         /* skip chunks except for "data" */
  140.         fread(temp, sizeof(*temp), SIZE_ID, fp);
  141.         while (memcmp(temp, "data", SIZE_ID)!=0) {
  142.                 nskip = fa_read_u32(fp);                                /* read chunk size */
  143.                 fseek(fp, nskip, SEEK_CUR);
  144.                 fread(temp, sizeof(*temp), SIZE_ID, fp);
  145.         }
  146.         data_size = fa_read_u32(fp); /*语音数据大小*/

  147.         fmt.format           = format;
  148.         fmt.channels         = channels;
  149.         fmt.samplerate       = samplerate;
  150.         fmt.bytes_per_sample = bytes_per_sample;
  151.         fmt.block_align      = block_align;
  152.         fmt.data_size        = data_size / block_align;             /* byte to short */

  153.         printf_fun(&fmt);

  154.         return 0;
  155. }
程序的解析结果:

file:///C:\Users\Administrator.GSTBKSL8FUFWFLH\AppData\Roaming\Tencent\Users\285988185\QQ\WinTemp\RichOle\EO{X$RKZ60H$5@B8DAF`GEP.jpg
未命名.jpg

希望对大家能够有帮助。
xubbwd@gmail.com

游客,如果您要查看本帖隐藏内容请回复


[ 本帖最后由 37°男人 于 2013-4-17 21:47 编辑 ]
邮箱:ternence.hsu@foxmail.com

回复评论 (19)

回复 楼主 37°男人 的帖子

谢谢楼主分享
加油!在电子行业默默贡献自己的力量!:)
点赞  2013-4-18 10:09
谢谢楼主分享
点赞  2013-4-18 11:31
楼主是不是在做音频播放的?

WAV文件的播放,是音频播放器是基础的,也是必由之路
点赞  2013-4-18 12:18
扩展了知识面
点赞  2013-4-18 12:59
写的很好,支持下…
点赞  2013-4-18 21:37
谢谢楼主分享
点赞  2013-4-18 22:08
顶一个,谢谢楼主
点赞  2013-4-18 22:13
谢谢楼主分享!
点赞  2013-4-19 10:01
谢谢分享   还是用的ubuntu系统
点赞  2013-4-19 15:51
谢谢楼主
点赞  2013-4-20 08:21
谢谢分享!
点赞  2013-4-20 15:01
感谢楼主分享
子时DIY http://atzishi.blog.163.com http://atzishi.taobao.com
点赞  2013-4-20 15:05

回复 4楼 dontium 的帖子

嗯,是的,最近都在研究音频的处理,软编码、播放、采集、回声抑制等,欢迎交流
xubbwd@gmail.com
邮箱:ternence.hsu@foxmail.com
点赞  2013-5-3 23:11

回复 10楼 ddlxiaoxu 的帖子

嗯,是用的ubuntu的系统,一个是ubuntu系统比较的好用,另外一个原因是应为开发TI的产品的时候,开发包的开发环境就是推荐的ubuntu下面进行开发
邮箱:ternence.hsu@foxmail.com
点赞  2013-5-3 23:12

回复 楼主 37°男人 的帖子

只读了一个文件头,后面怎么放音输出的没有啊
点赞  2013-5-8 16:53

回复 16楼 huo_hu 的帖子

后面放音播放的,没有写,可以根据不同的环境来,可以直接通过调用aplay来实现。

如果是通过alsa或者是oss来播放也可以。
邮箱:ternence.hsu@foxmail.com
点赞  2013-5-27 14:47
guo过来学习学习
点赞  2013-6-14 23:22
谢谢
点赞  2013-7-19 15:30
不错的东西,
点赞  2014-12-15 13:29
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复