当前位置:   article > 正文

Android音频系统简介_android 音频焦点 framework

android 音频焦点 framework
通过本文可了解Android系统的音频架构,基本组件及功能,大概了解常用的播放模式,音频流传输路径,低延迟音频的一些能力,AudioServer服务的初始化。本文仅供交流学习。

1 Android音频系统架构

1.1 Audio Framework架构

Audio系统的核心实现均在native c++层,提供java/C++ API供应用使用Audio部分能力,通过hal隔离硬件差异。

Android Audio Framework系统架构

1.2 车载音频路由架构

google提供的车载音频路由

1.3 音频数据传输路径

音频数据传输路径

2 属性定义

2.1 AudioAttribute

音频系统使用该属性进行音频焦点控制、音频通道路由及音量控制等,一般在应用开发中常用。

  1. AudioAttributes {
  2. mUsage //指定为什么要播放该声音,该声音的作用是什么。用来控制焦点、路由及音量决策(USAGE_MEDIA、 USAGE_VOICE_COMMUNICATION、未知等)
  3. mContentType //指定播放来源的类型(CONTENT_TYPE_MOVIE、CONTENT_TYPE_MUSIC、语音、发音、未知等)
  4. mSource
  5. mFlags //指定音频框架如何对音频播放应用效果
  6. mTags / mFormattedTags / mBundle (key value pairs)
  7. }

2.2 DeviceType

系统音频设备类型主要用于区分系统支持的录音及播音设备能力,一般在audio hal开发中常用。Android系统定义的设备类型如下(定义audio-base.h里):

设备类型描述
AUDIO_DEVICE_OUT_BUS输出设备,Android 的主要输出(车载应用下Android 的所有音频均通过这种方式)
AUDIO_DEVICE_OUT_TELEPHONY_TX输出设备,电话下行数据(车载相关)
AUDIO_DEVICE_OUT_EARPIECE输出设备,听筒(手机)
AUDIO_DEVICE_OUT_SPEAKER输出设备,扬声器(手机)
AUDIO_DEVICE_IN_BUS输入设备,基本的录音设备(车载相关)
AUDIO_DEVICE_IN_FM_TUNER输入设备,收音机的输入(车载相关)
AUDIO_DEVICE_IN_LINE输入设备,AUX IN音频(车载相关)
AUDIO_DEVICE_IN_BLUETOOTH_A2DP输入设备,通过蓝牙接收到的音乐(车载相关)
AUDIO_DEVICE_IN_TELEPHONY_RX输入设备,电话上行数据

3.关键组件

3.1 AudioPolicy

负责音频路由,音频录音或播音设备的选择。是运行在audioserver 进程中一个服务。在手机场景负责插上耳机的音频通道切换,车载场景负责音频的路由即选择何种音源在哪个设备播放。

3.2 AudioFlinger

是Audio数据消费者,消费音频数据并推进Audio hal、并与Audio Hal对接完成一些控制操作。也是运行在audioserver 进程中一个服务。内部涉及的关键模块:

  • Tracks.cpp:音频流管理,可控制音频流的状态,如 start、stop、pause
  • Threads.cpp:回放线程和录制线程;回放线程从 FIFO 读取回放数据并混音处理,然后写数据到输出流设备;录制线程从输入流设备读取录音数据并重采样处理,然后写数据到 FIFO。
  • AudioMixer.cpp:混音处理,包括重采样、音量调节、声道转换等,其中的重采样复用了 AudioResampler;由playback线程 AudioFlinger::MixerThread 直接使用
  • AudioResampler.cpp:重采样处理,可进行采样率转换和声道转换;由录制线程 AudioFlinger::RecordThread 直接使用
  • Effects.cpp:音效处理

3.3 AudioTrack

Audio数据生产者,用于向音频输出设备发送音频数据数,播放的数据为 PCM 格式音频数据,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合,然后输送到Audio HAL中进行播放。

目前Android11同时最多可以创建128个音频流。

4 播放模式

Android目前支持3种播放模式,最常用的是deep buffer模式。具体采用那种播放模式,是在audioPolicy中根据音频流属性AudioAttribute进行控制的。

4.1 Deep buffer playback

Android开发中最常用的播放模式,音乐等对时延要求不高的声音输出采用该模式。边加载边播放,由CPU进行解码,再送入AudioFlinger进行混音播放。处理流程如下:

  1. MediaPlayer将压缩的音频文件通过MediaCodec解成PCM数据。
  2. MediaPlayer通过AudioSink将数据搬运到AudioFlinger。
  3. AudioFlinger做混音及音效处理(audio系统中支持的音效有均衡器、低音增强、环绕声等)。
  4. AudioFlinger将处理好的数据从用户空间(匿名共享内存)拷贝到内核空间(DMA缓冲区)。
  5. DMA控制器将内核空间数据拷贝到对应后端设备。

4.2 Low latency playback

低延迟播放模式,用于按键音、游戏背景音等对时延要求高场景。一次加载完数据,应用一般采用soundpool播放。处理流程如下:

  1. 初试化时就由SoundPool加载压缩文件。
  2. 通过MediaPlayerService将音频文件解成PCM数据
  3. 由SoundPool送给AudioFlinger。

4.3 Compressed offload playback

也是用于音乐播放,但将音频解码的部分放在aDSP进行解码,混音及音效处理,这样可以降低CPU的负载,目前支持的格式有MP3/AAC。处理流程如下:

  1. MediaPlayer不进行音乐文件解码,直接将音频数据转成字节流通过AudioTrack送给AudioFlinger。
  2. AudioFlinger内部通过OffloadThread 将音频数据从用户空间(匿名共享内存)拷贝到内核空间。
  3. aDSP内部接收到数据采用MP3/AAC decoder进行解码工作。
  4. 解码完成,aDSP将音频数据送入内部的Mixer进行混音。
  5. 混音完成送入DMA缓冲区。
  6. DMA控制器将DMA缓冲区拷贝到对应后端设备。

5 低延迟音频

5.1 AAudio

Android提供AAudio进行低延迟音频的开发,通过mmap的方式进行音频数据的传输,对比普通的匿名共享内存+内核缓冲区的方式减少一次内存拷贝。AAudio也提供两种工作模式:

EXCLUSIVE mode

该模式下,应用可直接通过mmap的地址空间,将音频数据写入驱动。

SHARED mode

该模式下,应用需通过AudioServer对接mmap的地址空间,将音频数据写入驱动。但AudioServer不会对音频数据进行混音,音效处理等,因此延迟也会大大减少。

5.2 OpenSL ES

Open Sound Library for Embedded Systems,Android NDK 提供的OpenSL ES API 接口,它支持在 native 层直接处理音频数据,因此可减少java与native之间的数据拷贝工作。

6 Audio服务的初始化

6.1 audioserver deamon进程启动

通过init进程fork出来audioserver进程。

  1. //frameworks/av/media/audioserver/audioserver.rc
  2. service audioserver /system/bin/audioserver
  3. class core
  4. user audioserver
  5. onrestart restart audio-hal-2-0
  6. ioprio rt 4 //设置io优先级
  7. disabled

main_audioserver的main函数被调用,进行AudioFlinger 及 AudioPolicyService服务的启动及初始化。

  1. //frameworks\av\media\audioserver\main_audioserver.cpp
  2. int main(int argc __unused, char **argv)
  3. {
  4. sp<ProcessState> proc(ProcessState::self());
  5. sp<IServiceManager> sm = defaultServiceManager();
  6. ALOGI("ServiceManager: %p", sm.get());
  7. //1.初始化AudioFlinger
  8. AudioFlinger::instantiate();
  9. //2.初始化AudioPolicyService
  10. AudioPolicyService::instantiate();
  11. }

6.2 启动AudioFlinger子服务

AudioFlinger服务继承自BinderService,BnAudioFlinger。

instantiate是BinderService里实现的通用方法,会创建对应AudioFlinger服务, 并加入ServiceManager中。

  1. // frameworks\native\libs\binder\include\binder\BinderService.h
  2. static status_t publish(
  3. bool allowIsolated = false,
  4. int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
  5. sp<IServiceManager> sm(defaultServiceManager());
  6. //创建AudioFlinger服务并加入ServiceManager中
  7. return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
  8. dumpFlags);
  9. }
  10. static void instantiate() { publish(); }

AudioFlinger构造函数如下:

主要进行与audio hal及音效hal服务的绑定。

  1. // frameworks/av/services/audioflinger/AudioFlinger.cpp
  2. AudioFlinger::AudioFlinger()
  3. : BnAudioFlinger(),.....{
  4. // 创建mDevicesFactoryHal示例,与audio hal服务绑定。
  5. mDevicesFactoryHal = DevicesFactoryHalInterface::create();
  6. mEffectsFactoryHal = EffectsFactoryHalInterface::create();
  7. }

audioflinger继承自Refbase,因此也会执行onFirstRef()函数,不过google已经将重要的初始化逻辑迁移进了构造函数执行了。

6.3 启动AudioPolicyService子服务

AudioPolicyService初始化的重要逻辑在其onFirstRef()中实现。

  1. //frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
  2. void AudioPolicyService::onFirstRef()
  3. {
  4. {
  5. Mutex::Autolock _l(mLock);
  6. // start audio commands thread
  7. mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
  8. // start output activity command thread
  9. mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
  10. // 创建AudioPolicyManager,policy中大部分核心工作均在AudioPolicyManager中实现
  11. mAudioPolicyClient = new AudioPolicyClient(this);
  12. mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
  13. }
  14. // load audio processing modules
  15. sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
  16. {
  17. Mutex::Autolock _l(mLock);
  18. mAudioPolicyEffects = audioPolicyEffects;
  19. }
  20. mUidPolicy = new UidPolicy(this);
  21. mUidPolicy->registerSelf();
  22. mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
  23. mSensorPrivacyPolicy->registerSelf();
  24. }

关联文章

Android音频(1)_AudioTrack::createTrack

Android音频(2)_AudioTrack::write | play

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号