Qt 之 WAV文件解析

#简介
最近看了一下Qt的处理音频方面的资料,本身利用QAudioInputQAudioOutput 就可以实现录音播放功能,代码也很简单,但是录音生成的文件并不能用播放器打开,就算更改后缀名也无法识别(有时候下载的一些音频文件通过修改文件名可以播放)。本质上通过QAudioInput生成的音频文件并没有什么格式,只是一堆音频数据,换言之就是没有文件头,只有数据,当然播放器识别不出来了。这里我们把QAudioInput生成的音频文件转换为wav音频格式就可以用播放器播放了。下面就详细介绍一下WAV文件 , 下一篇中将用代码来实现录音/播放and录音文件(raw/pcm)转wav格式功能 。

#WAV文件分析
###WAV文件简介

WAV为微软公司开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几! WAV打开工具是WINDOWS的媒体播放器。

通常使用三个参数来表示声音,声道数、采样频率和采样位数。采样位数分为8位,16位,24位三种,声道有单声道和立体声之分,单声道振幅数据为n1矩阵点,立体声为n2矩阵点,取样频率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三种,不过尽管音质出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:WAV格式文件所占容量(B) = (取样频率 X量化位数X 声道) X 时间 / 8 (字节= 8bit) 每一分钟WAV格式的音频文件的大小为10MB,其大小不随音量大小及清晰度的变化而变化。

WAV是最接近无损的音乐格式,所以文件大小相对也比较大。WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型,属于无损音乐[1] 格式的一种。
符合 RIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头音频流的编码参数。数据块的记录方式是little-endian字节顺序,标志符并不是字符串而是单独的符号。

————摘自百度百科

###WAV文件特点

WAV音频格式的优点包括:简单的编/解码(几乎直接存储来自模/数转换器(ADC)的信号)、普遍的认同/支持以及无损耗存储。WAV格式的主要缺点是需要音频存储空间。对于小的存储限制或小带宽应用而言,这可能是一个重要的问题。WAV格式的另外一个潜在缺陷是在32位WAV文件中的2G限制,这种限制已在为SoundForge开发的W64格式中得到了改善。

常见的WAV文件使用PCM无压缩编码,这使WAV文件的质量极高,体积也出奇大,对于PCM WAV,恐怕也只有无损压缩的音频才能和其有相同的质量,平时我们见的什么mp3,wma(不含wmalossless)和wav的质量都是差很远的!这点可以通过频谱看出,即使320kbps的mp3和wav一比,也要自卑了!

————摘自百度百科

#WAV文件头分析
下图为wav文件的基本格式。

这里写图片描述这里写图片描述

仔细看上图,其实wav文件是由若干个数据块组成的。wav文件头信息包括从上图的RIFF头到数据块中的块头这一部分为wav文件的文件头(简而言之就是去除数据块中的块数据即为文件头,也就是不包含音频数据)

// wav文件头信息结构
struct WAVFILEHEADER
{
    // RIFF 头;
    char RiffName[4];
    unsigned long nRiffLength;

    // 数据类型标识符;
    char WavName[4];

    // 格式块中的块头;
    char FmtName[4];
    unsigned long nFmtLength;

    // 格式块中的块数据;
    unsigned short nAudioFormat;
    unsigned short nChannleNumber;
    unsigned long nSampleRate;
    unsigned long nBytesPerSecond;
    unsigned short nBytesPerSample;
    unsigned short nBitsPerSample;

    // 扩展信息(附加信息),根据 nFmtLength 来判断;
    // 扩展域大小;
    unsigned short nAppendMessage;
    // 扩展域信息数据;
    char* AppendMessageData;

    //Fact块,可选字段,一般当wav文件由某些软件转化而成,则包含该块和扩展信息;
    char FactName[4];
    unsigned long nFactLength;
    char FactData[4];

    // 数据块中的块头;
    char    DATANAME[4];
    unsigned long   nDataLength;
};

这里我们定义一个结构体分别对应上图中wav文件头从上到下不同的块。


##不同块数据的介绍

###RIFF 头

  • RIFFNAME —— (“RIFF”)
    资源交换文件标志,以RIFF标示

  • nRIFFLength —— ( 文件长度-8 )
    整个wav文件大小减去RIFFNAME和nRIFFLength所占用的字节数

数据类型标识符

  • WavName —— (“WAVE”)
    波形文件标识符,wav文件标志,表示是wav文件

格式块中的块头

  • FmtName —— ("fmt ")注意这里fmt后面还要加一个空格以满足4个字节

  • 波形格式标志

  • nFmtLength —— (一般为16 或者 18 也有 大于18的数值)
    表示格式块中块数据大小,通常为16,为18时表示格式块中块数据有附加信息(即扩展域大小-nAppendMessage),主要由一些软件制成的wav格式中含有该2个字节,当大于18时,nFmtLength - 18 (或者用nAppendMessage代替) 即为扩展域信息数据所占的字节数(上图中也指出),具体包含什么数据也只有生成该wav文件的生成者知道了。

格式块中的块数据

  • nAudioFormat ——(0001H)
    格式种类,也可以说是编码方式(值为1时,表示数据为线性PCM编码,大于1时表示有压缩的编码)

  • nChannleNumber ——(1 或者 2)
    音频通道数目,1–单通道(声道);2–双通道(声道)

  • nSampleRate
    采样频率(每秒样本数)

  • nBytesPerSecond —— (采样频率 × 音频通道数 × 每次采样得到的样本位数 / 8)
    波形数据传输速率(每秒平均字节数)

  • nBytesPerSample —— (通道数×每次采样得到的样本数据位值/8)
    数据块对齐单位(每个采样需要的字节数)

  • nBitsPerSample
    每次采样得到的样本数据位数值(Qt助手中提到一般设置为8 或 16 , 有一些系统可能支持更高的数据位数,百度百科中提到可取值 8、16、24)

  • nAppendMessage
    扩展域大小,扩展信息(可选),根据nFmtLength 的值判断是否存在

  • AppendMessageData
    扩展域信息数据,扩展信息(可选),根据nFmtLength 的值判断是否存在

Fact块(可选)

  • FactName (“fact”)
    Fact块名,表面这是一个Fact块,此块目前由是否nFmtLength决定是否存在,与扩展信息一致。

  • nFactLength
    Fact块数据长度 , 一般取值为4

  • FactData
    Fact块数据 , 具体包含什么信息只有生成该wav文件的生成者知道了

数据块中的块头

  • DATANAME —— (“data”)
    数据块标识符

  • nDataLength
    采样数据总字节数 / 数据块中块数据总大小(即wav文件实际音频数据所占的大小)

##注意
需要注意的一点,上面叙述中添加了一个Fact块(可选块),也就是格式块中的扩展域后面可能存在的一块,目前认为是存在扩展域就会存在Fact块。见下图,在格式块中根据nFmtLength(格式块中块数据大小) 的值,一般情况下为16字节,即不包含Fact块,看图中fmt子块中WAVEFORMATEX占了18个字节,通常情况下为16字节,包含附加信息Fact块就是18字节(也会大于18字节)。
从下图中可以看出wav文件都是以 52 49 46 46 开头(将wav文件用编辑器打开),也可以根据这几个值初步判断是否是一个wav文件。

通过以上对wav格式的分析,我们可以对一个wav文件进行解析,获取文件具体的信息,下篇中将会给出具体代码实现来解析一个wav文件,输出文件的信息。

这里写图片描述


##wav文件属性的计算
如果我们知道采样频率、每次采样得到的样本数据位数、声道数及wav文件大小就可以推出wav文件的时间,其实我们右击显示wav文件属性的时候,会有时间、比特率,但是这里显示的时间都是整数,不是很精确,比如一个小于1s的文件,查看属性显示时间长度就为0,所以想要得到精确的时间就得通过计算得出。
Qt 之 解析wav文件的头信息(详细分析、对比不同wav文件的数据) 中我们给出了如何解析wav文件头信息的方法,这样我们就可以计算出wav文件的音频时长。

波形数据传输速率(每秒平均字节数) = 采样频率 × 音频通道数 × 每次采样得到的样本位数 / 8

比特率(kbs) = 波形数据传输速率 × 8 / 1000

WAV文件所占大小(字节) = 波形数据传输速率 × 音频文件时长

音频文件时长(秒) = WAV文件所占容量 / 波形数据传输速率

Qt 之 WAV文件属性计算(比特率、文件大小、文件时长)文章中给出了具体分析。


###关于数据库中数据bit位置安排方式

数据块中的块数据才是真正的声音数据。除非安装其它特殊软件,否则Windows目前仅提供WAVE_FORMAT_PCM (pcm)一种数据格式,即脉冲编码调制(Pulse Code Modulation).根据声道数不同及取样位数的不同,安排4bit位的位置,wav数据的bit位置可以分成以下几种形式,见下图。

这里写图片描述


###参考资料:

http://blog.csdn.net/zhihu008/article/details/7854533

http://www.2cto.com/os/201312/267541.html

http://www.cnblogs.com/tiandsp/archive/2012/10/17/2728585.html


#尾
以上是经过多番资料查询以及个人的一些看法总结整理出,基本上概括了wav文件头信息中各个数据表示的实际意义以及取值,如果文章中出现错误,还请指出,谢谢

  • 15
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值