从 2017 年开始国外智能音箱的热潮席卷到国内, 各大小厂商都推出了智能音箱, 主要有阿里的天猫精灵京东的叮咚和小米的小爱同学等我也在去年双 11 入手了一款智能音箱 (天猫精灵), 体验下来总体感觉还是不错的, 我相信这股热潮在今年(2018) 会愈演愈热有报道说美国的青年有了智能音箱后对手机的依赖度有所下降, 即有些事情可以通过智能音箱解决了, 这种现象在国内也会出现智能音箱是在无线音箱的基础上加上人工智能 (AI) 发展起来的几年前无线音箱也火过, 推出了好多产品, 有基于 bluetooth 的, 也有基于 WiFi 的基于 bluetooth 的是主流, 基于 WiFi 的不多, 但是现在智能音箱都是基于 WiFi 的那时我还在芯片公司, 我们 team 的语音解决方案已经做得很成熟, 老板就让我们用自己公司的芯片做主芯片, 开发一个基于 WiFi 的无线音箱解决方案
无线音箱先由手机去配置连到某个无线路由器上, 手机也连到这个无线路由器上, 这样手机上的音乐播放器就可以把音乐在无线音箱上播放了既可以把手机本机上的歌曲推送到音箱上播放, 也可以把云端的歌曲推送到音箱上播放支持的协议有 DLNA 和 Airplay, 主流的音乐播放器 (QQ 音乐 / 酷狗音乐 / 网易云音乐等) 均支持, 也支持苹果的音乐播放器 (Airplay) 支持的音乐格式很多, 有 MP3/AAC/OGG/APE/WMA/ALAC/FLAC 等, 支持音乐双声道立体声播放, 但是在一个音箱上效果不明显如果有两个这样的音箱, 又用上公司开发的相应的音乐播放 APP, 可以把左声道的数据推送到一个音箱上, 右声道的数据推送到另一个音箱上, 产生较强的立体声效果
无线音箱的软件实现是在 openWrt 上开发的, 这样无线相关的软件全都好了, 我们只要开发音频相关的软件音频相关的绝大多数是基于开源的开发, 协议的 DLNA 用的是 sharepoint,AirPlay 用的是 gmediarender, 音乐格式解析及解码等用的是 FFMPEG, 音频的播放用的是 ALSASharepoint 和 gmediarender 基本上是拿来用, 在接口上改了一点点, 调用我们做好的 API 实现与我们自己软件的通信 FFMPEG 主要是增加 decoder, 同时还要对 decoder 优化使其能流畅的运行我们自己的软件就是搭一个框架 (实现一个 process) 把这些开源实现给串起来, 形成一个无线音箱音乐播放方案解决方案的软件框图如下:
我们实现的 process 叫 mediaplay, 它与协议 (DLNA/AirPlay) 之间通过 share memory 通信, 从而实现音乐的播放暂停停止等 Mediaplay 会调用 FFMPEG 提供的 API 去解析音乐格式, 并一帧一帧的解码得到 PCM 数据放进 ring buffer 中, 然后用 mutex block 住 mediaplayMediaplay 向 ALSA 注册了回调函数, 每隔一帧时长就会被调用一次, 取走 ring buffer 中一帧 PCM 数据, 并解锁 mutex 使 mediaplay 继续循环运行去解码下一帧在一首歌开始解码时一般会缓存若干帧在 ring buffer 中然后才使能播放, 这样做虽然增加了一两百毫秒的 delay, 但是保证了播放时的连续流畅性, 不会出现噪声再说音乐播放是非实时业务, 一两百毫秒的 delay 对用户是不敏感的
我们 team 共 4 人一人负责 ALSA(包括 driver 和 ALSA-Lib 的调用), 一人负责软件框架 (即实现 mediaplay process 及里面的控制逻辑), 一人负责 DLNA/AirPlay 协议的移植以及与 mediaplay 的通信, 我负责 FFMPEGdecoder 优化以及把优化好的 decoder lib 集成到 FFMPEG 中, 同时还负责后处理(主要是 EQ) 用开源的好处是网上资料很多我开始前先在网上搜怎么编译 FFMPEG 生成动态库, 以及怎么使能一些 decoder 不使能一些 decoder 等这些搞定后就调研我们需要的 decoder(MP3/AAC/APE/OGG/WMA/FLAC/ALAC)FFMPEG 是否都支持, 哪些是定点实现的, 哪些是浮点实现的 (我们是在 ARM 上做软件方案, 且 CPU 只有 500 兆, 一定要用定点实现, 浮点实现 CPU load 扛不住) 调研下来这些 decoder FFMPEG 都支持, 但是 AAC/OGG/WMA 是浮点实现的做了个小应用程序 (代码中调用 FFMPEG 的 API) 在芯片上去播放这些格式的音乐, 明显播放速度变慢了, 这就需要去找这些 decoder 的定点实现来替换浮点实现又到网上搜这些 decoder 定点实现中哪个应用最广泛(在网上快速搜到自己想要的东西也是一种能力, 我就在那时候这方面的能力得到了提高, 并且养成了要找开源首先去 GitHub 的习惯给 GitHub 打广告了, 哈哈)
对于 AAC, 搜下来定点方案中较好的是 3GPP 中 AAC 的参考实现由于是 3GPP 的 reference code, 质量肯定没问题, 就决定用它了刚开始未优化时在我们芯片上跑下来 load 是 2000 多 MCPS, 后来一步步优化到不到 200MCPS, 可以在芯片上高枕无忧的运行了, 也就没再继续优化, 还要去忙其他的 decoder 呢至于怎么优化的可以看我前面写过的一片文章 (音频的编解码及其优化方法和经验), 这里就不具体描述了, 通常优化都是有套路的优化好后就要把静态库集成到 FFMPEG 中, 并且加相应的适配代码, 使其能正常运行那时(2013 年) 网上关于这方面的描述不多, 我也是一边搜索一边尝试, 最终把 AAC 的定点实现库成功集成到 FFMPEG 中了这里也简单说一下怎么加 decoder 的库到 FFMPEG 中, 给有需要的做个参考主要有以下几个步骤:
1)把 decoder 调好, 得到库文件和头文件
2)修改 FFMPEG 的 configure
3)在 allcodecs.c 中加上 REGISTER_DECODER(), 注册这个 decoder
4)在 libavcodec 目录中加上这个 decoder 的适配文件(*.c), 同时修改 libavcodec 下的 makefile, 使这个适配文件能编进去
5)修改./configure 使这个 decoder 使能, 同时告诉相应的库路径和头文件路径
OGG 格式的解码用的是 Vorbis, 其官网 (www.xiph.org) 上就有定点实现本来 load 就不高, 把他简单优化一下就可以用了, 然后做成静态库集成到 FFMPEG 中从找定点实现到集成到 FFMPEG 中用了不到一星期时间, 可以说是非常顺利 WMA 就没有这么顺利了, 废了一番波折, 主要是因为微软不提供定点实现在网上花了一些时间搜索, 某个国外论坛里有人说 RockBox 里有 WMA 的定点实现把 RockBox download 下来在 Ubuntu 下生成一个带界面的应用程序, 播放一个 WMA 格式的音乐, 可以正常播放接下来就是把 WMA 的定点实现从 RockBox 中剥离出来, 它与其他代码耦合的比较深, 剥离花了些时间, 最终还是成功剥离了, 又花了点时间简单优化下并做成库集成进 FFMPEG 中这样三个 decoder 的优化及集成就搞定了
Decoder 搞定后就开始做后处理, 主要做均衡化(EQ), 它是通过改变不同频段上的 gain 值从而产生不同的音效, 有摇滚经典古典爵士舞曲等 10 种模式从信号处理的角度看, EQ 就是一个两阶 IIR 滤波器用户在手机 APP 上指定想要的模式后模式 ID 就会发到音箱上, 软件就会根据 ID 得到相应的参数做 EQ 后处理依旧在网上找定点实现, 找到后先做一个应用程序验证效果验证好后就开始把它用到我们的产品中并和其他模块联调调试好后看到我们的无线音箱也支持音效特别有成就感
经过我们几个月的努力, 无线音箱解决方案完成了, 也陆续得到客户的认可, 采用我们的方案对我个人而言, 从语音扩展到了音乐, 音频的知识面更广了
来源: https://www.cnblogs.com/talkaudiodev/p/8428434.html