Android10.0(Q) 实现通话中播放音乐/通话背景音(答录机/魔音功能)
作者:互联网
前言
这个功能大体意思类似机器人交互的效果,一般多应用到客服接听场景中,电话接通自动播放一段录音给
对方听,根据选项操作录音解析等完成一整个流程。这里面电话接通播放声音给对方听普通应用是做不到的,
因为这关系到音频焦点分配的问题。Android 电话拨入音频焦点(Audio Focus)
谷歌默认的策略,当电话响铃或接通后,电话的音频焦点使用优先级是最高的,其它应用是无法抢占的。
但我们有源码啊,可以跳过这个地方,但是尝试后你会发现依旧不行。因为这还关系到 audio 驱动部分的上下行。
修改方案
frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerBGSPlayer.cpp
vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerTelephonyTx.cpp
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h
frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
canReassignAudioFocus 直接放回 true,其实最终发现改不改这里无所谓,主要是 audio 的上下行
private boolean canReassignAudioFocus() {
// focus requests are rejected during a phone call or when the phone is ringing
// this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus
/*if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) {
return false;
}*/
return true;
}
audio driver 部分需要修改 mPcmMixerDlGain 和 mPcmMixerUlGain 默认初始值
其中 mPcmMixerDlGain 表示下行 gain 值,影响的是本端听到的声音大小
mPcmMixerUlGain 表示上行 gain 值,影响的是对方听到的声音大小,默认值是 0x00,
所以对方听不到,只要将 mPcmMixerUlGain 改为非 0 值即可,最大值 0xFF
vendor/mediatek/proprietary/hardware/audio/common/speech_driver/SpeechPcmMixerBGSPlayer.cpp
uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerDlGain = 0xFF;
-uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerUlGain = 0x0;
+uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerUlGain = 0xFF;
$ find -name "*.cpp" | xargs grep "setPcmMixerDlMute"
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:uint8_t SpeechPcmMixerBGSPlayer::mPcmMixerDlGain = 0xFF;
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp: pSpeechDriver->BGSoundConfig(mPcmMixerUlGain, mPcmMixerDlGain);
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp: mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp: mPcmMixerDlGain = 0xFF;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:uint8_t SpeechPcmMixerTelephonyTx::mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp: pSpeechDriver->TelephonyTxConfig(mPcmMixerUlGain, mPcmMixerDlGain);
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp: mPcmMixerDlGain = 0x0;
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp: mPcmMixerDlGain = 0xFF;
$ find -name "*.cpp" | xargs grep "setPcmMixerDlMute("
./common/speech_driver/SpeechPcmMixerBGSPlayer.cpp:void SpeechPcmMixerBGSPlayer::setPcmMixerDlMute(const bool mute_on) {
./common/speech_driver/SpeechPcmMixerTelephonyTx.cpp:void SpeechPcmMixerTelephonyTx::setPcmMixerDlMute(const bool mute_on) {
./common/V3/aud_drv/AudioALSAHardware.cpp: SpeechPcmMixerBGSPlayer::setPcmMixerDlMute((bool)value);
AndroidO 版本修改方法
frameworks/base/media/java/android/media/AudioAttributes.java
frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSAStreamManager.cpp
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h
frameworks/base/media/java/android/media/AudioAttributes.java
public Builder setCapturePreset(int preset) {
switch (preset) {
+ case MediaRecorder.AudioSource.VOICE_UPLINK:
+ case MediaRecorder.AudioSource.VOICE_DOWNLINK:
+ case MediaRecorder.AudioSource.VOICE_CALL:
+ case MediaRecorder.AudioSource.REMOTE_SUBMIX:
case MediaRecorder.AudioSource.DEFAULT:
case MediaRecorder.AudioSource.MIC:
frameworks/base/services/core/java/com/android/server/audio/MediaFocusControl.java
private boolean canReassignAudioFocus() {
// focus requests are rejected during a phone call or when the phone is ringing
// this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus
/*if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) {
return false;
}*/
- return true;
}
vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSAStreamManager.cpp
AudioALSAStreamManager::AudioALSAStreamManager() :
mForceDisableVoiceWakeUpForSetMode(false),
mBypassPostProcessDL(false),
mBGSDlGain(0xFF),
- mBGSUlGain(0),
+ //mBGSUlGain(0),
+ mBGSUlGain(0xFF),
mBypassDualMICProcessUL(false),
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioALSAVolumeController.h
#define HW_DIGITAL_GAIN_MAX (252)
#define HW_DIGITAL_GAIN_STEP (4) // 2==> 0.5 dB ,4==>1dB
-#define AUDIO_SYSTEM_UL_GAIN_MAX (45)
+#define AUDIO_SYSTEM_UL_GAIN_MAX (160)
#define MIN_PGA_GAIN (0)
#define MAX_PGA_GAIN_RANGE (30)
#define AUDIO_UL_PGA_STEP
vendor/mediatek/proprietary/hardware/audio/mt6735/include/AudioMTKGainController.h
#define HW_DIGITAL_GAIN_MAX (252)
#define HW_DIGITAL_GAIN_STEP (4) // 2==> 0.5 dB ,4==>1dB
-#define AUDIO_SYSTEM_UL_GAIN_MAX (45)
+#define AUDIO_SYSTEM_UL_GAIN_MAX (160)
#define MIN_PGA_GAIN (2)
#define MAX_PGA_GAIN_RANGE (30)
#define AUDIO_UL_PGA_STEP
其它问题收录
1、使用答录机的时候会听到连续的啪的声音
主要原因在于 AFE 不断去重新设置 uplink 的 AGC 那个寄存器。修正方法是当 mic volume
不变的时候不再重复设置 AGC 的那个寄存器。
Patch id: MAUI_02602310
2、答录机中进入远程访问之后,直接开始播放所有未读留言,此时用户输入 DTMF 无效
主要原因是函数 mmi_autoam_key_detection_callback 中没有把 MMI_AUTOAM_STATE_REMOTE_PRE_PLAY_UNREAD
这种 case 考虑进去,导致无法相对应的 DTMF 输入,修改方法是将这种 case 加进去
Patch id: MAUI_02029196
3、实现第三方的魔音功能的时候要修改 wav.c
添加第三方的魔音功能的时候,常常会要求开发 wav.c,因为要改到这里面的某些函数。出于策略,从 09A0924 之后,wav.c 等相关文件都被封装到 lib 中了,这部分将不会再重新开放出来。事实上,要实现魔音功能,其实不开放
wav.c 也是可以完成的,基本上只需要修改函数 wavADPCMPutData 和 wavDviADPCMPutDataMono,可以在 code
中对 ihdl->wav.Wav_PutData 进行赋值的地方进行相应的修改,赋值成自行修改之后的函数
wavADPCMPutData_modified 和 wavDviADPCMPutDataMono_modified 即可。
4、在通话中,播放背景音时,如何屏蔽掉按键音
如果是本地产生的按键音,可以利用 BGSND 的接口,把整个 speech 关闭。
修改 aud_snd_play_req 和 aud_snd_set_volume_req_hdlr:
SND_ConfigULMixer(snd_handle, KAL_TRUE, volume);
改为
SND_ConfigULMixer(snd_handle, KAL_FALSE, volume);
如果是因为按键产生 DTMF 发送到对方触发对方手机产生的声音,只能通过屏蔽本地产生 DTMF 处理。
方法是在通话时进入 option 选择其中的 DTMF 菜单并设成 off 或者直接在代码里设置
g_ucm_p->call_miss.is_dtmf=false 来实现。
5、来电时播放一段声音对对方听,自己这边不放出声来,同时本地的声音对方也听不见。然后在播放结束之后进入正常通话状态
修改文件 Am.c 中的函数 AM_SpeechOn()
在改函数内部加上判断条件,如果处于播放背景音的应用则不调用
AFE_TurnOnSpeaker(L1SP_SPEECH);
AFE_TurnOnMicrophone(L1SP_SPEECH);
在播放背景音的 callback 中调用函数
AFE_TurnOnSpeaker(L1SP_SPEECH);
AFE_TurnOnMicrophone(L1SP_SPEECH); 即可进入正常通话状态
参考
Android ALSA音频系统架构分析(1)----从Loopback了解Audio
mt6735 Audio Common 通话时如何播放声音给对方听
标签:答录机,Android10.0,driver,通话,speech,common,cpp,audio,define 来源: https://blog.csdn.net/u012932409/article/details/113827212