Android audio音频流数据异常问题怎么解决(android,audio,开发技术)

时间:2024-04-28 09:02:07 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

这篇文章主要介绍“Androidaudio音频流数据异常问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Androidaudio音频流数据异常问题怎么解决”文章能帮助大家解决问题。

    一、背景

    Android 系统的开发过程当中,音频异常问题通常有如下几类,无声,调节不了声音,爆音,声音卡顿,声音效果异常(忽大忽小,低音缺失等)等。

    尤其声音效果这部分问题通常从日志上信息量较少,相对难定位根因。想要分析此类问题,便需要对声音传输链路有一定的了解,能够在链路中对各节点的音频流进行采集,通过对比分析音频流的实际效果来缩小问题范围,找出原因。

    网上已经有很多音频框架图和相关的大致介绍,这里就不再赘述,只分享下音频流的传输链路,和我们可以重点其中的哪些关键节点,来帮助我们快速定位问题。

    二、Android Audio 音频系统

    1. 音频链路

    抓取音频链路当中的音频数据是分析声音异常问题的有效方法,通过抓取不同节点的声音数据,可以帮助我们快速定位问题发生的原因。下面先来看一张安卓官方的音频系统框架图:

    Android audio音频流数据异常问题怎么解决

    Audio 音频数据流整体上经过 APPframeworkhalkernel driver四个部分,从应用端发起,不管调用 audio 还是 media 接口,最终还是会由 AudioTrack 将数据往下传,经由 AudioFlinger 启动 MixThreadDirectThread 等,将多个 APP 的声音混合到一起,将声音传输到 hal 层。

    系统会根据音频流类型 stream 和音频策略 strategy 来选择对应的 output,从而找到对应的 module,将音频数据传输给 hal 层音频库 so 做声音相关的处理并传给 audio driver

    音频流传输路径图:

    Android audio音频流数据异常问题怎么解决

    从上述的音频流流程可以看到,我们首先要确认,当前音频流是经由哪一个 hal 层库做处理,是 primaryusb 还是三方 so 等,然后可以在对应的节点抓取相应的音频信息分析。

    可以根据自己的需要在音频流的部分节点埋下相应的 dump 指令,将 pcm 写入到相应的节点当中。

    2. 音频链路关键节点:

      AudioTrack:应用写入音频流的起点,有 MODE_STATICMODE_STREAM 模式,通过 write 接口将数据写入。

    此节点写入的数据是由应用层最原始的音频数据。   

    AudioFlinger:负责启动线程完成各个应用的混音,音频流声音调节等工作。设备同时可能存在多个应用播放声音,这时便需要将各个应用的声音混合在一起,并且做音量的调节。

    例如在车载场景中,音乐应用播放歌曲和地图应用语音导航的声音需要同时存在,便使用到了混音的功能,当导航语音响起时,歌曲声音有一个明显的变小,便可以设置音频流的音量。   

    audio_hw_halhal 层音频处理的入口,为 Android 原生逻辑,各厂家需要按照规范实现其中的音频设置等接口,声明 HAL_MODULE_INFO_SYM 结构体,实现 legacy_adev_open 方法,承接起连接 frameworkaudio driver 的作用,完成一些音效算法等逻辑处理。

    AudioStreamOut:和 audio_hw_hal 一样,是Android 给厂家提供的通用类,厂家在实现自己的通用库实现时需要可以按照谷歌规范,然后在相应的音频处理接口中实现自己的对音频流做音效,增益等处理。

    audio_hw_hal.cpp 代码如下,不同厂家这里的实现略有差异,这里只截取部分 AOSP 源码。

    Android audio音频流数据异常问题怎么解决

    Android audio音频流数据异常问题怎么解决

    3. 音频库的选择

    从音频流传输路径图可以看到,如何找到是哪一个音频 so 处理声音也是至关重要的。我们知道,系统对于应用层曝光的其实只有通道类型。

    举个例子:当用户打电话时,可以使用通话通道 STREAM_VOICE_CALL,当用户播放视频时,可以使用媒体通道 STREAM_MUSIC,当发送通知时,可以使用 STREAM_NOTIFICATION

    那传入这些通道的声音数据,又是怎么最终流向到具体的硬件输出设备呢?

    Android audio音频流数据异常问题怎么解决

    以媒体通道为例,当应用层将音频数据往 MUSIC 通道写入时,系统便会根据 StreamType 来生成相应的

    audio_attributes_t(.usage = AUDIO_USAGE_MEDIA, .content_type = AUDIO_CONTENT_TYPE_MUSIC})

    再通过 audio_attributes_t 来获取对应的 ProductStrategySTRATEGY_MEDIA),最后在拿到对应的 outputDevice

    Android 原生逻辑outputDevice 的选择在 Engine.cpp 上,会具体根据当前设备是否有接蓝牙,耳机等外设,按照优先级来选择相应的外设设备作为输出,可能是耳机 (AUDIO_DEVICE_OUT_WIRED_HEADSET),听筒(AUDIO_DEVICE_OUT_EARPIECE),喇叭(AUDIO_DEVICE_OUT_SPEAKER)等。

    具体可以看 getDeviceForStrategyInt 方法。

    /**Copyright(C)2015TheAndroidOpenSourceProject**LicensedundertheApacheLicense,Version2.0(the"License");*youmaynotusethisfileexceptincompliancewiththeLicense.*YoumayobtainacopyoftheLicenseat**http://www.apache.org/licenses/LICENSE-2.0**Unlessrequiredbyapplicablelaworagreedtoinwriting,software*distributedundertheLicenseisdistributedonan"ASIS"BASIS,*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.*SeetheLicenseforthespecificlanguagegoverningpermissionsand*limitationsundertheLicense.*/#defineLOG_TAG"APM::AudioPolicyEngine"//#defineLOG_NDEBUG0//#defineVERY_VERBOSE_LOGGING#ifdefVERY_VERBOSE_LOGGING#defineALOGVVALOGV#else#defineALOGVV(a...)do{}while(0)#endif#include"Engine.h"#include<AudioPolicyManagerObserver.h>#include<AudioPort.h>#include<IOProfile.h>#include<policy.h>#include<utils/String8.h>#include<utils/Log.h>namespaceandroid{namespaceaudio_policy{Engine::Engine():mManagerInterface(this),mPhoneState(AUDIO_MODE_NORMAL),mApmObserver(NULL){for(inti=0;i<AUDIO_POLICY_FORCE_USE_CNT;i++){mForceUse[i]=AUDIO_POLICY_FORCE_NONE;}}Engine::~Engine(){}voidEngine::setObserver(AudioPolicyManagerObserver*observer){ALOG_ASSERT(observer!=NULL,"InvalidAudioPolicyManagerobserver");mApmObserver=observer;}status_tEngine::initCheck(){return(mApmObserver!=NULL)?NO_ERROR:NO_INIT;}status_tEngine::setPhoneState(audio_mode_tstate){ALOGV("setPhoneState()state%d",state);if(state<0||state>=AUDIO_MODE_CNT){ALOGW("setPhoneState()invalidstate%d",state);returnBAD_VALUE;}if(state==mPhoneState){ALOGW("setPhoneState()settingsamestate%d",state);returnBAD_VALUE;}//storepreviousphonestateformanagementofsonificationstrategybelowintoldState=mPhoneState;mPhoneState=state;if(!is_state_in_call(oldState)&&is_state_in_call(state)){ALOGV("EnteringcallinsetPhoneState()");mApmObserver->getVolumeCurves().switchVolumeCurve(AUDIO_STREAM_VOICE_CALL,AUDIO_STREAM_DTMF);}elseif(is_state_in_call(oldState)&&!is_state_in_call(state)){ALOGV("ExitingcallinsetPhoneState()");mApmObserver->getVolumeCurves().restoreOriginVolumeCurve(AUDIO_STREAM_DTMF);}returnNO_ERROR;}status_tEngine::setForceUse(audio_policy_force_use_tusage,audio_policy_forced_cfg_tconfig){switch(usage){caseAUDIO_POLICY_FORCE_FOR_COMMUNICATION:if(config!=AUDIO_POLICY_FORCE_SPEAKER&&config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_COMMUNICATION",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_MEDIA:if(config!=AUDIO_POLICY_FORCE_HEADPHONES&&config!=AUDIO_POLICY_FORCE_BT_A2DP&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_ANALOG_DOCK&&config!=AUDIO_POLICY_FORCE_DIGITAL_DOCK&&config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_NO_BT_A2DP&&config!=AUDIO_POLICY_FORCE_SPEAKER){ALOGW("setForceUse()invalidconfig%dforFOR_MEDIA",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_RECORD:if(config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_RECORD",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_DOCK:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_BT_CAR_DOCK&&config!=AUDIO_POLICY_FORCE_BT_DESK_DOCK&&config!=AUDIO_POLICY_FORCE_WIRED_ACCESSORY&&config!=AUDIO_POLICY_FORCE_ANALOG_DOCK&&config!=AUDIO_POLICY_FORCE_DIGITAL_DOCK){ALOGW("setForceUse()invalidconfig%dforFOR_DOCK",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_SYSTEM:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_SYSTEM_ENFORCED){ALOGW("setForceUse()invalidconfig%dforFOR_SYSTEM",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED){ALOGW("setForceUse()invalidconfig%dforHDMI_SYSTEM_AUDIO",config);}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:if(config!=AUDIO_POLICY_FORCE_NONE&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS&&config!=AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL){ALOGW("setForceUse()invalidconfig%dforENCODED_SURROUND",config);returnBAD_VALUE;}mForceUse[usage]=config;break;caseAUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:if(config!=AUDIO_POLICY_FORCE_BT_SCO&&config!=AUDIO_POLICY_FORCE_NONE){ALOGW("setForceUse()invalidconfig%dforFOR_VIBRATE_RINGING",config);returnBAD_VALUE;}mForceUse[usage]=config;break;default:ALOGW("setForceUse()invalidusage%d",usage);break;//TODOreturnBAD_VALUE?}returnNO_ERROR;}routing_strategyEngine::getStrategyForStream(audio_stream_type_tstream){//streamtostrategymappingswitch(stream){caseAUDIO_STREAM_VOICE_CALL:caseAUDIO_STREAM_BLUETOOTH_SCO:returnSTRATEGY_PHONE;caseAUDIO_STREAM_RING:caseAUDIO_STREAM_ALARM:returnSTRATEGY_SONIFICATION;caseAUDIO_STREAM_NOTIFICATION:returnSTRATEGY_SONIFICATION_RESPECTFUL;caseAUDIO_STREAM_DTMF:returnSTRATEGY_DTMF;default:ALOGE("unknownstreamtype%d",stream);caseAUDIO_STREAM_SYSTEM://NOTE:SYSTEMstreamusesMEDIAstrategybecausemutingmusicandswitchingoutputs//whilekeyclicksareplayedproducesapoorresultcaseAUDIO_STREAM_MUSIC:returnSTRATEGY_MEDIA;caseAUDIO_STREAM_ENFORCED_AUDIBLE:returnSTRATEGY_ENFORCED_AUDIBLE;caseAUDIO_STREAM_TTS:returnSTRATEGY_TRANSMITTED_THROUGH_SPEAKER;caseAUDIO_STREAM_ACCESSIBILITY:returnSTRATEGY_ACCESSIBILITY;caseAUDIO_STREAM_REROUTING:returnSTRATEGY_REROUTING;}}routing_strategyEngine::getStrategyForUsage(audio_usage_tusage){//usagetostrategymappingswitch(usage){caseAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:returnSTRATEGY_ACCESSIBILITY;caseAUDIO_USAGE_MEDIA:caseAUDIO_USAGE_GAME:caseAUDIO_USAGE_ASSISTANT:caseAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:caseAUDIO_USAGE_ASSISTANCE_SONIFICATION:returnSTRATEGY_MEDIA;caseAUDIO_USAGE_VOICE_COMMUNICATION:returnSTRATEGY_PHONE;caseAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:returnSTRATEGY_DTMF;caseAUDIO_USAGE_ALARM:caseAUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:returnSTRATEGY_SONIFICATION;caseAUDIO_USAGE_NOTIFICATION:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:caseAUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:caseAUDIO_USAGE_NOTIFICATION_EVENT:returnSTRATEGY_SONIFICATION_RESPECTFUL;caseAUDIO_USAGE_UNKNOWN:default:returnSTRATEGY_MEDIA;}}audio_devices_tEngine::getDeviceForStrategy(routing_strategystrategy)const{DeviceVectoravailableOutputDevices=mApmObserver->getAvailableOutputDevices();DeviceVectoravailableInputDevices=mApmObserver->getAvailableInputDevices();constSwAudioOutputCollection&outputs=mApmObserver->getOutputs();returngetDeviceForStrategyInt(strategy,availableOutputDevices,availableInputDevices,outputs,(uint32_t)AUDIO_DEVICE_NONE);}audio_devices_tEngine::getDeviceForStrategyInt(routing_strategystrategy,DeviceVectoravailableOutputDevices,DeviceVectoravailableInputDevices,constSwAudioOutputCollection&outputs,uint32_toutputDeviceTypesToIgnore)const{uint32_tdevice=AUDIO_DEVICE_NONE;uint32_tavailableOutputDevicesType=availableOutputDevices.types()&~outputDeviceTypesToIgnore;switch(strategy){caseSTRATEGY_TRANSMITTED_THROUGH_SPEAKER:device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;break;caseSTRATEGY_SONIFICATION_RESPECTFUL:if(isInCall()||outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)){device=getDeviceForStrategyInt(STRATEGY_SONIFICATION,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}else{boolmedia_active_locally=outputs.isStreamActiveLocally(AUDIO_STREAM_MUSIC,SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)||outputs.isStreamActiveLocally(AUDIO_STREAM_ACCESSIBILITY,SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY);//routingissameasmediawithoutthe"remote"devicedevice=getDeviceForStrategyInt(STRATEGY_MEDIA,availableOutputDevices,availableInputDevices,outputs,AUDIO_DEVICE_OUT_REMOTE_SUBMIX|outputDeviceTypesToIgnore);//ifnomediaisplayingonthedevice,checkformandatoryuseof"safe"speaker//whenmediawouldhaveplayedonspeaker,andthesafespeakerpathisavailableif(!media_active_locally&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}}break;caseSTRATEGY_DTMF:if(!isInCall()){//whenoffcall,DTMFstrategyfollowsthesamerulesasMEDIAstrategydevice=getDeviceForStrategyInt(STRATEGY_MEDIA,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}//whenincall,DTMFandPHONEstrategiesfollowthesamerules//FALLTHROUGHcaseSTRATEGY_PHONE://Forceuseofonlydevicesonprimaryoutputif://-incallAND//-cannotroutefromvoicecallRXOR//-audioHALversionis<3.0andTXdeviceisontheprimaryHWmoduleif(getPhoneState()==AUDIO_MODE_IN_CALL){audio_devices_ttxDevice=getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);sp<AudioOutputDescriptor>primaryOutput=outputs.getPrimaryOutput();audio_devices_tavailPrimaryInputDevices=availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());//TODO:getPrimaryOutputreturnonlydevicesfromfirstmodulein//audio_policy_configuration.xml,hearingaidisnotthere,butit's//aprimarydevice//FIXME:thisisnottherightwayofsolvingthisproblemaudio_devices_tavailPrimaryOutputDevices=(primaryOutput->supportedDevices()|AUDIO_DEVICE_OUT_HEARING_AID)&availableOutputDevices.types();if(((availableInputDevices.types()&AUDIO_DEVICE_IN_TELEPHONY_RX&~AUDIO_DEVICE_BIT_IN)==0)||(((txDevice&availPrimaryInputDevices&~AUDIO_DEVICE_BIT_IN)!=0)&&(primaryOutput->getAudioPort()->getModuleVersionMajor()<3))){availableOutputDevicesType=availPrimaryOutputDevices;}}//forphonestrategy,wefirstconsidertheforceduseandthentheavailabledevicesby//orderofpriorityswitch(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]){caseAUDIO_POLICY_FORCE_BT_SCO:if(!isInCall()||strategy!=STRATEGY_DTMF){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO;if(device)break;//ifSCOdeviceisrequestedbutnoSCOdeviceisavailable,fallbacktodefaultcase//FALLTHROUGHdefault://FORCE_NONEdevice=availableOutputDevicesType&AUDIO_DEVICE_OUT_HEARING_AID;if(device)break;//whennotinaphonecall,phonestrategyshouldrouteSTREAM_VOICE_CALLtoA2DPif(!isInCall()&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADPHONE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_LINE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;if(device)break;if(!isInCall()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_EARPIECE;break;caseAUDIO_POLICY_FORCE_SPEAKER://whennotinaphonecall,phonestrategyshouldrouteSTREAM_VOICE_CALLto//A2DPspeakerwhenforcingtospeakeroutputif(!isInCall()&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;if(device)break;}if(!isInCall()){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;if(device)break;device=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;if(device)break;}device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;break;}break;caseSTRATEGY_SONIFICATION://Ifincall,justselecttheSTRATEGY_PHONEdevice:Therestofthebehaviorishandledby//handleIncallSonification().if(isInCall()||outputs.isStreamActiveLocally(AUDIO_STREAM_VOICE_CALL)){device=getDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}//FALLTHROUGHcaseSTRATEGY_ENFORCED_AUDIBLE://strategySTRATEGY_ENFORCED_AUDIBLEusessameroutingpolicyasSTRATEGY_SONIFICATION//except://-whenincallwhereitdoesn'tdefaulttoSTRATEGY_PHONEbehavior//-incountrieswherenotenforcedinwhichcaseitfollowsSTRATEGY_MEDIAif((strategy==STRATEGY_SONIFICATION)||(mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]==AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)){device=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}//ifSCOheadsetisconnectedandwearetoldtouseit,playringtoneover//speakerandBTSCOif((availableOutputDevicesType&AUDIO_DEVICE_OUT_ALL_SCO)!=0){uint32_tdevice2=AUDIO_DEVICE_NONE;device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_SCO;}//UseONLYBluetoothSCOoutputwhenringinginvibrationmodeif(!((mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]==AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)&&(strategy==STRATEGY_ENFORCED_AUDIBLE))){if(mForceUse[AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING]==AUDIO_POLICY_FORCE_BT_SCO){if(device2!=AUDIO_DEVICE_NONE){device=device2;break;}}}//UsebothBluetoothSCOandphonedefaultoutputwhenringinginnormalmodeif(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]==AUDIO_POLICY_FORCE_BT_SCO){if((strategy==STRATEGY_SONIFICATION)&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}if(device2!=AUDIO_DEVICE_NONE){device|=device2;break;}}}//Theseconddeviceusedforsonificationisthesameasthedeviceusedbymediastrategy//FALLTHROUGHcaseSTRATEGY_ACCESSIBILITY:if(strategy==STRATEGY_ACCESSIBILITY){//donotrouteaccessibilitypromptstoadigitaloutputcurrentlyconfiguredwitha//compressedformatastheywouldlikelynotbemixedanddropped.for(size_ti=0;i<outputs.size();i++){sp<AudioOutputDescriptor>desc=outputs.valueAt(i);audio_devices_tdevices=desc->device()&(AUDIO_DEVICE_OUT_HDMI|AUDIO_DEVICE_OUT_SPDIF|AUDIO_DEVICE_OUT_HDMI_ARC);if(desc->isActive()&&!audio_is_linear_pcm(desc->mFormat)&&devices!=AUDIO_DEVICE_NONE){availableOutputDevicesType=availableOutputDevices.types()&~devices;}}availableOutputDevices=availableOutputDevices.getDevicesFromType(availableOutputDevicesType);if(outputs.isStreamActive(AUDIO_STREAM_RING)||outputs.isStreamActive(AUDIO_STREAM_ALARM)){returngetDeviceForStrategyInt(STRATEGY_SONIFICATION,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}if(isInCall()){returngetDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);}}//Forothercases,STRATEGY_ACCESSIBILITYbehaveslikeSTRATEGY_MEDIA//FALLTHROUGH//FIXME:STRATEGY_REROUTINGfollowSTRATEGY_MEDIAfornowcaseSTRATEGY_REROUTING:caseSTRATEGY_MEDIA:{uint32_tdevice2=AUDIO_DEVICE_NONE;if(strategy!=STRATEGY_SONIFICATION){//nosonificationonremotesubmix(e.g.WFD)if(availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,String8("0"))!=0){device2=availableOutputDevices.types()&AUDIO_DEVICE_OUT_REMOTE_SUBMIX;}}if(isInCall()&&(strategy==STRATEGY_MEDIA)){device=getDeviceForStrategyInt(STRATEGY_PHONE,availableOutputDevices,availableInputDevices,outputs,outputDeviceTypesToIgnore);break;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_HEARING_AID;}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]!=AUDIO_POLICY_FORCE_NO_BT_A2DP)&&outputs.isA2dpSupported()){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;}}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]==AUDIO_POLICY_FORCE_SPEAKER)){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADPHONE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_LINE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_WIRED_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_ACCESSORY;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_USB_DEVICE;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;}if((device2==AUDIO_DEVICE_NONE)&&(strategy!=STRATEGY_SONIFICATION)){//nosonificationonauxdigital(e.g.HDMI)device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_DIGITAL;}if((device2==AUDIO_DEVICE_NONE)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK]==AUDIO_POLICY_FORCE_ANALOG_DOCK)){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;}if(device2==AUDIO_DEVICE_NONE){device2=availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER;}intdevice3=AUDIO_DEVICE_NONE;if(strategy==STRATEGY_MEDIA){//ARC,SPDIFandAUX_LINEcanco-existwithothers.device3=availableOutputDevicesType&AUDIO_DEVICE_OUT_HDMI_ARC;device3|=(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPDIF);device3|=(availableOutputDevicesType&AUDIO_DEVICE_OUT_AUX_LINE);}device2|=device3;//deviceisDEVICE_OUT_SPEAKERifwecomefromcaseSTRATEGY_SONIFICATIONor//STRATEGY_ENFORCED_AUDIBLE,AUDIO_DEVICE_NONEotherwisedevice|=device2;//Ifhdmisystemaudiomodeison,removespeakeroutofoutputlist.if((strategy==STRATEGY_MEDIA)&&(mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]==AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)){device&=~AUDIO_DEVICE_OUT_SPEAKER;}//forSTRATEGY_SONIFICATION://ifSPEAKERwasselected,andSPEAKER_SAFEisavailable,useSPEAKER_SAFEinsteadif((strategy==STRATEGY_SONIFICATION)&&(device&AUDIO_DEVICE_OUT_SPEAKER)&&(availableOutputDevicesType&AUDIO_DEVICE_OUT_SPEAKER_SAFE)){device|=AUDIO_DEVICE_OUT_SPEAKER_SAFE;device&=~AUDIO_DEVICE_OUT_SPEAKER;}}break;default:ALOGW("getDeviceForStrategy()unknownstrategy:%d",strategy);break;}if(device==AUDIO_DEVICE_NONE){ALOGV("getDeviceForStrategy()nodevicefoundforstrategy%d",strategy);device=mApmObserver->getDefaultOutputDevice()->type();ALOGE_IF(device==AUDIO_DEVICE_NONE,"getDeviceForStrategy()nodefaultdevicedefined");}ALOGVV("getDeviceForStrategy()strategy%d,device%x",strategy,device);returndevice;}audio_devices_tEngine::getDeviceForInputSource(audio_source_tinputSource)const{constDeviceVector&availableOutputDevices=mApmObserver->getAvailableOutputDevices();constDeviceVector&availableInputDevices=mApmObserver->getAvailableInputDevices();constSwAudioOutputCollection&outputs=mApmObserver->getOutputs();audio_devices_tavailableDeviceTypes=availableInputDevices.types()&~AUDIO_DEVICE_BIT_IN;uint32_tdevice=AUDIO_DEVICE_NONE;//whenacallisactive,forcedeviceselectiontomatchsourceVOICE_COMMUNICATION//formostotherinputsourcestoavoidreroutingcallTXaudioif(isInCall()){switch(inputSource){caseAUDIO_SOURCE_DEFAULT:caseAUDIO_SOURCE_MIC:caseAUDIO_SOURCE_VOICE_RECOGNITION:caseAUDIO_SOURCE_UNPROCESSED:caseAUDIO_SOURCE_HOTWORD:caseAUDIO_SOURCE_CAMCORDER:inputSource=AUDIO_SOURCE_VOICE_COMMUNICATION;break;default:break;}}switch(inputSource){caseAUDIO_SOURCE_VOICE_UPLINK:if(availableDeviceTypes&AUDIO_DEVICE_IN_VOICE_CALL){device=AUDIO_DEVICE_IN_VOICE_CALL;break;}break;caseAUDIO_SOURCE_DEFAULT:caseAUDIO_SOURCE_MIC:if(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_A2DP){device=AUDIO_DEVICE_IN_BLUETOOTH_A2DP;}elseif((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]==AUDIO_POLICY_FORCE_BT_SCO)&&(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_VOICE_COMMUNICATION://AllowonlyuseofdevicesonprimaryinputifincallandHALdoesnotsupportrouting//tovoicecallpath.if((getPhoneState()==AUDIO_MODE_IN_CALL)&&(availableOutputDevices.types()&AUDIO_DEVICE_OUT_TELEPHONY_TX)==0){sp<AudioOutputDescriptor>primaryOutput=outputs.getPrimaryOutput();availableDeviceTypes=availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle())&~AUDIO_DEVICE_BIT_IN;}switch(mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]){caseAUDIO_POLICY_FORCE_BT_SCO://ifSCOdeviceisrequestedbutnoSCOdeviceisavailable,fallbacktodefaultcaseif(availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;break;}//FALLTHROUGHdefault://FORCE_NONEif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_POLICY_FORCE_SPEAKER:if(availableDeviceTypes&AUDIO_DEVICE_IN_BACK_MIC){device=AUDIO_DEVICE_IN_BACK_MIC;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;}break;caseAUDIO_SOURCE_VOICE_RECOGNITION:caseAUDIO_SOURCE_UNPROCESSED:caseAUDIO_SOURCE_HOTWORD:if(mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]==AUDIO_POLICY_FORCE_BT_SCO&&availableDeviceTypes&AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET){device=AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_WIRED_HEADSET){device=AUDIO_DEVICE_IN_WIRED_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_HEADSET){device=AUDIO_DEVICE_IN_USB_HEADSET;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_USB_DEVICE){device=AUDIO_DEVICE_IN_USB_DEVICE;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_CAMCORDER:if(availableDeviceTypes&AUDIO_DEVICE_IN_BACK_MIC){device=AUDIO_DEVICE_IN_BACK_MIC;}elseif(availableDeviceTypes&AUDIO_DEVICE_IN_BUILTIN_MIC){device=AUDIO_DEVICE_IN_BUILTIN_MIC;}break;caseAUDIO_SOURCE_VOICE_DOWNLINK:caseAUDIO_SOURCE_VOICE_CALL:if(availableDeviceTypes&AUDIO_DEVICE_IN_VOICE_CALL){device=AUDIO_DEVICE_IN_VOICE_CALL;}break;caseAUDIO_SOURCE_REMOTE_SUBMIX:if(availableDeviceTypes&AUDIO_DEVICE_IN_REMOTE_SUBMIX){device=AUDIO_DEVICE_IN_REMOTE_SUBMIX;}break;caseAUDIO_SOURCE_FM_TUNER:if(availableDeviceTypes&AUDIO_DEVICE_IN_FM_TUNER){device=AUDIO_DEVICE_IN_FM_TUNER;}break;default:ALOGW("getDeviceForInputSource()invalidinputsource%d",inputSource);break;}if(device==AUDIO_DEVICE_NONE){ALOGV("getDeviceForInputSource()nodevicefoundforsource%d",inputSource);if(availableDeviceTypes&AUDIO_DEVICE_IN_STUB){device=AUDIO_DEVICE_IN_STUB;}ALOGE_IF(device==AUDIO_DEVICE_NONE,"getDeviceForInputSource()nodefaultdevicedefined");}ALOGV("getDeviceForInputSource()inputsource%d,device%08x",inputSource,device);returndevice;}template<>AudioPolicyManagerInterface*Engine::queryInterface(){return&mManagerInterface;}}//namespaceaudio_policy}//namespaceandroid

    通过以上分析,我们知道了音频会流向哪个输出设备,那么下一个问题来了,是由谁负责传输和对音频数据做最后的处理呢?

    这里就需要看音频设备的策略文件,还是以媒体通道为例,假设设备没有接任何外接设备,选择的 outputDeviceAUDIO_DEVICE_OUT_SPEAKER

    接下来就要看哪个 output so 支持 AUDIO_DEVICE_OUT_SPEAKER,符合度最高的 output so 将会负责数据传输,最终经由 tinyalsa 写入到 pcm 节点中。

    不同的 Android 版本在配置文件上会有些许差异,可能放置在 *audio_policy_configuration.xml 中,有些在 audio_policy.conf 中。

    三、案例分析

    1. 声音忽大忽小问题

    具体分析

    有用户反馈使用优酷视频播放视频时,概率性出现声音忽大忽小的问题,一旦出现就是在播放指定音频时是必现的。接下来联系用户帮提供设备的日志信息和操作步骤,按照用户操作来复现问题,通过 demo 还原用户环境参数便能复现。 首先分析确认发现在这个过程中声音音量均无变化,所以初步怀疑可能是和音频流数据出现异常有关。在上图中数字有标识的5个点中分别抓取音频,使用 Audacity 导入音频文件来进行分析,发现位置4的音频正常,而位置5的音频出现了声音异常的现象。具体见下图:

    Android audio音频流数据异常问题怎么解决

    所以便可以确认在音频数据经过 hal 层音效处理前是正常等,经过音效处理后,在某些特殊的声音数据下,音效库缩小了声音的幅值,从而导致声音的异常。

    为了实锤是音效库 so 导致的问题,通过关闭音效库的功能,最终发现声音忽大忽小的问题消失了。

    从以上尝试的结果综合分析可以确认,是音效 so 库对通道声音进行处理时影响到了原有声音的功能。通过修改 so 库最终来解决这个问题。

    2. 应用卡顿问题

    有用户反馈说是打开应用A播放视频正常,然后直接返回到 home 目录,应用A后台播放时会出现断音的现象。

    具体分析

    声音卡顿,录音掉帧类的现象在声音问题中非常常见。从现象上来看,就是用户切换到后台时没有暂停播放,视频在后台播放时出现。老规矩,我们先分析相关 log,通过日志分析发现,当问题出现时,日志上频繁打印 get null buffer 的信息。

    所以怀疑是否是音频数据丢失导致的。dump 音频数据抓取到系统混音后输出到输出设备的原始音频,可以帮助实锤上层系统传下来的数据是否正常。于是发现位置3的音频如下:

    Android audio音频流数据异常问题怎么解决

    从抓取到的音频可以看到,在后台异常播放时,在该时间段内会出现明显音频丢帧的现象。接下来要看看是在哪一块出现了丢帧。进一步分析 audioTrack 传下来的数据,出现了丢失掉一部分音频的现象,时长相当于原音频的一半。

    基于此,为了实锤是应用A传下来的数据就有缺失,从日志信息跟踪,决定在 audioTrack 上加日志信息来看,发现当切换到后台时,audioTrack 每次还是写 4096 个 byte ,但是写数据的频率降低了一半。 &emsp;&emsp;

    正常:28.600-27.546=1.054 44次 间隔 1.054/43= 0.0245秒/次。 &emsp;&emsp;

    异常:40.839-39.804=1.035 22次 间隔 1.035/21= 0.0493秒/次。

    考虑到这一块是否是和后台进程的优先级相关。当进程降低时导致了写数据的线程能够拿到的CPU资源变小,出现了断音的问题。通过和其他型号的平板对比发现,各厂家 Android 10 的平板大部分均有此问题,而 android7 和 android 8 的平板就没有这个问题。基于以上情况,更加怀疑是和 android 的特性相关,可能是新的 android 平板针对后台线程优先级做了处理,目的也很明确,就是限制后台应用的活跃程度,来保证设备性能。

    此时进一步分析最终发现是和 TimerSlackHigh 的参数相关。

    system/core/libprocessgroup/profiles/task_profiles.json:

    {"Name":"TimerSlackHigh","Actions":[{"Name":"SetTimerSlack","Params":{"Slack":"40000000"}}]},{"Name":"TimerSlackNormal","Actions":[{"Name":"SetTimerSlack","Params":{"Slack":"50000"}}]},

    该参数影响了应用后台线程 sleep/wait 之间所消耗的时间。可以看到,当应用从前台切换到后台时,这个时间从50 微秒上调到 40 毫秒。从而导致写入音频数据量大大减少。通过修改参数可以解决,但是提高后台线程的活跃度,很可能影响到整体性能,因此不作处理。最终像用户解释,切换后台时可以手动停止播放视频,同时反馈给应用,由应用规范应用流程,起后台进程来做单独处理。

    关于“Androidaudio音频流数据异常问题怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    本文:Android audio音频流数据异常问题怎么解决的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:Python Numpy之排序,搜索和计数怎么实现下一篇:

    18 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18