Stefan H
Stefan H

Reputation: 1

CoreAudio: AudioUnit can neither be stopped nor uninitialized

I wrote a command line c tool generating an sine wave and playing it using CoreAudio on the default audio output. I am initializing a AURenderCallbackStruct and initialize an AudioUnit using AudioUnitInitialize (as already discussed in this forum). All this is working as intended, but when it comes to closing the program I am not able to close the AudioUnit, neither with using AudioOutputUnitStop(player.outputUnit); nor AudioOutputUnitStop(player.outputUnit); nor AudioComponentInstanceDispose(player.outputUnit);

The order of appearance of these calls in the code does not change the behavior. The program is compiled without error messages, but the sine is still audible as long as the rest of the program is running.

Here is the code I'm using for initializing the AudioUnit:

void CreateAndConnectOutputUnit (ToneGenerator *player) {

    AudioComponentDescription outputcd = {0};
    outputcd.componentType = kAudioUnitType_Output;
    outputcd.componentSubType = kAudioUnitSubType_DefaultOutput;
    outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;

    AudioComponent comp = AudioComponentFindNext (NULL, &outputcd);
    if (comp == NULL) {
        printf ("can't get output unit");
        exit (-1);
    }

    AudioComponentInstanceNew(comp, &player->outputUnit);

    // register render callback
    AURenderCallbackStruct input;
    input.inputProc = SineWaveRenderCallback;
    input.inputProcRefCon = player;
    AudioUnitSetProperty(player->outputUnit,
                         kAudioUnitProperty_SetRenderCallback,
                         kAudioUnitScope_Output,
                         0,
                         &input,
                         sizeof(input);

    // initialize unit
    AudioUnitInitialize(player->outputUnit);
}

In my main program I'm starting the AudioUnit and the sine wave.

void main {
    // code for doing various things

    ToneGenerator player = {0};         // create a sound object
    CreateAndConnectOutputUnit (&player);
    AudioOutputUnitStart(player.outputUnit);

    // waiting to listen to the sine wave
    sleep(3);

    // attempt to stop the sound output
    AudioComponentInstanceDispose(player.outputUnit);
    AudioUnitUninitialize(player.outputUnit);
    AudioOutputUnitStop(player.outputUnit);

    //additional code that should be executed without sine wave being audible
}

As I'm new to both, this forum as well as programming in Xcode I hope that I could explain this issue in a way that you can help me out and I hope that I didn't miss the answer somewhere in the forum while searching for a solution.

Thank you in advance for your time and input,

Stefan

Upvotes: 0

Views: 1164

Answers (2)

hotpaw2
hotpaw2

Reputation: 70673

An Audio Unit runs in an asynchronous thread that may not actually stop immediately when you call AudioOutputUnitStop. Thus, it may work better to wait a fraction of a second (at least a couple audio callback buffer durations in time) before calling AudioUnitUninitialize and AudioComponentInstanceDispose on a potentially still running audio unit.

Also, check to make sure your player.outputUnit value is a valid unit (and not an uninitialized or trashed variable) at the time you stop the unit.

Upvotes: 0

user3078414
user3078414

Reputation: 1937

You should manage and unmanage your audio unit in a logical order. It doesn't make sense to stop playback on an already uninitialized audio unit, which had in fact previously been disposed of in the middle of the playback. Rather than that, try the following order:

AudioOutputUnitStop(player.outputUnit);           //first stops playback
AudioUnitUninitialize(player.outputUnit);         //then deallocates unit's resources
AudioComponentInstanceDispose(player.outputUnit); //finally disposes of the AU itself

The sine wave command line app you're after is a well elaborated lesson in this textbook. Please read it step by step.

Last, but not least, your question has nothing to do with C++, CoreAudio is a plain-C API, so C++ in both your title and tag are wrong and misleading.

Upvotes: 2

Related Questions