wav音频文件解析

概述

  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区块

名称偏移地址字节数端序内容
riffType0x004Byte大端‘RIFF’ (0x52494646)
riffSize0x044Byte小端fileSize - 8
waveType0x084Byte大端‘WAVE’(0x57415645)
  • 以’RIFF’为标识
  • riffSize是整个文件的长度减去ID和Size的长度
  • waveType是WAVE表示后面需要两个子块:Format区块和Data区块

FORMAT区块

名称偏移地址字节数端序内容
formatType0x004Byte大端'fmt ’ (0x666D7420)
formatSize0x044Byte小端16
compressionCode0x082Byte小端音频格式
numChannels0x0A2Byte小端声道数
sampleRate0x0C4Byte小端采样率
bytesPerSecond0x104Byte小端每秒数据字节数
blockAlign0x142Byte小端每个采样所需字节数
bitsPerSample0x162Byte小端采样位数
  • 以’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区块

名称偏移地址字节数端序内容
dataType0x004Byte大端‘data’ (0x64617461)
dataSize0x044Byte小端N
Data0x08NByte小端音频数据

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  
	
	
	@Override
	public String toString() {
		return "------------------RIFF------------------\n"+ 
			   "\n riffType\t:"+new String(riffType)+
			   "\n riffSize\t:"+riffSize+
			   "\n waveType\t:"+new String(waveType)+
			   "\n\n------------------FORMAT----------------\n"+
			   "\n formatType\t:"+ new String(formatType) +
			   "\n formatSize\t:"+ formatSize +
			   "\n compressionCode:"+ compressionCode +
			   "\n numChannels\t:" + numChannels +
			   "\n sampleRate\t:" + sampleRate +
			   "\n bytesPerSecond\t:" + bytesPerSecond +
			   "\n blockAlign\t:" + blockAlign +
			   "\n bitsPerSample\t:" + bitsPerSample +
			   "\n dataType\t:" + new String(dataType) +
			   "\n dataSize\t:" + dataSize + 
			   "\n\n-----------------------------------------";
	}
	
}

解析结果

WAV文件格式

测试文件

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数据格式

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dan淡淡的心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值