AVAudioSession / Audio Session Services 切换输出

10

好的,我的AVAudioSession定义如下(是c和obj-c调用的混合体)。 还要注意的是应用程序具有后台模式音频功能,因为如果在后台录制,它必须继续录制:

[(AVAudioSession *)[AVAudioSession sharedInstance] setDelegate: self];
// Allow the app sound to continue to play when the screen is locked.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
//Turn off automatic gain on the microphone
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeMeasurement error:nil];
//Turn on the ability to mix with others
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);

//Activate the audio session
[[AVAudioSession sharedInstance] setActive:YES error:nil];

该应用有几个不同的音频选项(只编程了前两个):

  • 正常:应用程序没有音频输出,因此不会干扰外部音频
  • 仅记录耳机麦克风:必须没有增益调整,并且不要干扰外部音频(将通过耳机播放)
  • 在应用中播放音乐,不录制:停止外部音频,并通过当前输出(扬声器或耳机)播放
  • 在应用中播放音乐并记录耳机麦克风:停止外部音频,仅通过耳机录制和播放

录音在前台和后台都很好用,我稍后会添加播放。然而,我今晚刚注意到,如果已经播放音频(Pandora)在扬声器上,然后我进入我的应用程序并激活录制模式,那么它将Pandora切换到通过手机扬声器播放,即使在音频会话被停用并且应用程序处于后台状态时(但未被强制关闭),音频仍将继续通过手机扬声器播放,直到我强制关闭该应用程序。

//Deactivate the audio session
[[AVAudioSession sharedInstance] setActive:NO error:nil];
相反,如果在启动应用程序进入录制模式时,耳机已插入且音乐通过耳机播放,则仅会有短暂的暂停,音乐将以相同的音量继续播放(正确,没有淡出)。
我不明白为什么在未插入耳机时激活音频会话时路由会更改,以及为什么在停用会话时它不会更改回来。尤其是切换到手机扬声器!我做错了什么吗?还是需要根据用户想要做什么来定义AVAudioSession而不是使用“play+record”和“mode measurement”?即使我需要为不同的用例分别定义它。例如,如果应用正在录制,那么音频将始终通过耳机进行输出,如果应用程序没有录制,则音频输出要么通过耳机进行输出,要么通过扬声器进行输出(具体取决于用户是否插入了耳机 - 即正常行为)。
额外的细节
好的,我尝试切换所有代码并注意到文档中隐藏的一个注释kAudioSessionProperty_OverrideAudioRoute kAudioSessionOverrideAudioRoute_None 指定kAudioSessionCategory_PlayAndRecord类别的输出音频应该转到接收器。这是此类别的默认输出音频路线。
然后我尝试以3种不同的方式设置此属性(这些属性):
- kAudioSessionProperty_OverrideAudioRoute与kAudioSessionOverrideAudioRoute_Speaker继续播放音频,但将其从扬声器输出到接收器,并将路线显示为ReceiverAndMicrophone。 - kAudioSessionProperty_OverrideCategoryDefaultToSpeaker与kAudioSessionOverrideAudioRoute_Speaker停止当前正在播放的音频,并将路由显示为SpeakerAndMicrophone。 - kAudioSessionProperty_OverrideCategoryDefaultToSpeaker并将值设置为1与kAudioSessionOverrideAudioRoute_Speaker执行相同的操作。
因此,文档说默认情况下要切换到接收器。 但是,无论我做什么,似乎都无法保持扬声器输出并保持外部音频播放。

1
嗨...你有找到解决方案吗?我这里也遇到了同样的问题。 - Sumit Sharma
1个回答

9

显然,属性设置的顺序很重要,尽管文档中没有提到。对于那些最终找到这篇文章的人,以下是有效的方法:

//Init and set the interrupt listener.  last parameter is passed to interruptlistener
AudioSessionInitialize(NULL, NULL, interruptlistener, NULL);

//Allow the app sound to continue to play when the screen is locked.
UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);

//Force current audio out through speaker
UInt32 routeSpeaker = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(routeSpeaker), &routeSpeaker);

//Turn on the ability to mix with others
UInt32 doSetProperty = 1;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接