AVAudioSession mixing with AVSpeechUtterance

3.2k views Asked by At

I have an issue where I would like to have the iPod playing music in the background and in my application I would like to have AVSpeechUtterance lower the volume of the iPod, play a string of text and then I would like to have the iPod resume playing. I have tried several things but never had AVAudioSession and AVSpeechUtterance work well together. I can get the iPod to stop, pause for a bit and then start playing again. I can see my string being passed to AVSpeechUtterance, but it does not take precedence to be played over the speaker. Here is my code:

View did load:

   - (void)viewDidLoad
   {
            //set the audio session for my app to play from the TTS library
            NSError *error;
            audioSession = [AVAudioSession sharedInstance];
            [audioSession setCategory:AVAudioSessionCategoryAmbient withOptions:1  error:&error];
            [audioSession setActive:YES error:&error];
            if(error){
                NSLog(@"Audio Error %@", error);
            }

            syn = [[AVSpeechSynthesizer alloc] init];
            syn.delegate = self;

            iPodMusicPlayer = [[MPMusicPlayerController alloc] init];

   }

Here is my speech function:

   -(void)speech:(NSString *)string
   {
             if(audioSession.isOtherAudioPlaying){
                 wasPlaying = YES;
                 NSLog(@"Other audio is playing");
                 [iPodMusicPlayer pause];
             }

             AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:string];
             utterance.rate = 0.3f;
             utterance.volume = 1.0;
             [syn speakUtterance:utterance];

   }

AVSpeechSynthesizer Delegate method that gets called after the speech is finished

   - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
   {
         if(wasPlaying){
            NSLog(@"Start Playing");
            [iPodMusicPlayer play];
            wasPlaying = NO;
         }
   }

I reviewed the Apple docs on AVAudioSession here and it looks like I have everything implemented correctly. Does anyone have any idea where I went wrong?

1

There are 1 answers

3
AgnosticDev On

I just wanted to let everyone know that after some troubleshooting, this is how I was able to solve my issue. I am not sure I like the solution, and am working to improve it.

View Did Load

    - (void)viewDidLoad
    {
            syn = [[AVSpeechSynthesizer alloc] init];
            syn.delegate = self;

            iPodMusicPlayer = [[MPMusicPlayerController alloc] init];
    }

Speech Function

    -(void)speak:(NSString *)string
    {

            audioSession = [AVAudioSession sharedInstance];

            NSError *setCategoryError = nil;
            NSError *activationError = nil;
            BOOL success = [audioSession setCategory:AVAudioSessionCategoryPlayback
                withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&setCategoryError];

            [audioSession setActive:YES error:&activationError];

            if(audioSession.isOtherAudioPlaying){
                wasPlaying = YES;
                NSLog(@"Other audio is playing");
                [iPodMusicPlayer pause];
            }

            NSLog(@"Success %hhd", success);

            AVSpeechUtterance *utterance = [AVSpeechUtterance           speechUtteranceWithString:string];
            utterance.rate = 0.3f;
            utterance.volume = 1.0;
            [syn speakUtterance:utterance];
     }

AVSpeechSynthesizer Delegate method that gets called after the speech is finished

     - (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
     {
            if(wasPlaying){
                NSLog(@"Start Playing");
               [iPodMusicPlayer play];
               wasPlaying = NO;
            }
     }