Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS AVAudioSession ducking is slow and synchronous

In iOS, I'm trying to duck the Music app's music when playing some sound effects. In case you don't know, "ducking" simply means that the music volume gets a bit down before playing my sound, then the sound plays, and then the music volume gets back its initial volume.

For ducking, I'm setting AVAudioSession category to AVAudioSessionCategoryAmbient with option AVAudioSessionCategoryOptionDuckOthers, and then activating/deactivating the session (and playing the sound in-between, obviously). It works well, but the volume changes seem to be done in the same thread as the call, and the app hangs while the volume is being modified.

If you want to replicate the behavior, I think the fastest route is to start a new SpriteKit project, which will give you the sample, ship rotating project. Then put the following code in the touchesBegan:withEvent method:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient withOptions: AVAudioSessionCategoryOptionDuckOthers error: nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[AVAudioSession sharedInstance] setActive:NO error:nil];

Next run the app in an iOS device, put some music in the Music app and touch the screen to create ships and duck the music. You'll hear the ducking, but also see the ships freezing on the screen.

Is this normal? What would be the simplest way to avoid the app freezing while the ducking is made?

By the way, I'm using an iPhone 5S on iOS 8.1. Also, I'm using this in a Unity3D plugin. How can I duck the Music app from Unity itself?

like image 512
Racso Avatar asked Nov 10 '22 10:11

Racso


1 Answers

You can try putting the AVAudioSession calls on a different thread. Then they won't be blocking the main (UI) thread. This is especially for setActive, which takes a noticeable amount of time to complete.

        dispatch_queue_t myQueue = dispatch_queue_create("com.myname.myapp", nil);
        dispatch_async(myQueue, ^{
            [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient withOptions: AVAudioSessionCategoryOptionDuckOthers error: nil];
            [[AVAudioSession sharedInstance] setActive:YES error:nil];
        });

This question also seems relevant: iOS AudioSessionSetActive() blocking main thread?

like image 84
Quij Avatar answered Nov 15 '22 12:11

Quij