kAudioDevicePropertyBufferFrameSize replacement for iOS

audio-streaming, core-audio, ios, latency

Solution

You can use the `kAudioSessionProperty_CurrentHardwareIOBufferDuration` property, which represents the buffer size in seconds. Multiply this by the sample rate you get from `kAudioSessionProperty_CurrentHardwareSampleRate` to get the number of samples you should buffer.

The resulting buffer size should be a multiple of 2. I believe either 512 or 4096 are what you're likely to get, but you should always base it off of the values returned from `AudioSessionGetProperty`.

Example:

Float64 sampleRate;
UInt32 propSize = sizeof(Float64);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, 
                        &propSize,
                        &sampleRate);

Float32 bufferDuration;
propSize = sizeof(Float32);
AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, 
                        &propSize,
                        &bufferDuration);

UInt32 bufferLengthInFrames = sampleRate * bufferDuration;

The next step is to find out the input stream format of the unit you're sending audio to. Based on your description, I'm assuming that you're programmatically generating audio to send to the speakers. This code assumes `unit` is an `AudioUnit` you're sending audio to, whether that's the RemoteIO or something like an effect Audio Unit.

AudioStreamBasicDescription inputASBD;
UInt32 propSize = sizeof(AudioStreamBasicDescription);
AudioUnitGetProperty(unit,
                     kAudioUnitProperty_StreamFormat,
                     kAudioUnitScope_Input,
                     0,
                     &inputASBD,
                     &propSize);

After this, `inputASBD.mFormatFlags` will be a bit field corresponding to the audio stream format that `unit` is expecting. The two most likely sets of flags are named `kAudioFormatFlagsCanonical` and `kAudioFormatFlagsAudioUnitCanonical`. These two have corresponding sample types `AudioSampleType` and `AudioUnitSampleType` that you can base your size calculation off of.

As an aside, `AudioSampleType` typically represents samples coming from the mic or destined for the speakers, whereas `AudioUnitSampleType` is usually for samples that are intended to be processed (by an audio unit, for example). At the moment on iOS, `AudioSampleType` is a SInt16 and `AudioUnitSampleType` is fixed 8.24 number stored in a SInt32 container. Here's a post on the Core Audio mailing list explaining this design choice

The reason I hold back from saying something like "just use Float32, it'll work" is because the actual bit representation of the stream is subject to change if Apple feels like it.

Problem

I was trying to set up an audio unit to render the music (instead of Audio Queue.. which was too opaque for my purposes).. iOS doesn't have this property `kAudioDevicePropertyBufferFrameSize`.. any idea how I can derive this value to set up the buffer size of my IO unit? I found this post interesting.. it asks about the possibility of using a combination of `kAudioSessionProperty_CurrentHardwareIOBufferDuration` and `kAudioSessionProperty_CurrentHardwareOutputLatency` audio session properties to determine that value.. but there is no answer.. any ideas?

Original source