Android 音频策略(音频优先级,音频输入输入,声音优先级)

这篇具有很好参考价值的文章主要介绍了Android 音频策略(音频优先级,音频输入输入,声音优先级)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、音频设备

音频设备(/system/core/include/system/audio.h)

enum {
    AUDIO_DEVICE_NONE                          = 0x0,
    /* reserved bits */
    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
    /* output devices */这些是输出声音的设备,就是我们听声音的设备
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,    // 听筒
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,    // 扬声器
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,    // 线控耳机,可以通过耳机控制远端播放、暂停、音量调节等功能的耳机
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,    // 普通耳机,只能听,不能操控播放
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,   // 单声道蓝牙耳机,十进制16
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,   // 车载免提蓝牙设备,十进制32
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,   // 立体声蓝牙耳机,十进制64
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,   // 蓝牙耳机
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,  // 十进制256
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,  // 十进制512
    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,  // HDMI输出
    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,  // 十进制2048
    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000, // 十进制4096
    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000, //USB设备
    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000,
    AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
    /* input devices */ (这里主要是接收声音的设备就是我们对着说话的设备)
    AUDIO_DEVICE_IN_COMMUNICATION         = AUDIO_DEVICE_BIT_IN | 0x1,
    AUDIO_DEVICE_IN_AMBIENT               = AUDIO_DEVICE_BIT_IN | 0x2,
    AUDIO_DEVICE_IN_BUILTIN_MIC           = AUDIO_DEVICE_BIT_IN | 0x4,  //手机自带MIC
    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,     //蓝牙耳机
    AUDIO_DEVICE_IN_WIRED_HEADSET         = AUDIO_DEVICE_BIT_IN | 0x10,  //3.5MM线性耳机
    AUDIO_DEVICE_IN_AUX_DIGITAL           = AUDIO_DEVICE_BIT_IN | 0x20,
    AUDIO_DEVICE_IN_VOICE_CALL            = AUDIO_DEVICE_BIT_IN | 0x40,
    AUDIO_DEVICE_IN_BACK_MIC              = AUDIO_DEVICE_BIT_IN | 0x80,
    AUDIO_DEVICE_IN_REMOTE_SUBMIX         = AUDIO_DEVICE_BIT_IN | 0x100,
    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x200,
    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x400,
    AUDIO_DEVICE_IN_USB_ACCESSORY         = AUDIO_DEVICE_BIT_IN | 0x800,
    AUDIO_DEVICE_IN_USB_DEVICE            = AUDIO_DEVICE_BIT_IN | 0x1000,   //USB耳机
    AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
};

注意:这些设备比较常用的就是HDMI,扬声器,3.5mm圆孔耳机,USB耳机,还有蓝牙耳机。本文也主要针对这些设备的输入和输出策略做出说明。

2、音频策略

Android音频策略主要是在 frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp中,接下来我们看一下如何根据自己的需求在这个文件中调整自己的 音频输入输出策略。

2.1、音频输出策略

音频输出策略是在Engine::getDeviceForStrategyInt这个函数里面:我们主要捡重要的讲

DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
                                              DeviceVector availableOutputDevices,
                                              DeviceVector availableInputDevices,
                                              const SwAudioOutputCollection &outputs) const
{
 DeviceVector devices;
 switch (strategy) {         //这个函数就是在我们播放声音的时候,他负责选择合适的音频输出策略,
                            //所以这里开头就是一个Switch来进行选择
     case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
          ........
     case STRATEGY_SONIFICATION_RESPECTFUL:
          ........
     case STRATEGY_DTMF:
          ........
     case STRATEGY_PHONE:      //这个是比较重要的一个 ,我们在进行腾讯会议,或者打电话通话的时候(也就是语音通话)
                               //一句话:语音通话的声音输出走这个策略
        // Force use of only devices on primary output if:
        // - in call AND
        //   - cannot route from voice call RX OR
        //   - audio HAL version is < 3.0 and TX device is on the primary HW module
        ....省略不重要信息
        // for phone strategy, we first consider the forced use and then the available devices by
        // order of priority
         switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
        case AUDIO_POLICY_FORCE_BT_SCO:(蓝牙通话的时候输出会走这里)
            if (!isInCall() || strategy != STRATEGY_DTMF) {
                devices = availableOutputDevices.getDevicesFromType(
                        AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
                if (!devices.isEmpty()) break;
            }
            devices = availableOutputDevices.getFirstDevicesFromTypes({
                    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO});
            注意:上面这行就是常用选择设备函数,都是后面会出现很多这样的形式,这个也是我们调整策略必须要操作的

            if (!devices.isEmpty()) break;
            // if SCO device is requested but no SCO device is available, fall back to default case
            FALLTHROUGH_INTENDED;

        default:    // FORCE_NONE(如果不是蓝牙通话)
            devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
            if (!devices.isEmpty()) break;
            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
            if (!isInCall() &&
                    (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                     outputs.isA2dpSupported()) {
                devices = availableOutputDevices.getFirstDevicesFromTypes({
                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
                        AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES});
                if (!devices.isEmpty()) break;
            }
            devices = availableOutputDevices.getFirstDevicesFromTypes({
                    AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADSET,
                    AUDIO_DEVICE_OUT_LINE, AUDIO_DEVICE_OUT_USB_HEADSET,
                    AUDIO_DEVICE_OUT_USB_DEVICE});
            //这句就是关键啦,如果你想调整你的音频策略就在这个列表里面去调整,这里就明确了优先级:
         带mic耳机>不带麦的耳机>USB耳机   意思就是如果你同时插着USB耳机和圆孔耳机,然后你又是在打电话,
         ,声音就从圆孔耳机走了。


重点:如果你想调整音频策略怎么做?直接调整列表里的类型顺序就好啦


          ......
        }
    break;

    case STRATEGY_SONIFICATION:
             ............
    case STRATEGY_ENFORCED_AUDIBLE:
             ..........
    case STRATEGY_ACCESSIBILITY:
             ..........
    case STRATEGY_REROUTING:
             ..........
    case STRATEGY_MEDIA: {         //重点又来啦,这里是播放媒体声音时走的策略
        DeviceVector devices2;
        ........
        .......
        前面省略的都是一堆forceuse,如果没有设置强制使用,那么就走到这句,看到没,用扬声器输出啊
        if (devices2.isEmpty()) {
            devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
        }
        //如果你想要调整音频策略,就照着这个写把列表里的字段换成你想要的设备然后往前面放就好了,他是按照顺序向下执行
的,如果device2有了设备后面的就不执行了。

        DeviceVector devices3;
        if (strategy == STRATEGY_MEDIA) {
            // ARC, SPDIF and AUX_LINE can co-exist with others.
            devices3 = availableOutputDevices.getDevicesFromTypes({
                    AUDIO_DEVICE_OUT_HDMI_ARC, AUDIO_DEVICE_OUT_SPDIF, AUDIO_DEVICE_OUT_AUX_LINE});
        }

        devices2.add(devices3);
        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
        // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
        devices.add(devices2);

        // If hdmi system audio mode is on, remove speaker out of output list. //这里是HDMI输出我们是可以设置HDMI
和扬声器同时输出的,就是在最后面可以或device2 | 多个设备。
        if ((strategy == STRATEGY_MEDIA) &&
            (getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO) ==
                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
            devices.remove(devices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER));
        }
       
        }
        } break;

    case STRATEGY_CALL_ASSISTANT:

    default:
        ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
        break;
    }

    if (devices.isEmpty()) {
        ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
        sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
        if (defaultOutputDevice != nullptr) {
            devices.add(defaultOutputDevice);
        }
        ALOGE_IF(devices.isEmpty(),
                 "getDevicesForStrategy() no default device defined");
    }
    ALOGVV("getDevices ForStrategy() strategy %d, device %s",
           strategy, dumpDeviceTypes(devices.types()).c_str());
    return devices;
}

这里就结束了音频的输出策略

2.2、音频输入策略

音频输出策略是在Engine::getDeviceForInputSource这个函数里面:我们主要捡重要的讲

sp<DeviceDescriptor> Engine::getDeviceForInputSource(audio_source_t inputSource) const
{
    const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
    const DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
    const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
    DeviceVector availableDevices = availableInputDevices;
    sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
    DeviceVector availablePrimaryDevices = primaryOutput == nullptr ? DeviceVector()
            : availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
    sp<DeviceDescriptor> device;

    // when a call is active, force device selection to match source VOICE_COMMUNICATION
    // for most other input sources to avoid rerouting call TX audio
    if (isInCall()) {
        switch (inputSource) {
        case AUDIO_SOURCE_DEFAULT:
        case AUDIO_SOURCE_MIC:  //一般会走到这里
        case AUDIO_SOURCE_VOICE_RECOGNITION:
        case AUDIO_SOURCE_UNPROCESSED:
        case AUDIO_SOURCE_HOTWORD:
        case AUDIO_SOURCE_CAMCORDER:
        case AUDIO_SOURCE_VOICE_PERFORMANCE:
            inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;   //也会走这个策略
            break;
        default:
            break;
        }
    }

    switch (inputSource) {
    case AUDIO_SOURCE_DEFAULT:
    case AUDIO_SOURCE_MIC:
        device = availableDevices.getDevice(
                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, String8(""), AUDIO_FORMAT_DEFAULT);
        if (device != nullptr) break;
        if (getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO) {
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            if (device != nullptr) break;
        }
        device = availableDevices.getFirstExistingDevice({
                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
        //打电话应该就是走的mic输入,收录声音就是用的mic,但是可以从列表里面看出来如果有圆孔耳机或者USB耳机,圆孔耳机和
USB耳机的优先级是要比BUILTIN_MIC (麦克风)高的
        break;

    case AUDIO_SOURCE_VOICE_COMMUNICATION: //这个策略就是我们进行腾讯会议这类型语音通话类的app进行声音输入时走
的策略
        // Allow only use of devices on primary input if in call and HAL does not support routing
        // to voice call path.
        if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
                (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
                        String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
            LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
            availableDevices = availablePrimaryDevices;
        }

        switch (getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION)) {
        case AUDIO_POLICY_FORCE_BT_SCO:
            // if SCO device is requested but no SCO device is available, fall back to default case
            device = availableDevices.getDevice(
                    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
            if (device != nullptr) {
                break;
            }
            FALLTHROUGH_INTENDED;

        default:    // FORCE_NONE
            device = availableDevices.getFirstExistingDevice({
                    AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_USB_HEADSET,
                    AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_IN_BUILTIN_MIC});
           //起决定性作用的还是这里,如果想要修改顺序,调整列表里的设备即可
            break;

        case AUDIO_POLICY_FORCE_SPEAKER:
            device = availableDevices.getFirstExistingDevice({
                    AUDIO_DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC});
            break;
        }
        break;

    case AUDIO_SOURCE_VOICE_RECOGNITION:
    case AUDIO_SOURCE_UNPROCESSED:
    case AUDIO_SOURCE_HOTWORD:
    case AUDIO_SOURCE_CAMCORDER:
    case AUDIO_SOURCE_VOICE_DOWNLINK:
    case AUDIO_SOURCE_VOICE_CALL:
    case AUDIO_SOURCE_VOICE_UPLINK:
    case AUDIO_SOURCE_VOICE_PERFORMANCE:
    case AUDIO_SOURCE_REMOTE_SUBMIX:
    case AUDIO_SOURCE_FM_TUNER:
    case AUDIO_SOURCE_ECHO_REFERENCE:
    default:
        ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
        break;
    }
    if (device == nullptr) {
        ALOGV("getDeviceForInputSource() no device found for source %d", inputSource);
        device = availableDevices.getDevice(
                AUDIO_DEVICE_IN_STUB, String8(""), AUDIO_FORMAT_DEFAULT);
        ALOGE_IF(device == nullptr,
                 "getDeviceForInputSource() no default device defined");
    }
    ALOGV_IF(device != nullptr,
             "getDeviceForInputSource()input source %d, device %08x",
             inputSource, device->type());
    return device;
}

这里做了后插优先,就是那个设备最后插入声音就从哪个设备走,包括输入和输出,主要就是通过获取最后插入的设备类型来动态的调整声音优先级即可文章来源地址https://www.toymoban.com/news/detail-761631.html

到了这里,关于Android 音频策略(音频优先级,音频输入输入,声音优先级)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android:persistent和android:priority的区别,对进程优先级有什么影响?

    前言:写的apk因为系统busy给我kill了,(adj 900): kill all background,在AndroidManifest.xml添加android:persistent=\\\"true\\\"后,被甲方要求不能这样做,还是得从adj改,把 priority改成1000 android:persistent和android:priority是两个不同的属性,它们分别用于不同的目的。 android:persistent:用于设置应用组

    2024年01月25日
    浏览(38)
  • Android进程类型及优先级(前台进程/可见进程/服务进程/缓存进程/空进程)

    Android 进程优先级 :前台进程 可见进程 服务进程 缓存进程 空进程 ; 关键优先级进程 : 活动进程 ; 高优先级进程 : 可见进程 , 服务进程 ; 低优先级进程 : 后台进程 , 空进程 ; Android 系统中会尽量保证优先级高的进程的存在时间尽可能长 ;如果资源不足 ( 这里的资源最主要的是内

    2024年04月12日
    浏览(37)
  • c语言[]优先级大于*优先级

    本博文源于笔者正在学习的c语言[]优先级大于*优先级.在定义二维数组时,a+1与[]号结合后,谁的优先级更高,是本博文探讨的话题 想要看看*与[]谁的优先级更高 通过代码发现[]优先级比*号要高(a+1)[1]等价于a+2再取*号就是9了,在第二个pirintf代码中,等价于a[1][1] =6,第三个

    2024年01月20日
    浏览(60)
  • NVIC 简介、抢占优先级和响应优先级

    NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。 如果医院只有医生的话,当看病的人很多时,医生就得安排一下先看谁,后看谁,如果有紧急的病人,那还得让紧急的病人最先来,这个安排先后次序的任务很繁琐,

    2024年02月05日
    浏览(55)
  • 中断处理优先级和中断响应优先级的区别

      中断响应优先级是针对同时到达的中断请求先处理谁的规定。比如A、B同时向CPU发出中断请求,而中断响应优先级是AB,那么CPU就会先处理A,再处理B。   如下图:   中断处理优先级是解决中断嵌套情况下优先处理谁的问题。比如A、B两个中断的中断处理优先级是BA,

    2024年02月11日
    浏览(42)
  • Linux_进程的优先级&&环境变量&&上下文切换&&优先级队列

    什么是优先级? 指定一个进程获取某种资源的先后顺序 本质是进程获取cpu资源的优先顺序 为什么要有优先级 进程访问的资源(CPU)是有限的 操作系统关于调度和优先级的原则:分时操作系统,基本的公平,如果进程因为长时间不被调整,就造成了饥饿问题 Linux的优先级特

    2024年04月09日
    浏览(57)
  • 【CSS】CSS 特性 ( CSS 优先级 | 优先级引入 | 选择器基本权重 )

    定义 CSS 样式时 , 可能出现  多个 类型相同的 规则   定义在 同一个元素上 , 如果 CSS 选择器 相同  ,  执行 CSS 层叠性  , 根据  就近原则  选择执行的样式 , 如 : 出现两个 div 标签选择器 , 都设置 color 文本颜色 ; 如果 CSS 选择器 不同 ,  则需要考虑 CSS 优先级 问题 ,  需要计

    2024年02月10日
    浏览(54)
  • 机械臂多任务逆运动学(优先级同等和存在优先级)

    我们经常使用微分运动学来计算机器人的逆运动学,对于单个任务的机械臂的逆运动学使用的是梯度投影法: 冗余机械臂求解逆运动学解——梯度投影法 但是对于多任务的逆运动学在一般的机器人学里面很少有提及,最近看到了相关的论述,于是做一下笔记整理一下。 设共

    2024年02月16日
    浏览(57)
  • DSCP 与IP 优先级IP优先级,一个月成功收割腾讯、阿里、字节offer

    DSCP DSCP由RFC2474定义,它重新命名了IPv4报头中TOS使用的那1字节和IPv6报头中数据类(TrafficClass)那1字节,新的名字称为DS字段(Differentiated ServicesField)。该字段的作用没有变,仍然被QoS工具用来标记数据。不同的是IPv4使用3比特,而DSCP使用6比特,最低2比特不用。 RFC2474 定义最

    2024年04月12日
    浏览(56)
  • 【STM32】进阶(一):抢占式优先级和响应式优先级(NVIC_PriorityGroupConfig)

    【STM32】STM32单片机总目录 STM32(Cortex-M3)中每个中断源都有两级优先级:抢占式优先级(pre-emption priority)和子优先级(subpriority),子优先级也叫响应式优先级。 望文知义,就是优先级高的可以抢占优先级的中断。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断

    2024年02月12日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包