Using AudioStreamer with AVAudioPlayer and Avoiding Hardware Locking

1 minute read

In Ambiance, I use some customized AVAudioPlayers to play the apps audio. When possible, these AVAudioPLayers use hardware decoding of the audio files which speeds up the audio processing considerably and frees the software from having to dedicate resources to the process.

 
I also use Matt Gallagher's AudioStreamer to play remote files off my server for Ambiance previews.  In the latest version of the app, I was getting some feedback from beta testers that preview was not always working. One of them sent me a screenshot:
 
 
So I set out on trying to reproduce and I found that playing an AudioStreamer stream worked fine when no other audio was playing, but when other audio was playing, it failed.  Setting breakpoints in the code, I saw that it was failing in the enqueueBuffer method in this code:
 
err = AudioQueueStart(audioQueue, NULL);
if (err)
{
    [self failWithErrorCode:AS_AUDIO_QUEUE_START_FAILED];
    return;
}
err was returning a code of 1752656245. Knowing that Audio Queue codes are actually ascii codes, I threw it into calculator:
 
 
and saw "hwiu" as the code.  A quick google search led me to the docs where I saw that this means that the streamer was unable to obtain the hardware codec.  This makes sense! Ambiance uses the hardware codec to play sounds, and when a preview comes along and tries to play a streaming sound it cannot due to the fact that that hardware spot is taken.  I had been pausing the main sound, but that did not release the hold on the hardware codec.
 
It turns out the solution to my problem was much easier. Previews in my app are not used for very long durations, so using the software to play them isn't too taxing.  I decided to change the hardware codec preference for the audioQueue:
 
// set the software codec too on the queue.
UInt32 val = kAudioQueueHardwareCodecPolicy_PreferSoftware;
OSStatus ignorableError;
ignorableError = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_HardwareCodecPolicy, &val, sizeOfUInt32);
if (ignorableError)
{
    return;
}
This code goes in "createQueue", line 1494 (as of 7/2/10).  It is telling the codec to prefer the software route, but use the hardware if anything fails.  So far, all tests have been unable to reproduce the issue and everything works fine.

Comments