美文网首页
混音播放

混音播放

作者: 进击的杰爷 | 来源:发表于2022-04-10 00:57 被阅读0次

    前言

    公司今年开始设置了创新奖,分享奖等各种大奖,不由得动力满满的,是时候拿些压箱底来冲击下奖项了。

    正所谓,博一博,单车变摩托。

    1,音频API

    安卓sdk里,播放音频有 SoundPool,MediaPlayer, AudioTrack 三种方案。

    SoundPool,明显不适合技术选型,因为它比较适合播放短促音效,文件小的音频。

    MediaPlayer,使用频繁的方案,自带解码,支持mp3,wav等音频文件,但只支持单一音频播放。同样不适合。

    AudioTrack,偏底层的音频播放方案,只支持pcm文件。所以,需要将音频文件解码成PCM(byte[] ),再将数据读取到固定的buffer缓存块里,然后再写入 AudioTrack ,就可以播放声音。

    由于前面两个选项已被否决。那么,AudioTrack适不适合混和播放呢?暂不做确认,先看看什么是混和播放。

    2,混音播放

    混和播放,也就是多音轨同时播放,暂停,seekTo 等操作。

    MediaPlayer 也不是不行。新建多个MediaPlayer实例,然后同时操作,该方案其实也是项目里Loop最初的实现方案,曲谱的实现方案。

    虽然项目里的重点模块-曲谱都用上该方案,说明可行性还是有的。但终究不是终极方案。

    比如所有音轨播放之前,播放一段前置节拍。此时会出现衔接间断的问题。

    由于MediaPlayer是对AudioTrack的封装,所以,这个方案的逻辑,其实是系统针对多应用同时播放声音的方案。

    所以,简单的将MediaPlayer替换成AudioTrack,通过多个AudioTrack实例来实现,原理上是一模一样的。

    那还有没有其他方案呢。

    这里就不得不探讨下声音的数字化的原理:在单位时间内对声波进行采样,最后量化成pcm数据。

    同理,混音的原理是是:各个声音波形的叠加,也就是pcm数据的叠加。

    而安卓sdk提供的音频API里,唯一能够针对pcm数据进行播放的,就只有AudioTrack。

    结合上述的分析,具体的方案如下图:

    所以,该方案可行?

    这里抛开其他一些额外处理(比如不同采样率的音频混音,混音后的溢出),理论上是可行的,但其实有个致命的问题。

    那就是多音轨时,jvm内存可能会爆掉。

    这笔帐是可以算清楚的,

    假如采样率为 44100HZ,位深为 16bit,声道数为 2 的 pcm,60 秒大小应为

    44100×16bit×2×60s÷8bit=10,584,000Byte=10.0936889648MB 

    而 Loop 单轨最高录制 5分钟,即单轨大小为 50M,8轨共计 400M

    对于一些低端机型,怕是要承受不来的。

    但实际场景并没有这么极限。所以,应该是可行的。

    实际上,恩雅APP采用了Google Oboe的方案,比AudioTrack更加底层,更加高效以及低延迟。

    但混音原理是一样的,至于不同采样率的音频混音,混音后的溢出同样是存在的,这些还未完善。

    而内存溢出方面,由于JNI 没有内存限制,所以比AudioTrack更加放心。实测录制8条5分钟的音轨,整个应用占用的将近1G,1+3机型也不会出现内存溢出的问题。

    至于为何一开始没有在AudioTrack下功夫,只是项目前期已经接入Google Oboe,也就不再考虑范围。

    所以,接下来,则是重头戏 Oboe 的混音实现了。由于篇幅太长,只能下集解说了。

    相关文章

      网友评论

          本文标题:混音播放

          本文链接:https://www.haomeiwen.com/subject/hlnmsrtx.html