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 ?即使我需要为不同的用例单独定义它。例如,如果应用程序正在录制,音频将始终通过耳机,如果应用程序没有录制,则音频输出耳机或扬声器(取决于用户是否插入了耳机- 即,正常行为)。

额外细节

好的,我尝试切换所有代码 c 并注意到文档中隐藏了关于 kAudioSessionProperty_OverrideAudioRoute 的注释

kAudioSessionOverrideAudioRoute_None
为 kAudioSessionCategory_PlayAndRecord 类别指定输出音频应发送到接收器。这是该类别的默认输出音频路由。

因此,我尝试以 3 种不同的方式设置此属性(这些属性):

  • kAudioSessionProperty_OverrideAudioRoute 和 kAudioSessionOverrideAudioRoute_Speaker 继续播放音频,但通过接收器将其切换出去,并将路由显示为 ReceiverAndMicrophone
  • kAudioSessionProperty_OverrideCategoryDe​​faultToSpeaker 和 kAudioSessionOverrideAudioRoute_Speaker 停止当前播放的音频,并将路由显示为 SpeakerAndMicrophone
  • 值为 1 的 kAudioSessionProperty_OverrideCategoryDe​​faultToSpeaker 与 kAudioSessionOverrideAudioRoute_Speaker 执行相同的操作

所以基本上文档说默认是切换到接收器。但是,无论我做什么,我似乎都无法保持扬声器输出并保持外部音频播放。

4

1 回答 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);
于 2013-03-13T18:56:14.073 回答