Re: How to safely dispose of audio converter
Re: How to safely dispose of audio converter
- Subject: Re: How to safely dispose of audio converter
- From: Brian Willoughby <email@hidden>
- Date: Sun, 27 Nov 2016 15:18:52 -0800
CoreAudio is multi-threaded, and the calls you're dealing with are asynchronous. That means other threads can still be in the process of accessing resources even after your calls to disconnect the resources have returned.
What you need to do is register for one or more property change notifications. CoreAudio will then call your notification callbacks when the audio threads have finished with your requested changes.
As one example, I assume that you must have called Start on the Output AU in order to get your callback working. You should probably then call Stop on the same Output AU in order to cease the callback. There are various property change notifications associated with Running or stopped audio units. You could use the callbacks to trigger freeing of the shared resources.
As another example, since you're using the SetRenderCallback property to disconnect your callback, then I assume there is a property change notification for SetRenderCallback that you could use to synchronize your resource deallocation.
In either case, your application needs to wait for all the requested changes to take effect, by listening for the notifications, before freeing the audio converter.
Brian Willoughby
Sound Consulting
On Nov 27, 2016, at 8:51 AM, Andreas Falkenhahn <email@hidden> wrote:
> I am using a render callback to send PCM data to the audio hardware, it is installed
> like this:
>
> callback.inputProc = MixerInputCallback;
> callback.inputProcRefCon = ci;
>
> AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(AURenderCallbackStruct));
>
> My MixerInputCallback() then looks like this:
>
> static OSStatus MixerInputCallback(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
> {
> struct channelinfo *ci = (struct channelinfo *) inRefCon;
>
> AudioConverterFillComplexBuffer(ci->converter, ACComplexInputProc, inRefCon, &inNumFrames, ioData, NULL);
>
> return noErr;
> }
>
> Now how can I safely dispose of the audio converter object accessed in MixerInputCallback()?
> i.e. I need to make sure that the converter isn't accessed while I'm trying to kill it.
>
> AFAIU I'm not allowed to use any form of mutex protection inside MixerInputCallback()
> because it's running on the audio I/O proc and mustn't block.
>
> So how can I make sure that it is safe to kill the audio converter? I've tried to kill the render
> callback first, like so:
>
> callback.inputProc = NULL;
> callback.inputProcRefCon = NULL;
>
> AudioUnitSetProperty(mixerAudioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(AURenderCallbackStruct));
>
> And then kill the audio convert using
>
> AudioConverterDispose(ci->converter);
>
> But it doesn't work. Running a stress test with such code often leads to memory access faults
> when disposing of the converter.
>
> So how can I make sure that the audio converter is no longer in use when calling AudioConverterDispose()?
> I'd somehow need to find a way to wait for the completion of MixerInputCallback() while at the same
> time forbidding Core Audio to run MixerInputCallback() again. I don't think this is as easy as setting
> a flag because multithreading is involved and MixerInputCallback() runs on the audio I/O proc.
>
> So how can I do this? How can I safely stop my MixerInputCallback() so that I can safely dispose of
> the audio converter accessed by MixerInputCallback()?
>
> --
> Best regards,
> Andreas Falkenhahn mailto:email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden