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画出的波形类似...
一.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画出的波形类似...
相关文章推荐
- "There is not a valid medialib id!"与解析wav文件格式
- 基于Linux ALSA音频驱动的wav文件解析及播放程序
- wav音频文件格式解析
- Android 音频开发-如何存储和解析wav文件
- wav文件格式分析详解和解析代码
- 基于Linux ALSA音频驱动的wav文件解析及播放程序
- [置顶] WAV文件格式解析
- 二进制文件处理 WAV文件格式解析【利用python 将wav文件音量变小】
- [转]wav文件结构解析
- WAV文件格式分析解析,附带吗
- wav音频文件格式解析
- WAV文件格式终极解析
- Android音频开发(4):如何存储和解析wav文件
- WAV文件格式分析解析,代码已附
- Qt 之 解析wav文件的头信息(详细分析、对比不同wav文件的数据)
- wav文件格式解析
- wav音频文件头解析
- wav文件格式分析详解和解析代码
- 基于Linux ALSA音频驱动的wav文件解析及播放程序
- wav音频文件头解析