如何存储和解析wav文件
定义:wav格式,就是微软开发的一种文件格式规范,文件分为两部分
(1)第一部分:文件头,记录重要的参数信息,对于音频而言,包括:采样率,通道数,位宽等等
(2)第二部分:数据块,也就是一帧一帧的二进制数据,对于音频而言,就是原始的PCM数据
(一)将采集的PCM音频数据保存到wav文件
文件头
wav格式头,主要分为三个部分
(1)属于最顶层的信息块
ChunkID 来表示这是一个RIFF格式文件
Format 填入WAVE 来标识这是一个wav文件
ChunkSize 记录了整个wav文件的字节数
(2)第二部分 属于fmt信息块
主要记录了本wav音频文件的详细音频参数信息,例如通道数,采样率,位宽
(3)第三部分,数据data信息块,由Subchunk2Size 这个字段来记录后面存储的二进制原始音频数据的长度
其实,格式就是一种规范,告诉你二进制数据是怎么存储的,你应该按照什么样的方式解析
下图就是数据怎么进行二进制存储的
所以可以写一个java类来抽象和描述wav文件头
public class WavFileHeader {
public static final int WAV_FILE_HEADER_SIZE = 44;
public static final int WAV_CHUNKSIZE_EXCLUDE_DATA = 36;//第一部分"顶层"和第二部分"fmt"信息块共占36位
public static final int WAV_CHUNKSIZE_OFFSET = 4; //ChunkSize是第4位开始,占4个byte
public static final int WAV_SUB_CHUNKSIZE1_OFFSET = 16;//SubChunk1Size是第16位开始,占4个byte
public static final int WAV_SUB_CHUNKSIZE2_OFFSET = 40;//SubChunk2Size是第40位开始,占4个byte
public String mChunkID = "RIFF";
public int mChunkSize = 0;
public String mFormat = "WAVE";
public String mSubChunk1ID = "fmt ";
public int mSubChunk1Size = 16;
public short mAudioFormat = 1;
public short mNumChannel = 1; //通道数
public int mSampleRate = 8000; //采样率
public int mByteRate = 0;
public short mBlockAlign = 0;
public short mBitsPerSample = 8;//数据位宽
public String mSubChunk2ID = "data";
public int mSubChunk2Size = 0;
public WavFileHeader() {
}
public WavFileHeader(int sampleRateInHz, int channels, int bitsPerSample) {
mSampleRate = sampleRateInHz;
mBitsPerSample = (short) bitsPerSample;
mNumChannel = (short) channels;
mByteRate = mSampleRate * mNumChannel * mBitsPerSample / 8;
mBlockAlign = (short) (mNumChannel * mBitsPerSample / 8);
}
}
也就是将上图描述的用java代码进行抽象化
读写wav文件
wav文件就是一段“文件头+音频二进制数据”,因此:
(1)写wav文件,其实就是先写入一个wav文件头,然后再继续写入音频二进制数据
(2)读wav文件,其实也就是先读一个wav文件,然后再继续读出音频二进制数据即可
值得注意的是:
(1)wav文件头中,有哪些是变化的,哪些是不变的: 文件头开头的“RIFF”字符串就是“不变的”部分,而用来记录音频数据总长度的“Subchunk2Size”变量就是属于“变化的”部分,因为,再音频数据没有彻底全部写完之前,你是无法知道一共写入了多少字节的音频数据的,因此,这个部分,需要用一个变量记录起来,到全部写完之后,再使用 Java 的“RandomAccessFile”类,将文件指针跳转到“Subchunk2Size”字段,改写一下默认值即可。
(2)如何将int ,short变量与byte[] 的转换文章来源:https://www.toymoban.com/news/detail-404071.html
private static byte[] intToByteArray(int data) {
return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(data).array();
}
private static byte[] shortToByteArray(short data) {
return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(data).array();
}
private static short byteArrayToShort(byte[] b) {
return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getShort();
}
private static int byteArrayToInt(byte[] b) {
return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getInt();
}
参考文献:Jhuster的博客文章来源地址https://www.toymoban.com/news/detail-404071.html
到了这里,关于android音频学习笔记之wav头文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!