> 来源 | HaaS技术社区
1、背景
近十年是移动智能设备迅速爆发的十年。随着智能手机、平板电脑、AI智能音响、车载智能设备的普及,“语音”已经成为了用户与智能设备交互的最重要方式之一。
例如,当您拿出手机拨打电话时,“内置mic”负责您声音的采集、“听筒”是对方声音输出的默认设备。当您家人也想和对方聊上几句时,您往往会打开Speaker让家人一起畅聊。当您接听的是商务会议时,您往往会插上“3.5mm耳机”或者“蓝牙耳机”,让自己拥有更加私密的通话氛围。
开车中的您正在沉浸在车载音乐BGM中时,如果手机导航软件需要提醒您“前方有违章拍照”时手机会怎么做呢?以Android手机为例,Android会把BGM的音量降低,然后将导航播报的声音和低音量的BGM混音后播放,当导航播报完毕后再将BGM恢复到原来的音量继续播放。这种无缝切换的设计不仅友好的提醒了您前方的路况信息,又让您持续的沉浸在BGM中无法自拔。
还有细心的朋友可能会发现,现在大型商场中,AI智能机器人越来越多了。您已经不需要在手机上打开某个APP、敲上想查的关键字去搜索您想找的商户来,您需要做的仅仅是开口说出您的问题,机器人即可给您满意的答案。
2、为什么需要音频系统框架
以上这些应用场景的实现都是由智能设备中的“音频中枢系统”来完成的。如果要用一句话来描述智能设备的“音频系统”的话,那么可以这么理解,就是“向下屏蔽和管理的错中复杂的声卡设备,向上为应用程序提供友好丰富的语音服务接口”。
嵌入式OS中需要管理的音频硬件codec错综复杂。功能上区分有仅支持录音的、仅支持播放的、同时支持录音播放/播放的codec、有支持音量调节的也有不支持的。接口上区分有I2S接口的,PCM接口的,AC97接口的。音频codec的厂商也有近百家,搭配的CPU平台也有几十种,排列组合之后就是上万种的“CPU + Audio Codec”的可能,且每一种排列组合在Linux内核中都已经有成熟的音频驱动程序支持,繁荣的硬件驱动生态是各种主流智能设备的OS无法摒弃Linux内核的重要原因。
![image.png](https://ucc.alicdn.com/pic/developer-ecology/1204aa189120461fada23fa545890a02.png) 图1: 典型音频硬件系统框架
丰富的应用生态也是Linux在嵌入式设备中经久不衰的重要原因。以Linux系统为例,Linux屏蔽了底层音频硬件的差异,在用户态通过alsa-lib为生态中的音频应用提供了统一的API接口供调用。
因此要快速开发一款经久不衰的智能语音产品,一个优秀的的音频系统框架是至关重要的。
3、Linux ALSA音频框架
ALSA是Advanced Linux Sound Architecture的缩写,即高级Linux音频架构,在Linux上提供了对音频和MIDI(较少使用)的支持。在Linux 2.6的内核版本后,AlSA目前已经成为了linux的主流音频体系结构。官方资料和源码下载参考:“ALSA-Project”。
ALSA包含内核设备驱动层ALSA-Driver以及用户态的ALSA-Lib两大模块。应用程序直接调用ALSA-Lib的标准接口即可完成对底层音频硬件的控制,直接访问内核接口是不被允许的。
ALSA有如下特点
- 标准音频驱动模型,支持多种音频设备。
- 模块化的内核驱动程序,支持热插拔(例如3.5mm耳机)。
- 支持SMP(对称多处理)和多线程。
- 提供多种音频处理组件(例如重采样,混音,多声道管理,软音量调节等),以及丰富的调试诊断工具。
- 兼容旧版本OSS应用程序。
![image.png](https://ucc.alicdn.com/pic/developer-ecology/b38e24d7aba14955bf4330090fa17d50.png) 图2: Linux ALSA音频系统框架
3.1 用户态ALSA-Lib
ALSA-Lib提供了对内核ALSA-Driver完整功能接口的支持,为应用提供了更加安全的API接口,同时也提供了丰富的音频组件,从而让应用程序的开发更加简单且高效。
3.1.1 ALSA-Lib API
官网给出的alsa-lib的API列表信息如下,
![image.png](https://ucc.alicdn.com/pic/developer-ecology/009a26cb2d7d4d00a4a7f1064ccd968d.png) 图3:ALSA官网对ALSA-Lib API的描述
下面提供了一些ALSA-Lib接口的简单描述,
- Control interface: 提供灵活的方式管理注册的音频设备,并提供设备查询接口。
- PCM digital interface:PCM(pulse code modulation脉冲编码调制)是最常见的数字表示模拟信号的方法。PCM音频流几乎被所有的计算机系统支持,因此alsa的PCM模块中提供了丰富的接口供应用层完成对音频数据流的访问。PCM模块中的playback和capture两个子模块提供了上层应用依赖的重要接口。
- playback: 负责把用户空间的解码后的PCM音频流输出到音频驱动层,进而通过硬件codec转换成人耳可以辨识的模拟音频。
- capture: 底层硬件mic拾取到模拟信号,经过采样、量化,最终转换成数字PCM流。capture模块提供了应用层获取PCM音频流的接口。
- RawMidi interface:MIDI (Music Instrument Digital Interface)是一种标准电子音乐指令集,该模块提供了访问声卡上MIDI总线的接口,这些接口封装了丰富的MIDI事件(例如音符...),开发者只需要管理音频中各MIDI事件的组合与时间即可。值得注意的是MIDI接口的设备已经逐渐退出,使用范围越来越少了。
- Sequencer interface: 一个比原始RawMidi接口高级的MIDI编程和声音同步接口,可以处理很多MIDI协议和定时器。
- Timer interface: 为支持声音的同步事件提供访问声卡上的定时器。
- Mixer interface: 混音器接口,控制多路音频混合输出以及各路音频音量控制。
3.1.2 ALSA-Lib插件
ALSA-Lib还提供了丰富的PCM插件。插件可以自动处理诸如:命名设备、采样率转换、通道间的采样复制、写入文件、为多个输入/输出连接声卡/设备(不同步采样)、使用多通道声卡/设备等工作。插件的使用是通过ALSA-Lib的配置文件来进行,同时配置文件也规定了音频在ALSA-Lib中的处理链路。常用的音频插件包括,
- softvol: 软音量插件,主要用来调节增益用的,采用的整形数运算。
- route: 主要做声道的转换,如双声道转化为单声道
- rate: 采样率转换插件,默认的采用linear 算法会有失真,可以尝试speexdsp的重采样算法来优化。
- dmix: 混音插件。
- file: 主要用于问题定位,将pcm数据直接保存的文件里面供调试使用。
- dsnoop: 与dmix 刚好相反,他是将DAC录音的pcm 数据分发给多个client。
- hw: 与alsa-driver操作的接口
- multi: 将多个声卡的合并为一个虚拟的pcm 节点,即对不同的声卡的pcm 进行merge
- extplug: 主要承接外部自定义的插件,方便介入第三方或者自定义的插件,天猫精灵中的DTS/Sona 音效就可以通过extplug来做。
3.1.3 移植ALSA-Lib的难点
ALSA-Lib提供了对内核ALSA Driver的完整支持,同时也有非常多的组件可供使用,但是如果尝试移到ALSA-Lib到AliOS Things中也面临着以下的问题,
- 代码量庞大:Linux 2.5版本开始ALSA音频框架取代了旧的OSS音频框架,主要原因是性能更好且支持多个播放源。但经过多个版本迭代之后,代码量已经达到数十万行的级别,且依赖大量Linux上才有的头文件和接口。短时间内要把ALSA-Lib完整功能移植到AliOS Things中是耗时耗力的工程,ROI并不高。更合理的做法是根据AliOS Things的定位,结合实际项目场景的需求,择优而取。
- 很多被淘汰的代码接口:由于历史原因,ALSA保持了对旧的OSS音频框架的完整支持,同时还有对MIDI, Sequencer, Timer等现代智能设备已经不再使用的接口支持。这些过时的接口和标准分布在ALSA-LIB的各处代码中。要将ALSA-Lib裁剪的足够小也是一个耗时耗力的事情。
- Licence不太友好:Linux ALSA是GPL Licence, 存在代码污染的风险。
3.2 内核态ALSA-Driver
Linux kernel中ALSA-Driver主要包含ALSA Core, ASOC Core, Hardware Driver三部分。
![image.png](https://ucc.alicdn.com/pic/developer-ecology/75b508844278408d93f111b61e50cb20.png) 图4: Linux ALSA音频驱动代码结构
3.2.1 ALSA-Core
ALSA-Core是alsa-driver的核心层,向上提供音频设备(PCM/ Control/ MIDI/ Timer ...)的系统调用,向下驱动硬件设备。
3.2.2 ASOC-Core
ASOC-Core是建立在标准ALSA Core基础上,为了更好支持嵌入式系统和应用于移动设备的音频Codec的一套软件体系。在移动设备中, 为了更好的提供ALSA支持, 在核心层的基础上出现了ASOC(ALSA System on Chip)层,主要由如下三部分组成,
- Codec: 负责配置Codec为音频capture和playback模式,音量调节,bias参数等。
- Platform: 主要负责SoC平台音频DMA和音频接口的配置和控制, 包括时钟、DMA、I2S、PCM等。
- Machine: 可以理解成Codec、Platform的组合。每个产品的硬件平台可以支持多个Machine (Platform + Codec),用户根据实际硬件设置和应用场景动态配置。
3.2.3 Hardware Driver
处于ALSA Driver框架的最底层,具体的代码逻辑也是驱动开发人员需要实现的部分。Linux ALSA Driver中将Audio硬件抽象成了platform, codec, machine三大块,每个模块分工清晰。
4、AliOS Things的音频框架设计
AliOS Things的定位是轻量级的物联网操作系统,作为后起之秀,和众多物联网操作系统一样,很难获得广大硬件厂商的软件支持,同时在应用生态上也无法与成熟的Linux相媲美。所以我们不妨大胆的去尝试,积极拥抱已有的Linux硬件驱动生态和应用生态将会是AliOS Things快速获取用户认可的重要选择。
综上AliOS Things的音频系统框架主要出于以下三点考虑:
- 兼容已有的Linux音频应用生态:Linux版本的AI智能音箱、IP Camera、智慧面板等产品都是基于Linux ALSA音频框架开发的,为了降低开发者基于AliOS Things开发类似产品的门槛,AliOS Things的音频框架向上为应用层提供Linux一致的接口是合理的。
- 兼容已有的Linux硬件驱动生态:一个音频系统的硬件平台可能有上万种的排列组合,如果开发者基于AliOS Things开发音频软件系统需要重新适配上万种的硬件驱动,那么对于开发者而言将是灾难。因此AliOS Things如何更友好的去兼容已有的硬件驱动生态是必须考虑的问题。
- 降低音频应用开发难度,培养良好的开发者生态:满足了以上两点的要求,那么对于开发者来说基于AliOS Things开发应用程序并没有特别高的门槛,这是让开发者不畏惧AliOS Things,敢为使用AliOS Things的重要因素。
4.1 整体设计
![image.png](https://ucc.alicdn.com/pic/developer-ecology/bc3c63cc5bba4563a7ed2ca2f9759270.png) 图5: AliOS Things音频框架设计
由图可见,AliOS Things音频系统包括音频驱动框架、音频服务框架、音频应用组件三大部分。
4.2 音频驱动
AliOS Things音频驱动框架设计的2大目标是,
- 遵循“一切皆文件”的思想,通过VFS向用户测提供和Linux/Android一样的操作接口。
- 向下同时兼容RTOS上碎片化的、Linux上丰富标准的音频驱动生态。
4.3 音频服务
音频服务框架(Audio Service)是AliOS Things音频系统的核心模块,包括应用测Sound PCM/Control接口设计、音量管理、播放焦点管理、音效管理、dsnoop录音分发模块、plugin管理模块,Audio Card Manage、PCM/Control Interface模块等。其中plugin管理模块涉及的插件有"soft volume", "rate", "dmix"和 "sona/dts"等。
4.4 音频应用
目前AliOS Things上已经适配好的音频应用组件有"FFMPEG & SDL", "wav播放器",uVoice等,例如智能音响上常用的url播放器, tts播放器, 本地提示音(mp3, aac ...)播放器,蓝牙A2DP音频等。已经初步具备了云端钉一体的智能语音能力。
5、未来
目前AliOS Things的音频驱动框架还处于初级阶段,距离Android上非常完整的、优秀的音频服务体验还有很大的差距。好在AliOS Things也算是在音频应用领域迈出了坚实的一步,未来还有很多工作需要去尝试。
希望广大的HaaS开发者们积极给我们提意见,一起为AliOS Things的音频框架出谋划策,一起拼一起赢。
更多精品好文