我的 iOS 7 应用程序会在必要时发出文本声音。
我想做的是让用户在我的应用程序运行时收听他的音乐或播客(或任何其他使用音频的应用程序)。
预期的行为是,当我的应用程序说话时,其他音频会混合或闪避,然后其他音频会立即恢复到初始级别。
我尝试了很多方法来实现这个目标,但没有什么足够好,因为我在代码后面列出了我面临的问题。
我当前的实现基于在播放或文本转语音之前创建会话,如下所示:
+ (void)setAudioActive {
[[self class] setSessionActiveWithMixing:YES];
}
播放/演讲后,我将 i 设置为空闲,如下所示:
+ (void)setAudioIdle {
[[self class] setSessionActiveWithMixing:NO];
}
根据活动参数处理会话设置的核心函数,如下:
+ (void)setSessionActiveWithMixing:(BOOL)active
{
NSError *error = NULL;
BOOL success;
AVAudioSession *session = [AVAudioSession sharedInstance];
static NSInteger counter = 0;
success = [session setActive:NO error:&error];
if (error) {
DDLogError(@"startAudioMixAndBackground: session setActive:NO, %@", error.description);
}
else {
counter--; if (counter<0) counter = 0;
}
if (active) {
AVAudioSessionCategoryOptions options = AVAudioSessionCategoryOptionAllowBluetooth
//|AVAudioSessionCategoryOptionDefaultToSpeaker
|AVAudioSessionCategoryOptionDuckOthers
;
success = [session setCategory://AVAudioSessionCategoryPlayback
AVAudioSessionCategoryPlayAndRecord
withOptions: options
error: &error];
if (error) {
// Do some error handling
DDLogError(@"startAudioMixAndBackground: setCategory:AVAudioSessionCategoryPlayback, %@", error.description);
}
else {
//activate the audio session
success = [session setActive:YES error:&error];
if (error) {
DDLogError(@"startAudioMixAndBackground: session setActive:YES, %@", error.description);
}
else {
counter++;
}
}
}
DDLogInfo(@"Audio session counter is: %ld",counter);
}
我目前的问题是:
1)当我的应用程序开始说话时,我听到声音中有一些毛刺,这使得它不太好听;
2)当我将路由连接到蓝牙时,底层音频(例如Podcast或ipod音乐)变得非常低并且听起来很吵,这使得我的解决方案根本无法使用,我的用户将拒绝这个级别的质量差。
3)当其他蓝牙连接设备尝试发出声音(例如汽车或实例中的GPS)时,我的应用程序没有收到任何中断(或者我处理错误),请参阅我的代码如下:
- (void)startAudioMixAndBackground {
// initialize our AudioSession -
// this function has to be called once before calling any other AudioSession functions
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioSessionDidChangeInterruptionType:)
name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
// set our default audio session state
[[self class] setAudioIdle];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
if ([self canBecomeFirstResponder]) {
[self becomeFirstResponder];
}
@synchronized(self) {
self.okToPlaySound = YES;
}
//MPVolumeSettingsAlertShow();
}
// want remote control events (via Control Center, headphones, bluetooth, AirPlay, etc.)
- (void)remoteControlReceivedWithEvent:(UIEvent *)event
{
if (event.type == UIEventTypeRemoteControl)
{
switch(event.subtype)
{
case UIEventSubtypeRemoteControlPause:
case UIEventSubtypeRemoteControlStop:
[[self class] setAudioIdle];
break;
case UIEventSubtypeRemoteControlPlay:
[[self class] setAudioActive];
break;
default:
break;
}
}
}
#pragma mark - Audio Support
- (void)audioSessionDidChangeInterruptionType:(NSNotification *)notification
{
AVAudioSessionInterruptionType interruptionType = [[[notification userInfo]
objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (AVAudioSessionInterruptionTypeBegan == interruptionType)
{
DDLogVerbose(@"Session interrupted: --- Begin Interruption ---");
}
else if (AVAudioSessionInterruptionTypeEnded == interruptionType)
{
DDLogVerbose(@"Session interrupted: --- End Interruption ---");
}
}