wav音频文件解析

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  
	
	
	@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音频文件解析_第1张图片

测试文件

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

你可能感兴趣的:(笔记)