wav音频文件解析
- 概述
- 文件结构
-
- RIFF区块
- FORMAT区块
- DATA区块
- demo
- 解析结果
- 测试文件
- 相关资料
概述
Waveform Audio File Format(WAVE,又或者是因为WAV后缀而被大众所知的)是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。
它采用RIFF(Resource Interchange File Format)文件格式结构。通常用来保存PCM格式的原始音频数据,所以通常被称为无损音频。但是严格意义上来讲,WAV也可以存储其它压缩格式的音频数据。
文件结构
WAV文件遵循RIFF规则,其内容以区块(chunk)为最小单位进行存储。WAV文件一般由3个区块组成:RIFF chunk、Format chunk和Data chunk。另外,文件中还可能包含一些可选的区块,如:Fact chunk、Cue points chunk、Playlist chunk、Associated data list chunk等。
这里只介绍RIFF chunk、Format chunk和Data chunk。
RIFF区块
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
riffType | 0x00 | 4Byte | 大端 | ‘RIFF’ (0x52494646) |
riffSize | 0x04 | 4Byte | 小端 | fileSize – 8 |
waveType | 0x08 | 4Byte | 大端 | ‘WAVE’(0x57415645) |
- 以’RIFF’为标识
- riffSize是整个文件的长度减去ID和Size的长度
- waveType是WAVE表示后面需要两个子块:Format区块和Data区块
FORMAT区块
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
formatType | 0x00 | 4Byte | 大端 | 'fmt ’ (0x666D7420) |
formatSize | 0x04 | 4Byte | 小端 | 16 |
compressionCode | 0x08 | 2Byte | 小端 | 音频格式 |
numChannels | 0x0A | 2Byte | 小端 | 声道数 |
sampleRate | 0x0C | 4Byte | 小端 | 采样率 |
bytesPerSecond | 0x10 | 4Byte | 小端 | 每秒数据字节数 |
blockAlign | 0x14 | 2Byte | 小端 | 每个采样所需字节数 |
bitsPerSample | 0x16 | 2Byte | 小端 | 采样位数 |
- 以’fmt '为标识
- formatSize表示该区块数据的长度(不包含ID和Size的长度)
- compressionCode表示Data区块存储的音频数据的格式,PCM音频数据的值为1
- numChannels表示音频数据的声道数,1:单声道,2:双声道
- sampleRate 表示音频数据的采样率
- bytesPerSecond每秒数据字节数 = SampleRate * NumChannels * BitsPerSample / 8
- blockAlign每个采样所需的字节数 = NumChannels * BitsPerSample / 8
- bitsPerSample每个采样存储的bit数,8:8bit,16:16bit,32:32bit
[注意] 这个区域只需要关心 NumChannels SampleRate BitsPerSample 三个参数就可以了,其它的都是依据这三个计算出来的。
DATA区块
名称 | 偏移地址 | 字节数 | 端序 | 内容 |
---|---|---|---|---|
dataType | 0x00 | 4Byte | 大端 | ‘data’ (0x64617461) |
dataSize | 0x04 | 4Byte | 小端 | N |
Data | 0x08 | NByte | 小端 | 音频数据 |
demo
import java.io.FileInputStream;/*** @author 作者 luhua*/
public class WavTest {public static void main(String[] args) throws Exception {WavHeard wavHeard = new WavHeard();FileInputStream fis = new FileInputStream("F:\testFile\audio\b.wav");byte[] b = new byte[4];/**RIFF部分*/fis.read(wavHeard.riffType);/**riffSize*/fis.read(b);wavHeard.riffSize = (b[3]&0xff)<<24|(b[2]&0xff)<<16|(b[1]&0xff)<<8|(b[0]&0xff);/**wave*/fis.read(wavHeard.waveType);/**FMT */fis.read(wavHeard.formatType);/**表示该区块数据的长度(不包含FMT 和fSize的长度)*/fis.read(b);wavHeard.formatSize = (b[3]&0xff)<<24 | (b[2]&0xff)<<16 | (b[1]&0xff)<<8 | (b[0]&0xff);/**PCM音频数据的值为1*/b = new byte[2];fis.read(b);wavHeard.compressionCode = (short) ((b[1]&0xff)<<8 | (b[0]&0xff));/**音频数据的声道数,1:单声道,2:双声道*/fis.read(b);wavHeard.numChannels = (short) ((b[1]&0xff)<<8 | (b[0]&0xff));/**采样率*/b = new byte[4];fis.read(b);wavHeard.sampleRate = (b[3]&0xff) <<24 | (b[2]&0xff)<<16 | (b[1]&0xff)<<8 | (b[0]&0xff);/**每秒数据字节数*/fis.read(b);wavHeard.bytesPerSecond = (b[3]&0xff) <<24 | (b[2]&0xff)<<16 | (b[1]&0xff)<<8 | (b[0]&0xff);/**每个采样所需字节数*/b = new byte[2];fis.read(b);wavHeard.blockAlign = (short) ((b[1]&0xff)<<8 | (b[0]&0xff));/**每个采样存储的bit数*/fis.read(b);wavHeard.bitsPerSample = (short) ((b[1]&0xff)<<8 | (b[0]&0xff));/**data*/fis.read(wavHeard.dataType);/**dataSize*/b = new byte[4];fis.read(b);wavHeard.dataSize = (b[3]&0xff) <<24 | (b[2]&0xff)<<16 | (b[1]&0xff)<<8 | (b[0]&0xff);fis.close();System.out.println(wavHeard);}}class WavHeard{ public byte[] riffType = new byte[4]; //4byte,资源交换文件标志:RIFF public int riffSize; //4byte,从下个地址到文件结尾的总字节数 public byte[] waveType = new byte[4]; //4byte,wav文件标志:WAVE public byte[] formatType = new byte[4]; //4byte,波形文件标志:FMT(最后一位空格符) public int formatSize; //4byte,音频属性(compressionCode,numChannels,sampleRate,bytesPerSecond,blockAlign,bitsPerSample)所占字节数 public short compressionCode; //2byte,格式种类(1-线性pcm-WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM) public short numChannels; //2byte,通道数 public int sampleRate; //4byte,采样率 public int bytesPerSecond; //4byte,传输速率 public short blockAlign; //2byte,数据块的对齐,即DATA数据块长度 public short bitsPerSample; //2byte,采样精度-PCM位宽 public byte[] dataType = new byte[4]; //4byte,数据标志:data public int dataSize; //4byte,从下个地址到文件结尾的总字节数,即除了wav header以外的pcm data length @Overridepublic String toString() {return "------------------RIFF------------------n"+ "n riffTypet:"+new String(riffType)+"n riffSizet:"+riffSize+"n waveTypet:"+new String(waveType)+"nn------------------FORMAT----------------n"+"n formatTypet:"+ new String(formatType) +"n formatSizet:"+ formatSize +"n compressionCode:"+ compressionCode +"n numChannelst:" + numChannels +"n sampleRatet:" + sampleRate +"n bytesPerSecondt:" + bytesPerSecond +"n blockAlignt:" + blockAlign +"n bitsPerSamplet:" + bitsPerSample +"n dataTypet:" + new String(dataType) +"n dataSizet:" + dataSize + "nn-----------------------------------------";}}
解析结果
测试文件
csdn下载 : https://download.csdn.net/download/qq_41054313/18704149
百度网盘 : https://pan.baidu.com/s/1U93rkCs-jqrPBE-Zgd_W7A 提取码:xhn8
相关资料
百度百科
RIFF文件规范
WAV文件格式详解
WVAE文件格式分析
wave文件(*.wav)格式、PCM数据格式