1.采样率
一秒钟内对声音旗子暗记的采样次数称为采样率,单位 Hz。采样率越高所表示的声波越平滑,对声音的还原度就越好,须要的存储空间也会更大。在数字音频领域常见的采样率有:
l 8000Hz 电话所用采样率

l 22050Hz 无线电广播所用采样率
l 32000Hz miniDV 数码视频 camcorder、DAT(LPmode) 所用采样率
l 44100Hz 音频 CD,也常用于 MPEG-1 音频(VCD,SVCD,MP3)所用采样率
l 48000Hz miniDV、数字电视、DVD、DAT、电影和专业音频所用的数字声音所用采样率
l 96000或192000Hz DVD-Audio、一些 LPCMDVD 音轨、BD-ROM(蓝光盘)音轨、和 HD-DVD(高清晰度 DVD)音轨所用采样率
2.采样精度
对声音旗子暗记的每一次采样在打算机中都表示为一个数字,数字的取值范围越大所表示的声音振幅的变革范围就越大,在 Android 中支持的采样精度有三种,定义在 AudioFormat 中:
二、混音实现
这里我们采取线性叠加求均匀值的办法对两道音频流进行混音,混音前须要担保两道音频流具有相同的采样率、采样位深和声道数。
1.采样位深为 8 bit 时的混音实现
采样位深为 8 bit 时只须要将两端 pcm 数据对应位置的数字相加求均匀值即可。
2.采样位深为 16 bit 时的混音实现
采样位深为 16 bit 时,一次采样须要用两个 byte 表示,以是须要先操纵续的两个 byte 转换成 short 再相加求均匀值。同时还须要考虑字节序问题,字节序分为大端字节序(高位字节在前,低位字节在后)和小端字节序(低位字节在前,高位字节在后),在 Android 中通过 MediaCodec 解码或从 AudioRecord 中录制的音频数据所采取的字节序都可以通过 ByteOrder.nativeOrder() 方法得到,一样平常都采取的小端字节序。
三、利用 ffmpeg 实现重采样
实现混音时须要担保两道音频流的格式(采样率、位深和声道数)完备相同,因此在混音前须要对原始音频数据进行重采样。这里我们利用 ffmpeg 来实现,只须要编译
libswresample、libavformat 和 libavformat 这三个库就可以:
上面的代码中创建了一个重采样须要的高下文环境 SwrContext,并配置了重采样前和重采样后的必备参数,接下来看下如何利用 SwrContext 实现重采样:
上面代码实现中涌现的 inbuffer_address 和 outbuffer_address 是 Android 层调用 ByteBuffer.allocateDirect() 方法提前创建的输入/输出缓存,由于 Android 调用 cxx 涉及到 JNI 调用,且重采样方法的调用也会比较频繁,创建缓存可以避免频繁的分配和销毁内存产生的花费。其余还须要把稳,实际输出的采样数目并不一定与输入的采样数目相同,在创建输出缓存时须要将缓存大小设置的比预期稍高一些或动态调度缓存大小。
末了在重采样结束后还须要开释高下文占用的资源:
四、总结
本文首先采取 ffmpeg 将源音频数据重采样为目标音频格式,再将两道音频格式相同的音频流混成一道音频流,采取的混音办法是将两道音频流对应位置的采样数据相加求均匀值,这种混音办法不会引入额外的噪音,但是在音频流数量比较多时会导致总体音量低落的问题。对付混音的办法,感兴趣的读者可以自行探索。