I have a code that plays a monophonic event (short beeps at different frequencies). I create an AudioOutputUnit, stop it and whenever I need to play audio. I start. When I played it for the required time, I stop it.
Sounds simple enough.
However, AudioOutputUnitStart will usually take 180 ms to return to my iPhone 4S (with iOS 5.1), which is too much.
Here is the creation / initialization of AudioOutputUnit
void createAOU() { m_init = false; // find the default playback output unit AudioComponentDescription defaultOutputDescription; defaultOutputDescription.componentType = kAudioUnitType_Output; defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO; defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; defaultOutputDescription.componentFlags = 0; defaultOutputDescription.componentFlagsMask = 0; // Get the default playback output unit AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription); if (defaultOutput == NULL) return; OSErr err = AudioComponentInstanceNew(defaultOutput, &m_toneUnit); if (err != noErr) return; // single channel, floating point, linear PCM AudioStreamBasicDescription streamFormat; streamFormat.mSampleRate = m_framerate; streamFormat.mFormatID = kAudioFormatLinearPCM; streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; streamFormat.mBytesPerPacket = sizeof(float); streamFormat.mFramesPerPacket = 1; streamFormat.mBytesPerFrame = sizeof(float); streamFormat.mChannelsPerFrame = 1; streamFormat.mBitsPerChannel = sizeof(float) * 8; err = AudioUnitSetProperty (m_toneUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); if (err != noErr) return; // Attach callback to default output AURenderCallbackStruct input; input.inputProc = RenderTone; input.inputProcRefCon = this; err = AudioUnitSetProperty(m_toneUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); if (err != noErr) return; float aBufferLength = 0.001; // In seconds AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(aBufferLength), &aBufferLength); err = AudioUnitInitialize(m_toneUnit); if (err != noErr) return; reset(); m_init = true; }
To get started, I just call:
OSErr err = AudioOutputUnitStart(m_toneUnit);
When done:
OSErr err = AudioOutputUnitStop(m_toneUnit);
I tried different things: what makes the kAudioSessionProperty_PreferredHardwareIOBufferDuration property very small (e.g. 5 ms) Decrease the frame rate (try 48 kHz, 44.1 kHz, 8 kHz)
No matter what I do ... When I first start an audio unit, AudioOutputUnitStart returns only after 160-180 ms. If I stop and start right away, then it will only take about 5 m, which is much more acceptable.
The delay in my application is quite important, and 180 ms is definitely not acceptable.
Any suggestions? I saw several people ask similar questions, but usually they didnβt have an answer.
I hope this time everything will be different :)