My iOS 7 app vocals lyrics when needed.
What I would like to do is let the user listen to his music or podcasts (or any other application using audio) while my work.
The expected behavior is that other audio or mix or duck, when my application speaks, then the rest of the audio resumes its volume at the initial level right after.
I tried many ways to achieve this goal, but nothing is enough, as I list the problems that I encounter after the code.
My current implementation is based on creating a session before playing or text-to-speech as follows:
+ (void)setAudioActive { [[self class] setSessionActiveWithMixing:YES]; }
After playing / speaking, I set to idle as follows:
+ (void)setAudioIdle { [[self class] setSessionActiveWithMixing:NO]; }
The main function that handles the session setup according to the active parameter is as follows:
+ (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); }
My current problems:
1) When my application starts talking, I hear some kind of king glitch in the sound, which makes it not very pleasant;
2) When I connect the route to bluetooth, the main sound (say, a podcast or music for iPod) goes very low and sounds noisy, which makes my solution simply unusable, my users will reject this level of poor quality.
3) When other devices connected to Bluetooth tried to emit sounds (for example, GPS in the car or instance), my application does not receive any interruptions (or I am processing them incorrectly), see my code as follows:
- (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 ---"); } }