Android音频系统简介

通过本文可了解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

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

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

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进程。

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

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

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

6.2 启动AudioFlinger子服务

AudioFlinger服务继承自BinderService,BnAudioFlinger。

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

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

static void instantiate() { publish(); }

AudioFlinger构造函数如下:

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

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

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

6.3 启动AudioPolicyService子服务

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

//frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
void AudioPolicyService::onFirstRef()
{
    {
        Mutex::Autolock _l(mLock);
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
        // 创建AudioPolicyManager,policy中大部分核心工作均在AudioPolicyManager中实现
        mAudioPolicyClient = new AudioPolicyClient(this);
        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
    }
    // load audio processing modules
    sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
    {
        Mutex::Autolock _l(mLock);
        mAudioPolicyEffects = audioPolicyEffects;
    }

    mUidPolicy = new UidPolicy(this);
    mUidPolicy->registerSelf();

    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
    mSensorPrivacyPolicy->registerSelf();
}

关联文章

Android音频(1)_AudioTrack::createTrack

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mongo-Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值