android_audio_system框架

Audio system architecture

 


AudioTrack

每一种类型的audio stream播放都需要创建一个AudioTrack实例。在AudioTrack的构造函数中主要做2件事:
1, AudioSystem::getOutput()
通过AudioSystem控制流获取一个音频参数(sampleRate/format/channelMask)配置好的output。这个output在不同的模块中有不同的意义:
1.1 output在AudioTrack实例中是AudioFlinger服务中混音线程的ID号。
1.2 output在AudioPolicyManager实例中是AudioFlinger服务中混音线程的ID号。
1.3 output在audioflinger服务中是audio hal层的AudioStreamOut对象。


2, audioFlinger->createTrack()
AudioTrack实例把取到的output传给audioflinger,audioflinger从混音线程池里找到已经创建好的混音线程。
混音线程注意3点:
2.1 每个混音线程都有一个track池。每个tack对象播放一种类型的audio stream。或者说每一种类型的audio strea 对应一个track对象。
2.2 每个混音线程都会关联一个AudioStreamOut对象、MasterVolume和所有audio stream type的数组。
2.3 AudioStreamOut对象可以理解为:本地Codec、蓝牙等音频设备的软件抽象。


混音线程new 一个Track实例,然后添加到自己的track池里。
总结:
创建AudioTrack实例相应的会在AudioFlinger混音线程里创建一个Track实例。
创建AudioStreamOut对象相应的会在AudioFlinger服务中创建一个混音线程。

AudioPolicyService

AudioPolicyService主要完成以下任务
JAVA应用层通过JNI,经由IAudioPolicyService接口,访问AudioPolicyService提供的服务 
输入输出设备的连接状态 
系统的音频策略(strategy)的切换 
音量/音频参数的设置 

AudioPolicyService的静态结构


 
进一步说明:
1. AudioPolicyService继承了IAudioPolicyService接口,这样AudioPolicyService就可以基于Android的Binder机制,向外部提供服务;
2. AudioPolicyService同时也继承了AudioPolicyClientInterface类,他有一个AudioPolicyInterface类的成员指针mpPolicyManager,实际上就是指向了AudioPolicyManager;
3. AudioPolicyManager类继承了AudioPolicyInterface类以便向AudioPolicyService提供服务,反过来同时还有一个AudioPolicyClientInterface指针,该指针在构造函数中被初始化,指向了AudioPolicyService,实际上,AudioPolicyService是通过成员指针mpPolicyManager访问AudioPolicyManager,而AudioPolicyManager则通过AudioPolicyClientInterface(mpClientInterface)访问AudioPolicyService;
4. AudioPolicyService有一个内部线程类AudioCommandThread,顾名思义,所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行;
AudioPolicyManager

AudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。包括音量管理,音频策略(strategy)管理,输入输出设备管理。


输入输出设备管理

音频系统为音频设备定义了一个枚举:AudioSystem::audio_devices,例如:DEVICE_OUT_SPEAKER,DEVICE_OUT_WIRED_HEADPHONE,DEVICE_OUT_BLUETOOTH_A2DP,DEVICE_IN_BUILTIN_MIC,DEVICE_IN_VOICE_CALL等等,每一个枚举值其实对应一个32bit整数的某一个位,所以这些值是可以进行位或操作的,例如我希望同时打开扬声器和耳机,那么可以这样:
newDevice = DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADPHONE;
setOutputDevice(mHardwareOutput, newDevice);
AudioPolicyManager中有两个成员变量:mAvailableOutputDevices和mAvailableInputDevices,他们记录了当前可用的输入和输出设备,当系统检测到耳机或者蓝牙已连接好时,会调用AudioPolicyManager的成员函数:
status_t AudioPolicyManager::setDeviceConnectionState(AudioSystem::audio_devices device,                                                  AudioSystem::device_connection_state state, const char *device_address)
该函数根据传入的device值和state(DEVICE_STATE_AVAILABLE/DEVICE_STATE_UNAVAILABLE)设置mAvailableOutputDevices或者mAvailableInputDevices,然后选择相应的输入或者输出设备。
其他一些相关的函数:
setForceUse()  设置某种场合强制使用某一设备,例如setForceUse(FOR_MEDIA, FORCE_SPEAKER)会在播放音乐时打开扬声器 
startOutput()/stopOutput() 

startInput()/stopInput()


音量管理

AudioPolicyManager提供了一下几个与音量相关的函数:
initStreamVolume(AudioSystem::stream_type stream, int indexMin, int indexMax) 
setStreamVolumeIndex(AudioSystem::stream_type stream, int index) 
getStreamVolumeIndex(AudioSystem::stream_type stream) 
AudioService.java中定义了每一种音频流的最大音量级别:
    private int[] MAX_STREAM_VOLUME = new int[] {
        5,  // STREAM_VOICE_CALL
        7,  // STREAM_SYSTEM
        7,  // STREAM_RING
        15, // STREAM_MUSIC
        7,  // STREAM_ALARM
        7,  // STREAM_NOTIFICATION
        15, // STREAM_BLUETOOTH_SCO
        7,  // STREAM_SYSTEM_ENFORCED
        15, // STREAM_DTMF
        15  // STREAM_TTS
    };
由此可见,电话铃声可以有7个级别的音量,而音乐则可以有15个音量级别,java的代码通过jni,最后调用AudioPolicyManager的initStreamVolume(),把这个数组的内容传入AudioPolicyManager中,这样AudioPolicyManager也就记住了每一个音频流的音量级别。应用程序可以调用setStreamVolumeIndex设置各个音频流的音量级别,setStreamVolumeIndex会把这个整数的音量级别转化为适合人耳的对数级别,然后通过AudioPolicyService的AudioCommandThread,最终会将设置应用到AudioFlinger的相应的Track中。


音频策略管理

我想首先要搞清楚stream_type,device,strategy三者之间的关系:
AudioSystem::stream_type  音频流的类型,一共有10种类型 
AudioSystem::audio_devices  音频输入输出设备,每一个bit代表一种设备,见前面的说明 

AudioPolicyManager::routing_strategy 音频路由策略,可以有4种策略 


 

getStrategy(stream_type)根据stream type,返回对应的routing strategy值,getDeviceForStrategy()则是根据routing strategy,返回可用的device。Android把10种stream type归纳为4种路由策略,然后根据路由策略决定具体的输出设备。


成员变量mOutputs

KeyedVector<audio_io_handle_t, AudioOutputDescriptor *> mOutputs;   // list of output descriptors


这是AudioPolocyManager用管理输出的键值对向量(数组),通常AudioPolocyManager会打开3个输出句柄(audio_io_handle_t),它实际上就是AudioFlinger中某个PlaybackTread的ID。这3个句柄分别是:
mHardwareOutput            // hardware output handler 
mA2dpOutput                   // A2DP output handler 
mDuplicatedOutput          // duplicated output handler: outputs to hardware and A2DP 
可以通过startOutput()把某一个stream type放入到相应的输出中。

AudioCommandThread

   这是AudioPolicyService中的一个线程,主要用于处理音频设置相关的命令。包括:
START_TONE 
STOP_TONE 
SET_VOLUME 
SET_PARAMETERS 
SET_VOICE_VOLUME 
     每种命令的参数有相应的包装:
class ToneData 
class VolumeData 
class ParametersData 
class VoiceVolumeData 
    START_TONE/STOP_TONE:播放电话系统中常用的特殊音调,例如:TONE_DTMF_0,TONE_SUP_BUSY等等。
    SET_VOLUME:最终会调用AudioFlinger进行音量设置
    SET_VOICE_VOLUME:最终会调用AudioFlinger进行电话音量设置
    SET_PARAMETERS:通过一个KeyValuePairs形式的字符串进行参数设置,KeyValuePairs的格式可以这样:
"sampling_rate=44100" 
"channels=2" 
"sampling_rate=4a4100;channels=2"     // 组合形式 
这些KeyValuePairs可以通过AudioPolicyService的成员函数setParameters()传入。









  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值