08.音频系统:第006课_音频系统HAL分析:第001节_音量相关概念

该小节我们开始讲解音量调节,首先我们来回顾一下之前的知识,我们知道android系统可以支持一个或者多个声卡,一般来说,每个声卡有输出,或者输入共功能。
在这里插入图片描述
对于他的输出功能,在AudioFlinger中有一个线程与他对应,这个线程一般来说是MixerThread。这个线程的数据来源有多个APP,该线程最终会把多个APP提供的数据混合在一起,然后发送给声卡,之前我们分析过,应用程序APP中会创建一个AudioTrack,在MixerThread中存在与APP对应的Track,应用 程序吧数据写给AudioTrack,线程通过Track利用共享内存就获得哪些数据,线程混合这些数据之后,进行播放。
这里就会引入一个问题了,一个的APP调节音量,会不会导致硬件的音量被调节,答案是不会:

a. 对于MixerThread
   APP对音量的设置不会影响到声卡的硬件音量,
   而只会影响APP的音频数据的幅值(变小或放大),
   这些音频数据最终被混合后传给声卡
   
   多个APP本身的音量设置互不影响
   
   
b. 对于DirectOutputThread
   同一时间里只有一个APP、只有一个AudioTrack使用它,
   所以该AudioTrack的音量可以被DirectOutputThread直接用来设置硬件音量

再前面的小节中,我们一直讲解的都是MixerThread,没有过多的涉及到DirectOutputThread,在/system/etc/audio_policy.conf中可以看到如下:

      hdmi {
        sampling_rates 44100|48000|192000
        channel_masks AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_7POINT1
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_AUX_DIGITAL
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }

其中的flags AUDIO_OUTPUT_FLAG_DIRECT代表该声音可以被某个应用程序独占。如果我们的应用程序传入AUDIO_OUTPUT_FLAG_DIRECT,表示他需要寻找到一个可以独自控制的声卡,如果找个了对应的声卡,其中flags AUDIO_OUTPUT_FLAG_DIRECT,之后这个应用程序可以独占这个声卡通道,不需要和其他的应用程序进行混音。在大部分android系统中,DirectOutputThread的应用并不多,大部分我们使用的是MixerThread。

在这里我们得到了一个小小的结论,应用程序设置音量时,对音量只是一个软件值,其并不会影响到声卡,我们可以把这个结论继续推广一下,下面是android手机:
在这里插入图片描述

当我按下音量键的时候,会出现第一幅图,可以设置铃声音量,媒体音量,以及闹钟音量。第三幅图示接上了蓝牙耳机的图,可以看到媒体音量的标记消失了,变成了一个蓝牙音量的标记,此时按下音量键,他设置的是蓝牙的音量。再比如,第四幅图,我们在电话的时候,按下音量键,其设置的是通话的音量,同时媒体的音量被静音了。

这些滑动条控制的应该是某一类声音的音量,这些类就称为Stream,从图中可以看到,在android系统中有十几种Stream。当我们想去调节某一个Stream音量的时候,android系统只会出现几个滑动条,对于手机其会有5类滑动条,对于机顶盒,所有的Stream都归为一类(这里利用分组的概念)。

我们知道APP应用创建AudioTrack的时候,会指定StreamType,StreamType分组为strategy,然后获得device再找到output或者说一个播放线程。对Stream进行分类之后称为alias(别名),一个alias包含了多个Stream,对应一个滑动条。当我们设置滑动条的时候,该alias中包含的Stream都会受到影响。

下面是对这些知识的一些总结:

a. APP设置音量时互不影响, 这是AudioTrack volume

b. stream volume
	可以引申出来: 各种stream的音量也可以单独设置、互不影响。
	比如"音乐音量"不应该影响到"来电振铃"、"闹钟"、"通话"的音量。
	
	手机音量控制界面有5种滑动条, 用于设置某种类型的声音音量,
	但是Android系统创建AudioTrack时可以指定10种stream,
	这5种滑动条如何控制10种stream?
	必须分组!在Android源码中称之为"别名", 即alias
	比如在电话中, 以下5种stream的alias都是STREAM_RING,
	那么对应的滑动条即可控制这5种stream的音量
	STREAM_SYSTEM
	STREAM_RING
	STREAM_NOTIFICATION
	STREAM_SYSTEM_ENFORCED
	STREAM_DTMF

APP设置的是AudioTrack的音量,使用滑动条控制的音量是stream音量。下面是APP音量的关系:
APP1音量 = AudioTrack1音量 * stream音量
APP2音量 = AudioTrack2音量 * stream音量
可以看出如果stream音量为0,则所有stream对应的APP都为零。

我们调节音量的时候,只能通过AudioTrack与stream进行控制,那么有没有办法设置有所有的stream与所有的AudioTrack呢?是有的,术语称为master,其会把音量写入到声卡中,这样就设置了所有的音量。当然,一可以和上面的公式一样,再多上一个系数乘积。
以上的公式是简化的(只为大家方便了解),下面是复杂的:

c. 无论是AudioTrack volume、stream volume, 都是单独设置.
   能否通过某个变量影响到所有stream、所有AudioTrack的音量?
   有!这就是 master volume, 这个值是可以直接用来控制声卡的
   
d. 混音:
app1: 
data1_mix = data1_in * master_volume * stream1_volume * AudioTrack1_volume

app2: 
data2_mix = data2_in * master_volume * stream2_volume * AudioTrack2_volume

混合在一起:
data_mix = data1_mix + data2_mix

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/89736322