Objective c AudioQueue回调和inUserData指针生存期
我一直在用Objective-C开发一个应用程序,它使用Objective c AudioQueue回调和inUserData指针生存期,objective-c,callback,core-audio,Objective C,Callback,Core Audio,我一直在用Objective-C开发一个应用程序,它使用AudioQueueNewOutput。我有其他声音库的经验,所以回调机制很熟悉。然而,我遇到的一个问题是inUserData指针。调用AudioQueueStop时,即使immediate设置为true,回调也可以再次运行。这使得在调用AudioQueueStop的同时取消分配用户指针中的内容是不合适的 这是运行kaudioqueproperty\u的目的吗?该侦听器的回调是否保证不会再次调用队列回调,并且可以安全地释放用户指针 如果这不
AudioQueueNewOutput
。我有其他声音库的经验,所以回调机制很熟悉。然而,我遇到的一个问题是inUserData
指针。调用AudioQueueStop
时,即使immediate设置为true,回调也可以再次运行。这使得在调用AudioQueueStop
的同时取消分配用户指针中的内容是不合适的
这是运行kaudioqueproperty\u的目的吗?该侦听器的回调是否保证不会再次调用队列回调,并且可以安全地释放用户指针
如果这不是正确的机制,那么我很难想象会是什么。回调可以尝试同步调用AudioQueueStop
后它认为剩下的缓冲区数量,但这似乎很脆弱。我希望避免像在这么多秒后释放或内存泄漏这样的黑客行为。根据苹果公司的说法,任何类型的内存管理都不应该在音频上下文回调中进行。在启动音频单元或队列之前,应在回调外部预先分配或保留回调所需的所有内存。因此,在任何音频回调中,retain状态都应该是无关紧要的
为了最大限度地谨慎,我不会在应用程序终止之前释放音频缓冲区(如果有调用)。与应用程序的总内存占用相比,音频缓冲区通常非常小。我没有泄漏,而是把它们放在水池里,直到需要时再放(如果有的话)
如果您真的想取消分配,因为您知道采样率和缓冲区的大小,您可以估计所有活动缓冲区清空需要多长时间。四倍于此(考虑到潜在的操作系统双缓冲),估计应该是相当安全的。事实证明,您可以使用属性侦听器安全地执行此操作。特别是,kaudioqueproperty\u正在运行
。您的对象可以保留自身的引用,然后在队列停止运行时nil
it
例如,
@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
只有在队列启动和停止时才调用属性侦听器回调。如果AudioQueueGetProperty
对此属性产生0,则不会再次调用回调,您可以安全地解除分配。我就是这样做的。这似乎总是很老套,但这是解决问题的务实办法。只需从dealloc中释放dispatch_after块中的渲染内存。要清楚,我希望释放的不仅仅是缓冲区,尽管我也想释放缓冲区。在我的例子中,给回调的用户指针想要取消分配,但它不能,因为回调可能仍在使用它。因此,那里的内存使用量更大一些。