iOS bufferSize fix in juce 4.3 disables mix with other audio app

Hi,

An issue regarding the buffer size on iOS was identified and fixed in this thread : Block Size on iOS 8
The correction is available in juce 4.3. This bug fix has a side effect on the mix with other app audio feature.

I’ve made the following test using the AppAppExample available in juce 4.3:

  • activated the background mode for Audio,Airplay,… and uses bluetooth LE accessories

  • modified the prepareToPlay method so that the App starts immediately to play a sound
    frequency = 400.0;
    amplitude = 0.9;
    phaseDelta = (float) (2.0 * double_Pi * frequency / sampleRate);

  • compiled and deploy the app on my ipod touch (iOS 9.3.2)

  • the App start to play a 400 Hz sound,

  • I switch to the Music App, the sound is still here,

  • I start a music, the sinusoid stops and shouldn’t

  • I stop the music, the sinusoid starts again.

  • Now I remove the bug fix introduced in juce 4.3 regarding the buffer size in the juce_ios_Audio.cpp (see code above)

  • the mixing behavior of the App is now back to normal, I can hear both the music from Music App and the sinusoid BUT the bufferSize is back to 1156.

I can’t go further to identify what is wrong with the bug fix regarding the bufferSize.

Thanks for your help

Mickaël

/* AudioUnitInitialize (audioUnit);

    AudioUnitSetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
                          kAudioUnitScope_Global, 0, &actualBufferSize, sizeof (actualBufferSize));

*/
if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0, &framesPerSlice, &dataSize) == noErr
&& dataSize == sizeof (framesPerSlice) && static_cast (framesPerSlice) != actualBufferSize)
{
actualBufferSize = static_cast (framesPerSlice);
prepareFloatBuffers (actualBufferSize);
}

    // line restored
    AudioUnitInitialize (audioUnit);

Hi Mickaël,

Thank you for providing details. We’ll have a look at this.

Hi T0m,

Thank you. Let me know if you need additional information.

Mickaël

So what’s happening is that the Music App is changing the maximum buffer size of the shared audio session. When the Music app starts playing the buffers are larger than your app can handle and the sound drops out. Additionally the Music App (or any other) can change the sample rate of the audio too, which, at the moment, could change the pitch of your app playing in the background.

You can verify all this by doing something like

    AudioDeviceManager::AudioDeviceSetup setup;
    deviceManager.getAudioDeviceSetup (setup);
    setup.sampleRate = 44100;   // Or whatever the foreground app wants
    setup.bufferSize = 4096;   // The Apple docs suggest this for background audio, especially when the device is locked
    deviceManager.setAudioDeviceSetup (setup, true);

and your app should work.

I’m still looking at this but the fix is tricky - it’ll take a while to get sorted out.

I did reproduce the behavior you described. On my ipod touch, Music App requires a 1024 buffer size. If I set this same buffer size in my App, they do play together.
I tried with a lower value and noticed the message you mentionned "kAudioUnitErr_TooManyFramesToProcess : inFramesToProcess=1024, mMaxFramesPerSlice=128"
I also tried starting my App with a 1024 buffer, then, while Music App is playing, setting a lower buffer size. The actual buffersize that is set is also 1024.
So you’re right.

Do you think it is possible to use my own App with a buffer size lower than 1024 together with Music App ? I had the impression it used to work but perhaps the buffer size was internally changed without me knowing.
Good luck for fix and thanks.

There’s a fix for this on the develop branch.

I don’t think it’s possible to have a lower buffer size than a foreground app requests. You can, however, check the size of the buffers you’re receiving and manually chunk them down to the size you want - it’s not too complicated/expensive.

You will now also receive prepareToPlay calls on each sample rate change (which will also include the new buffer size). Unfortunately there’s no facility to watch for buffer size changes directly…

Please give it a go and report back.

Hi,

I’ve just given it a go. Now the process block is called even if the buffersize has changed. I still have to chunk the buffer as you mentionned. When Music App is paused, the buffersize comes back to its original size. I also checked that the frequency change works.

I thought it used to work even with buffer size lower than 1024. I’ve just checked with an older version of my App but I have the same behavior. So I had a bug actually :frowning:

Thanks