Search code examples
callbackcore-audiorenderpass-through

Core Audio: Bizarre problem with pass-through using render callback


I am implementing an audio passthrough using the RemoteIO audio unit, by attaching a render callback to the input scope of the output bus (ie the speakers).

Everything works swimmingly, ...

OSStatus RenderTone(
                    void *                      inRefCon, 
                    AudioUnitRenderActionFlags  * ioActionFlags, 
                    const AudioTimeStamp        * inTimeStamp, 
                    UInt32                      inBusNumber, 
                    UInt32                      inNumberFrames, 
                    AudioBufferList             * ioData)

{   
    SoundEngine * soundEngine = (SoundEngine *) inRefCon;

    // grab data from the MIC (ie fill up ioData)
    AudioUnit thisUnit = soundEngine->remoteIOUnit->audioUnit;
    OSStatus err = AudioUnitRender(thisUnit, 
                                   ioActionFlags, 
                                   inTimeStamp, 
                                   1, 
                                   inNumberFrames, 
                                   ioData);
    if (result)
    {
        printf("Error pulling mic data");
    }

    assert(ioData->mNumberBuffers > 0);

    // only need the first buffer
    const int channel = 0;
    Float32 * buff = (Float32 *) ioData->mBuffers[channel].mData;
}

until I add that last line.

    Float32 * buff = (Float32 *) ioData->mBuffers[channel].mData;

With this line in place, no errors, simply silence. Without it, I can click my fingers in front of the microphone and hear it in my headset.

EDIT: AudioBuffer buf0 = ioData->mBuffers[0]; // Is sufficient to cause failure

What is going on?

It is not an error caused by the compiler optimising out an unused variable. If I set buff++; on the next line, behaviour is the same. although maybe the compiler can still detect the variable is effectively unused.


Solution

  • Problem was the request for data from the microphone was failing the very first time this callback fires.

    And what I should have been doing was examining the return value, and returning it (ie quitting the callback) if it was not success

    What was probably happening was that I was accessing invalid data

    It is still rather bizarre, but no need to go into it.