您的位置:首页 > 其它

wav文件解析

2013-05-18 10:29 155 查看
前两天在公司做了个wav文件的播放器和波形显示的东东,回来之后忽然想起一直没有做过总结,趁现在还有空赶紧整理一下...

一.W***格式文件头

1.综述:

wav文件是由四个大块构成的,按照从前到后的顺序依次为RIFF W***E Chunk,Format Chunk,Fact Chunk(可选),Data Chunk.具体如下图所示:

------------------------------------------------

  | RIFF W***E Chunk |

  | ID = 'RIFF' |

  | RiffType = 'W***E' |

------------------------------------------------

  | Format Chunk |

  | ID = 'fmt ' | (此处为四个字节,最后面一个是空格)

------------------------------------------------

| Fact Chunk(optional) |

  | ID = 'fact' |

------------------------------------------------

  | Data Chunk |

  | ID = 'data' |

------------------------------------------------

除了Fact Chunk外,其他三个Chunk都是必须的,并且都有自己的ID,放在块的开始位置,后面紧跟的四个字节是本块所占的大小(出去ID和Size本身所占的四个字节),低字节表示地位,高字节表示高位...

2.详细介绍:

①RIFF W***E Chunk

  ==================================

  | |所占字节数| 具体内容 |

  ==================================

  | ID | 4 Bytes | 'RIFF' |

  ----------------------------------

  | Size | 4 Bytes | |

  ----------------------------------

  | Type | 4 Bytes | 'W***E' |

  ----------------------------------

以RIFF作为标识,后面紧跟size,该size的大小是整个W***E文件大小减去8个字节,然后是Type字段,为"W***E"表示是Wav文件,结构体定义如下:

struct RIFF_HEADER

{

  char szRiffID[4]; // 'R','I','F','F'

  DWORD dwRiffSize;

  char szRiffFormat[4]; // 'W','A','V','E'

  };

②Format Chunk

  ====================================================================

  | | 字节数 | 具体内容 |

  ====================================================================

  | ID | 4 Bytes | 'fmt ' |

  --------------------------------------------------------------------

  | Size | 4 Bytes | 数值为16或18,18则最后又附加信息 |

  -------------------------------------------------------------------- ----

  | FormatTag | 2 Bytes | 编码方式,一般为0x0001 | |

  -------------------------------------------------------------------- |

  | Channels | 2 Bytes | 声道数目,1--单声道;2--双声道 | |

  -------------------------------------------------------------------- |

  | SamplesPerSec | 4 Bytes | 采样频率 | |

  -------------------------------------------------------------------- |

  | AvgBytesPerSec| 4 Bytes | 每秒所需字节数 | |===> W***E_FORMAT

  -------------------------------------------------------------------- |

  | BlockAlign | 2 Bytes | 数据块对齐单位(每个采样需要的字节数) | |

  -------------------------------------------------------------------- |

  | BitsPerSample | 2 Bytes | 每个采样需要的bit数 | |

  -------------------------------------------------------------------- |

  | | 2 Bytes | 附加信息(可选,通过Size来判断有无) | |

  -------------------------------------------------------------------- ----

以"fmt "作为标识,一般长度为16个字节,如果是18个字节则有附加信息,写在最后两个字节上,定义结构体如下:

struct W***E_FORMAT

  {

  WORD wFormatTag;

  WORD wChannels;

  DWORD dwSamplesPerSec;

  DWORD dwAvgBytesPerSec;

  WORD wBlockAlign;

  WORD wBitsPerSample;

  };

  struct FMT_BLOCK

  {

  char szFmtID[4]; // 'f','m','t',' '

  DWORD dwFmtSize;

  W***E_FORMAT wavFormat;

  };

③Fact Chunk(可选字段)

  ==================================

  | |所占字节数| 具体内容 |

  ==================================

  | ID | 4 Bytes | 'fact' |

  ----------------------------------

  | Size | 4 Bytes | 数值为4 |

  ----------------------------------

  | data | 4 Bytes | |

  ----------------------------------

在标准W***E文件中是可有可无的字段,一般当wav文件是某些软件合成的话则包含该字段.定义结构体如下:

struct FACT_BLOCK

  {

  char szFactID[4]; // 'f','a','c','t'

  DWORD dwFactSize;

  };

PS:数据区域不在头部的定义当中...

⑤Data Chunk

  ==================================

  | |所占字节数| 具体内容 |

  ==================================

  | ID | 4 Bytes | 'data' |

  ----------------------------------

  | Size | 4 Bytes | |

  ----------------------------------

  | data | | |

  ----------------------------------

这是真正存储语音数据的地方,以"data"为标识,Size是数据区域的大小,紧接着就是语音数据.定义结构体如下:

struct DATA_BLOCK

  {

  char szDataID[4]; // 'd','a','t','a'

  DWORD dwDataSize;

  };

根据Format Chunk里面声道数和位数的大小,读取W***E数据时候还要看具体的内容,总之数据区不管由几个字节表示一个采样点,都是地位表示低字节,高位表示高字节...

二.波形表示

①数据密集时候表示波形算法:

数据很密集的情况下,在一个区域内有很多个点,这些点肯定可以连成一条线,在这种情况下,取这段区域的最大值和最小值然后用平滑曲线连接起来,就可以得到大体的波形了...

②数据疏散时候表示波形:

在屏幕上画出每个点的位置,然后用GDI的平滑曲线函数连接各个点,就可得到类似Adobe Audition的显示波形

③每个采样点和屏幕位置的对应:

我只试着处理了8位和16位单声道的数据,现说明如下:

8位采样的用short型的变量存储的话范围就是0-255,0表示屏幕的最上端,而255表示屏幕的最下端,所以就可以用rect.bottom - perData*rect.Height()/255来计算屏幕点的位置了...

16位采样的用short型变量存储就会出现溢出,但是恰好可以利用它的溢出来解决问题,由于16位的unsigned 类型表示范围是0-65535,所以用short存储的时候就会出现范围是-32767到32768之间其中负值表示屏幕中线以上的数据,而正值是屏幕中线以下的位置所以计算公式改为:

rect.top + rect.Height()/2 + perData*rect.Height()/65535

画出曲线来基本和Adobe Audition画出的波形类似...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: