08.音频系统:第004课_Android音频系统详解:第002节_以例子说明几个重要概念

该小节我们以几个例子,说明几个重要的概念:stream type, strategy, device, output, profile, module : policy,out flag

我们先画一个图,假设深黑色大框为我们的andriod设备:
在这里插入图片描述

接着声卡,声卡上面有一个喇叭,以及一个耳机/麦克插孔。andriod设备还又蓝牙设备,我们也可以使用蓝牙,接上一个蓝牙耳机。还有一个HDMI接口,HDMI接到电视机可以播放声音。喇叭,耳机,蓝牙耳机,HDMI电视机等等设备,在andriod系统中统称为device。

有输出device,也有输入device,如下:
输出device

    DEVICE_OUT_EARPIECE                 : 听筒
 
    DEVICE_OUT_SPEAKER                  : 扬声器
 
    DEVICE_OUT_WIRED_HEADSET            : 带话筒的耳机
    DEVICE_OUT_WIRED_HEADPHONE          : 不带话筒的耳机
 
    DEVICE_OUT_BLUETOOTH_SCO            : 蓝牙.面向连接(SCO)方式:主要用于话音传输
    DEVICE_OUT_BLUETOOTH_SCO_HEADSET    : 蓝牙耳机,带话筒
    DEVICE_OUT_BLUETOOTH_SCO_CARKIT     : 蓝牙车载设备
    DEVICE_OUT_BLUETOOTH_A2DP           : 蓝牙立体声
    DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: 蓝牙立体声音耳机
    DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER   : 带话筒的
 
    DEVICE_OUT_AUX_DIGITAL              : The audio output device code for S/PDIF or HDMI. S/PDIF的全称是Sony/Philips Digital Interface Format
    DEVICE_OUT_ANLG_DOCK_HEADSET        : 通过基座连接的模拟有线耳机
    DEVICE_OUT_DGTL_DOCK_HEADSET        : 通过基座连接的数字有线耳机
    DEVICE_OUT_FM_HEADPHONE             : 
    DEVICE_OUT_FM_SPEAKER
    DEVICE_OUT_SPEAKER_SSPA2
    DEVICE_OUT_HDMI
    DEVICE_OUT_FM_TRANSMITTER

输入device

        DEVICE_IN_COMMUNICATION         : 手机上的话筒
        DEVICE_IN_AMBIENT               :
        DEVICE_IN_BUILTIN_MIC           : 蓝牙麦克
        DEVICE_IN_BLUETOOTH_SCO_HEADSET : 蓝牙耳机上的话筒
        DEVICE_IN_WIRED_HEADSET         : 有线耳机上的话筒
        DEVICE_IN_AUX_DIGITAL           :
        DEVICE_IN_VOICE_CALL            :
        DEVICE_IN_BACK_MIC              :
        DEVICE_IN_VT_MIC                : 
        DEVICE_IN_FMRADIO               : FM中的输入.

在图中使用红线依次连接连接,我们可以看出,一个声卡在硬件上可能对应多个device,如/dev/pcmC0D0p对应着多个device,但我们需要从喇叭播放时,或者中耳机播放时,我们需要重新设置一下声卡。

一个声卡上,多个device的组合就是一个output(该概念,在上小节有提及)。output概念如下:
1.output是多个device的组合
2.这些device(喇叭,耳机),属于同一硬件上不同的端口。
3.这些device支持同样的参数,如:采样率,通道。
即output是具有相同特性device的组合。这些output与device都属于硬件的概念,

我们想去操作一个硬件,在安卓系统中,我们是使用hadware module(图示绿色方框)去操作硬件。那么问题就来了。
1.hw moddle的名字是什么?是哪个.so文件
2.一个moddle他支持哪些output。
3.output支持哪些device,参数是什么?(如支持哪些采样率)
以上问题我们都需要回答,所以有一个配置件:/system/audio_policy.conf,

先在我们引入了三个概念:
1.module:硬件操作库,用来操作device
2.output:支持相同参数的,来自同一硬件的device
3.device:喇叭,耳机等等
然后由上,引出profile(配置),即/system/audio_policy.conf文件。用来描述output(如:采样率等等)。

output表示实际上,可以支持哪些设备,即参数。如我们指定一个output,其可以支持喇叭,也可以支持耳机,但是实际上,如果没有接上耳机,那么他只能支持喇叭,只有我们接上耳机的时候,才能同时支持耳机和喇叭。
output与prifule的区别如下“”:
在这里插入图片描述
prifule其实来自配置文件,而output是来自实际的情况。在该小节开头说要讲解的概念stream type, strategy, device, output, profile, module : policy,out flag。device, output, profile, module 已经讲解完成了。还剩下stream type与 strategy。

在我们使用android系统的时候,我们知道,我们没有插入耳机的时候,其声音会从喇叭播放出来,当我们插上耳机的时候,声音会从耳机播放出来。

如果写应用程序的APP,一个播放器。其有可能从耳机播放,也可能是从喇叭播放。那么播放音乐时有那么多的路径,APP该怎么办。实际上APP是不用理会的。

在有的国家在拍照的时候,会强制发出声音,为了防止偷拍,那么写应用程序的人,让他播放一个声音,这个声音时从喇叭播放,你插上耳机的时候,其也是从喇叭播放,接上蓝牙耳机也是一样,其也会从喇叭播放。这样才能起到强制发出声音的作用。那么写应用程序的人,怎么去管理这些路径?

实际上应用程序也管不到,只能表明声音的类型,这个声音的类型就称为stream type,存在以下类型(使用java和c++都是一一对应的,即c++代码与java代码都可以使用以下宏):

Stream Type						Description
STREAM_VOICE_CALL				电话语音
STREAM_SYSTEM					系统声音
STREAM_RING						铃声声音,如来电铃声、闹钟铃声等
STREAM_MUSIC					音乐声音
STREAM_ALARM					警告音
STREAM_NOTIFICATION				通知音
STREAM_DTMF						DTMF音(拨号盘按键音)

这里只粘贴了一些常用的,有太多的Stream Type,我们需要为每个类型播放的声音,找到他们播放的硬件,由于太多的类型,所以会进行分组Strategy(具有相同行为的Stream:播放的设备一样,device相同,播放优先级相同)。
打开AudioPolicyManagerBase.cpp文件,我们可以看到:

AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
        AudioSystem::stream_type stream) {
    // stream to strategy mapping
    switch (stream) {
    case AudioSystem::VOICE_CALL:
    case AudioSystem::BLUETOOTH_SCO:
        return STRATEGY_PHONE;
    case AudioSystem::RING:
    case AudioSystem::ALARM:
        return STRATEGY_SONIFICATION;
    case AudioSystem::NOTIFICATION:
        return STRATEGY_SONIFICATION_RESPECTFUL;
    case AudioSystem::DTMF:
        return STRATEGY_DTMF;
    default:
        ALOGE("unknown stream type");
    case AudioSystem::SYSTEM:
        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
        // while key clicks are played produces a poor result
    case AudioSystem::TTS:
    case AudioSystem::MUSIC:
        return STRATEGY_MEDIA;
    case AudioSystem::ENFORCED_AUDIBLE:
        return STRATEGY_ENFORCED_AUDIBLE;
    }
}

通过以上分析,我们做出如下总结:
Android系统里使用hardware module来访问硬件, 比如声卡
声卡上有喇叭、耳机等等,称为device
为了便于管理, 把一个设备上具有相同参数的一组device称为output,
一个module能支持哪些output,一个output能支持哪些device,使用配置文件/system/etc/audio_policy.conf来描述

app要播放声音, 要指定声音类型: stream type
有那么多的类型, 来来来, 先看它属于哪一类(策略): strategy
根据strategy确定要用什么设备播放: device, 喇叭、耳机还是蓝牙?
根据device确定output, 进而知道对应的playbackthread,
把声音数据传给这个thread

out flag是什么呢?如我们有一个特殊的APP(专业APP),其只给HDMI接口发送声音,这时候我们设置out flag = AUDIO_OUTPUT_FLAG_DIRECT,其out flag 可选如下:

AUDIO_OUTPUT_FLAG_DIRECT				表示音频流直接输出到音频设备,不需要软件混音,一般用于 HDMI 设备声音输出
AUDIO_OUTPUT_FLAG_PRIMARY				表示音频流需要输出到主输出设备,一般用于铃声类声音
AUDIO_OUTPUT_FLAG_FAST					表示音频流需要快速输出到音频设备,一般用于按键音、游戏背景音等对时延要求高的场景
AUDIO_OUTPUT_FLAG_DEEP_BUFFER			表示音频流输出可以接受较大的时延,一般用于音乐、视频播放等对时延要求不高的场景
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD		表示音频流没有经过软件解码,需要输出到硬件解码器,由硬件解码器进行解码

其会导致,最终的声音不需要混音,直接输出到HDMI对应的divice。

一个stream如何最终选择到一个device,
这些stream如何互相影响(一个高优先级的声音会使得其他声音静音),
等等等, 统称为policy (政策)

猜你喜欢

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