08.音频系统:第004课_Android音频系统详解:第008节_AudioTrack创建过程_选择output

应用程序创建的AudioTrack怎么去选择output呢?下面是上小节的图:
在这里插入图片描述
首先应用程序传入声音类型,然后根据声音类型会设置一个属性,然后根据声音的属性确定他的组/类别,找到device,最后在根据device找到对应的output(一个device可能对应多个output,但是只选择一个)。一下其调用过程:

a. APP构造AudioTrack时指定了 stream type
b. AudioTrack::set
c. AudioPolicyManager::getStrategyForAttr
d  AudioPolicyManager::getDeviceForStrategy
e. AudioPolicyManager::getOutputForDevice
       e.1 AudioPolicyManager::getOutputsForDevice
       		audio_stream_type_t audio_attributes_to_stream_type
	   e.2 output = selectOutput(outputs, flags, format);

在这里插入图片描述
期图上的audio_stream_type_t由AudioTrack::set指定,audio_attributes_to_stream_type函数根据audio_stream_type_t设置audio_stream_type_t ,最终转行成Strategy。可以看到11种audio_stream_type_t最终归为6种Strategy,其就是进行了分类/组。最后要根据Strategy得到播放的设备,这是一个比较复杂的过程,即getDeviceForStrategy函数。我们用一个例子对这个函数进行演示。

在日常生活中,使用android手机打电话:
1.如果接上了蓝牙车载导航,优先使用车载导航播放声音。
2…否则,如果插上了耳机,优先使用耳机播放声音。
3.否则,使用手机扬声器播放声音。
4.可以手工选择扬声器等设备(即使接上蓝牙设备,一可以手工选择其他的播放)

假设播放声音的APP指定audio_stream_type_t为AUDIO_STREAM_VOICE_CALL,那么他的Strategy会被设置为STRATEGY_PHONE,我们看看STRATEGY_PHONE对应的device是什么,

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,bool fromCache)
	/*AudioPolicyManagerInterface *mEngine;*/
	mEngine->getDeviceForStrategy(strategy);

其实质就是根据优先级,获得对应的device,在获得device之后,我们就需要根据device去获得Output了,即调用getOutputForDevice函数。前面的小节中,我们分析过,在AudioPolicyManager对象中,存在一个moutputs,其对应的是以及打开的output:

        sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor
        // list of descriptors for outputs currently opened
        
        SwAudioOutputCollection mOutputs;

可以看到每个output都存在一个mOutputs,以及相应的一个mPrimaryOutput,其中的SwAudioOutputDescriptor mPrimaryOutput包含有:

const sp<IOProfile> mProfile;          // I/O profile this output derives from

成员,来自于配置文件,如配置文件中,如开发板下/system/etc/audio_policy.conf文件中存在:

/*描述多个modules*/
audio_hw_modules {
  primary { //一个modules对应一个厂家提供的so文件
    outputs { //一个modules可以有多个output
      primary {//一个output表明他的参数(primary代表默认设备)
        sampling_rates  44100|48000 //采样率
        channel_masks AUDIO_CHANNEL_OUT_STEREO //通道
        formats AUDIO_FORMAT_PCM_16_BIT //格式
        /*有哪些device,如喇叭,耳机等等*/
        devices  AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_SPDIF
        flags AUDIO_OUTPUT_FLAG_PRIMARY
      }

我们可以看到其存在:

devices  AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_SPDIF

即mProfile中表明了该ouput支持哪些Device,现在我们来看看函数getOutputForDevice:

audio_io_handle_t AudioPolicyManager::getOutputForDevice(
non_direct_output:
	/*遍历一下已经打开的mOutputs,其中是否有支持device*/	
	SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
		/*取出outputs中的每一项*/
		for (size_t i = 0; i < openOutputs.size(); i++) 
		{
			/*与支持的device进行比较*/
			if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
				/*r如果支持,则添加到outputs。最终返回一个或者多个output*/
				outputs.add(openOutputs.keyAt(i));
	/*从设备所支持的outputs,中选择一个output:*/
	setOutputDevice(outputDesc, newDevice, false);
		
		

其中setOutputDevice函数中的翻译如下,有可能有多个output,怎么从多个output中选择出最合适的?
//1.
a.APP创建AudioTrack时会传入flag
b.output对应的profile(/system/etc/audio_policy.conf)中也有flag(该文件中每个output节点都存在flag)
c.使用上述a,b的flag进行比较,取出吻合度最高的output。

//2.
如果有多个吻合度相同的情况下,同时primar output支持该设备,则选择他

//3.
如果primar output不支持,则选择所有支持的output中的第一个。

现在我们知道了怎么找到output,找到了output则代表找到了播放线程,该线程会创建一个track,其和应用程序的Audio track对应。那么怎么在这个线程中创建对应的track?下小节进行讲解。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江南才尽,年少无知!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值