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: Doug Wyatt <email@hidden>
- Date: Fri, 09 Dec 2016 11:21:42 -0800
In the case of anything else built on AUBase, including AUMultiChannelMixer, it's not a matter of the property being changed asynchronously and waiting for a notification (I'm reinstalling Xcode at the moment, hard to look at code, but from memory, setting the render callback might not send a notification anyhow).
The usual problem is that one can be in the middle of rendering upstream of the AU while trying to disconnect, and it's not the AU's responsibility to protect against that.
One solution is to use a mutex. Lock the mutex around the call to SetRenderCallback. When rendering upstream from the mixer, try to lock the mutex; if it fails, you know disconnection is in progress and can bail out. The realtime thread won't block because you're only trying to lock the mutex.
> On Nov 27, 2016, at 15:18 , Brian Willoughby <email@hidden> wrote:
>
> 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
_______________________________________________
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