Android系统Audio框架介绍
音频基础知识
声音有哪些重要属性呢?
- 响度(Loudness)
响度就是人类可以感知到的各种声音的大小,也就是音量。响度与声波的振幅有直接关系。
- 音调(Pitch)
音调与声音的频率有关系,当声音的频率越大时,人耳所感知到的音调就越高,否则就越低。
- 音色(Quality)
同一种乐器,使用不同的材质来制作,所表现出来的音色效果是不一样的,这是由物体本身的结构特性所决定的。
如何将各种媒体源数字化呢?
音频采样
将声波波形信号通过ADC转换成计算机支持的二进制的过程叫做音频采样(Audio Sampling)。采样(Sampling)的核心是把连续的模拟信号转换成离散的数字信号。
- 样本(Sample)
这是我们进行采样的初始资料,比如一段连续的声音波形。
- 采样器(Sampler)
采样器是将样本转换成终态信号的关键。它可以是一个子系统,也可以指一个操作过程,甚至是一个算法,取决于不同的信号处理场景。理想的采样器要求尽可能不产生信号失真。
- 量化(Quantization)
采样后的值还需要通过量化,也就是将连续值近似为某个范围内有限多个离散值的处理过程。因为原始数据是模拟的连续信号,而数字信号则是离散的,它的表达范围是有限的,所以量化是必不可少的一个步骤。
- 编码(Coding)
计算机的世界里,所有数值都是用二进制表示的,因而我们还需要把量化值进行二进制编码。这一步通常与量化同时进行。
奈奎斯特采样理论
“当对被采样的模拟信号进行还原时,其最高频率只有采样频率的一半”。
换句话说,如果我们要完整重构原始的模拟信号,则采样频率就必须是它的两倍以上。比如人的声音范围是2~ 20kHZ,那么选择的采样频率就应该在40kHZ左右,数值太小则声音将产生失真现象,而数值太大也无法明显提升人耳所能感知的音质。
录制过程
- 音频采集设备(比如Microphone)捕获声音信息。
- 模拟信号通过模数转换器(ADC)处理成计算机能接受的二进制数据。
- 根据需求进行必要的渲染处理,比如音效调整、过滤等等。
- 处理后的音频数据理论上已经可以存储到计算机设备中了,比如硬盘、USB设备等等。不过由于这时的音频数据体积相对庞大,不利于保存和传输,通常还会对其进行压缩处理。比如我们常见的mp3音乐,实际上就是对原始数据采用相应的压缩算法后得到的。压缩过程根据采样率、位深等因素的不同,最终得到的音频文件可能会有一定程度的失真,另外,音视频的编解码既可以由纯软件完成,也同样可以借助于专门的硬件芯片来完成。
回放过程
- 从存储设备中取出相关文件,并根据录制过程采用的编码方式进行相应的解码。
- 音频系统为这一播放实例选定最终匹配的音频回放设备。
- 解码后的数据经过音频系统设计的路径传输。
- 音频数据信号通过数模转换器(DAC)变换成模拟信号。
- 模拟信号经过回放设备,还原出原始声音。
Audio框架
- APP
厂商根据特定需求自己写的一个音乐播放器软件等等。
- Framework
Android也提供了另两个相似功能的类,即AudioTrack和AudioRecorder,MediaPlayerService内部的实现就是通过它们来完成的,只不过MediaPlayer/MediaRecorder提供了更强大的控制功能,相比前者也更易于使用。除此以外,Android系统还为我们控制音频系统提供了AudioManager、AudioService及AudioSystem类。这些都是framework为便利上层应用开发所设计的。
- Libraries
framework只是向应用程序提供访问Android库的桥梁,具体功能实现放在库中完成。比如上面的AudioTrack、AudioRecorder、MediaPlayer和MediaRecorder等等在库中都能找到相对应的类。
1、frameworks/av/media/libmedia【libmedia.so】
2、frameworks/av/services/audioflinger【libaudioflinger.so】
3、frameworks/av/media/libmediaplayerservice【libmediaplayerservice.so】
4. HAL
从设计上来看,硬件抽象层是AudioFlinger直接访问的对象。这说明了两个问题,一方面AudioFlinger并不直接调用底层的驱动程序;另一方面,AudioFlinger上层模块只需要与它进行交互就可以实现音频相关的功能了。因而我们可以认为AudioFlinger是Android音频系统中真正的“隔离板”,无论下面如何变化,上层的实现都可以保持兼容。
音频方面的硬件抽象层主要分为两部分,即AudioFlinger和AudioPolicyService。实际上后者并不是一个真实的设备,只是采用虚拟设备的方式来让厂商可以方便地定制出自己的策略。抽象层的任务是将AudioFlinger/AudioPolicyService真正地与硬件设备关联起来,但又必须提供灵活的结构来应对变化——特别是对于Android这个更新相当频繁的系统。比如以前Android系统中的Audio系统依赖于ALSA-lib,但后期就变为了tinyalsa,这样的转变不应该对上层造成破坏。因而Audio HAL提供了统一的接口来定义它与AudioFlinger/AudioPolicyService之间的通信方式,这就是audio_hw_device、audio_stream_in及audio_stream_out等等存在的目的,这些Struct数据类型内部大多只是函数指针的定义,是一些“壳”。当AudioFlinger/AudioPolicyService初始化时,它们会去寻找系统中最匹配的实现(这些实现驻留在以audio.primary.*,audio.a2dp.*为名的各种库中)来填充这些“壳”。根据产品的不同,音频设备存在很大差异,在Android的音频架构中,这些问题都是由HAL层的audio.primary等等库来解决的,而不需要大规模地修改上层实现。换句话说,厂商在定制时的重点就是如何提供这部分库的高效实现了。
AudioRcorder和AudioTrack是Audio系统对外提供API类,AudioRcorder主要用于完成音频数据的采集,而AudioTrack则是负责音频数据的输出。AudioFlinger管理着系统中的输入输出音频流,并承担着音频数据的混合,通过读写Audio硬件实现音频数据的输入输出功能;AudioPolicyService是Audio系统的策略控制中心,掌管系统中声音设备的选择和切换、音量控制等。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。