无论是文字、图像还是音频,播放器都需要以一定的格式组织和存储,以便知道如何分析此数据。 例如,对于原始图像数据,YUV、Bitmap和wav格式是最简单和最常见的。
wav格式和bitmap一样,是微软开发的文件格式规范,共同点是整个文件分为两部分。 第一部分是“文件头”,用于记录重要的参数信息。 对于音频,图像包括图像的宽度高度、颜色位数等,如采样率、通道数和位宽度。 第二部分是“数据块”,它是一帧一帧的二进制数据,对音频来说是原始的PCM数据。 如果是图像,则为RGB数据。
上一篇文章介绍了如何使用Android平台的API进行原始音频信号的采集和播放,本文重点介绍了如何将Android平台采集的PCM音频数据保存到wav文件中,并对wav文件进行了分析
最后,我还将介绍AudioDemo程序,它集成了最近几篇文章中的相关代码,并演示了从收集和播放Android音频的完整过程。
言归正传,谈谈如何读写wav文件的格式。
1 .文件头
首先,让我们看一下wav格式的“文件头”
让我们简单分析一下这个wav格式头。 主要分为三个部分。
第一个是属于“最高位”的块,用“ChunkID”表示这是“RIFF”形式的文件,用“Format”填充“WAVE”表示这是wav文件。 “ChunkSize”记录整个wav文件的字节数
第二部分属于“fmt”块,主要记录了该wav音频文件的详细的音频参数信息,例如通道数、采样率、位宽等
第三部分属于" data "块,名为" Subchunk2Size "的字段记录以后保存的二进制原始音频数据的长度。
分析到这里,您就会知道,实际上,进行多媒体格式的分析并不是特别复杂。 简言之,格式是一种规范,它告诉我二进制数据应该如何存储和如何分析。
更具体地说,您可以定义以下Java类来抽象和编写wav文件头:
/* *版权通知*版权( c ) 2023, j huster * https://github.com/j huster/audio demo * * @ licenseundertheapacheliiche version 2.0 * * @ filewavfileheader.jav a* @ 19 */package com.j huster.publicclasswavfileheader { publicstringmchunkid=& amp; #039; riff&; #039; public int mChunkSize=0; public String mFormat=&; #039; WAVE&; #039; public String mSubChunk1ID=&; #039; fmt&; #039; public int mSubChunk1Size=16; public short mAudioFormat=1; 公共短信道=1; 公共int msamplerate=8000; 公共字节速率=0; public short mBlockAlign=0; public short mBitsPerSample=8; public String mSubChunk2ID=&; #039; 数据和映射; #039; public int mSubChunk2Size=0; publicwavfileheader ( } publicwavfileheader ) intsamplerateinhz,int bitsPerSample,int channels ) msamplerate=sample reate reate mNumChannel=(short ) channels; mbyte rate=msamplerate * mnum channel * mbitspersample/8; mblockalign=(short ) ) mNumChannel*mBitsPerSample/8; }关于各字段的具体含义,请参考以上链接,看看wav文件的读写方法。
音视频开发学习地址:【免费】FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发-学习视频教程-腾讯课堂
【文章福利】:小编整理了一下个人觉得不错的学习。书籍,视频资料被组文件共享。 需要的东西可以自己追加哦。 点击832218493加入(需要自己) )。
2 .读写wav文件
如本文开头所述,wav文件实际上是“文件头”“音频二进制”,因此:
)1)写入wav文件,实际上只需写入wav文件头部,然后继续进行音频二进制的写入即可
)2)读取wav文件,实际上只需读取一个wav文件头,然后继续进行音频二进制读取即可
那么,在手写代码之前,有两点需要弄清楚:
)1) wav文件头中有“变化的”和“不变化的”吗?
例如,文件开头的字符串“RIFF”为“不变”的部分,用于记录音频数据的全长的变量“Subchunk2Size”为“变化”的部分。 要说为什么,那是因为如果音频数据没有完全被写出来,就不知道一共写了多少字节的音频数据。 因此,您只需使用Java的" RandomAccessFile "类将文件指针跳转到" Subchunk2Size "字段并重写缺省值,因为这一部分需要用变量记录
)2) int、short变量和byte[]的转换方法
由于所有wav文件都是以二进制格式读写的,因此在wav文件头类中定义的所有变量都必须转换为字节流。 具体的转换方法如下。
privatestaticbyte [ ] inttobytearray ( int data ) returnbytebuffer.allocate(4).order ) byteorder.little_endian ) } privatestaticbyte [ ] shorttobytearray ( shortdata ) returnbytebuffer.allocate(2).order ) byteorder.little _ end ded b ) ) returnbytebuffer.wrap ) b ).order ) byteorder.little_endian ).} privatestaticintbytearraytoint ( byte [ ] b ) returnbytebuffer.wrap ) b ).order ) byteorder.little_endian ) .关于读写Gettle wav文件的类,我已经是你们的“封装” 我们还完成了AudioDemo程序,它结合了上一篇文章中显示的音频收集和播放代码。 放在我的Github上。 欢迎下载并运行测试,结合代码具体学习Android音频相关技术、代码地址。
3359 github.com/j huster/audio demo
注:本系列文章中的所有代码今后将纳入此demo项目。 版权属于作者。 这是51CTO博客作者Jhuster的原创作品。 请联系作者获得转载许可。 否则,将被追究法律责任。 安卓音频开发(4)如何存储和分析wav文件https://blog.51cto.com/tick tick/1752947