I've been working on an application in Objective-C that uses AudioQueueNewOutput
. I've got experience with other sound libraries so the callback mechanism is familiar. However, one issue I've had is with the inUserData
pointer. When you call AudioQueueStop
, even with immediate set true, the callback can run again. This makes it inappropriate to deallocate whatever is in the user pointer at the same time as calling AudioQueueStop
.
Is this the purpose of kAudioQueueProperty_IsRunning
? Does the callback of that listener guarantee that the queue callback will not be called again and that the user pointer is safe to be deallocated?
If that is not the correct mechanism, then it's hard for me to think of what could be. The callback could try to synchronize how many buffers it thinks are left after AudioQueueStop
has been called, but that seems fragile. I would like to avoid hacks like deallocating after so many seconds or leaking memory.
It turns out that you can use property listeners to do this safely. In particular, kAudioQueueProperty_IsRunning
. Your object can keep a reference of itself and then nil
it when the queue stops running.
As an example,
@interface Foo : NSObject
@end
@implementation Foo {
AudioQueueRef queue;
Foo *inUse;
}
static void listener_callback(void *user_data, AudioQueueRef queue,
AudioQueuePropertyID prop) {
Foo *p = (__bridge id)user_data;
UInt32 res;
UInt32 resSize = sizeof(res);
AudioQueueGetProperty(queue, kAudioQueueProperty_IsRunning, &res, &resSize);
if (resSize == sizeof(UInt32) && res == 0) {
p->inUse = nil;
}
}
- (id)init {
// ... set up self and audio queue
// create some kind of playback callback
inUse = self;
AudioQueueAddPropertyListener(queue, kAudioQueueProperty_IsRunning,
listener_callback,
(__bridge void *_Nullable)self);
AudioQueueStart(queue, NULL);
return self;
}
@end
The property listener callback is only called when the queue starts and stops. If AudioQueueGetProperty
yields 0 for this property, then the callback will not be called again and you are safe to deallocate.