1

我正在iOS中进行一些Core Audio编程,并且遇到了一种情况,我需要在一些C回调代码中使用我在Objective C中声明的变量。缓冲区变量必须可由 Objective C 和 C 语法访问,但在 C 语法中存在错误提示“使用未声明的标识符缓冲区”。

我该如何解决这个问题?提前致谢。

码头。

变量是缓冲区,在 RIORecerdingViewController.h 中声明如下:

@interface RIORecoerdingViewController : UIViewController <AVAudioSessionDelegate> {
OSStatus status;
AudioComponentInstance audioUnit;

AudioStreamBasicDescription audioFormat;
RIO rio;

IBOutlet UIButton *button;
BOOL isPlaying;
Float64 graphSampleRate;

NSString *destinationFilePath;
CFURLRef destinationURL;
ExtAudioFileRef outExtAudioFile;

// New
AUGraph theGraph;
TPCircularBuffer buffer;
}

我希望在 C 回调函数中使用它

static OSStatus recordingCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                              AudioBufferList *ioData) {

if (rio->recording)
{   
    TPCircularBufferProduceBytes(&buffer, abl.mBuffers[0].mData, inNumberFrames * 2 * sizeof(SInt32)); //&buffer has an error "Use of undeclared identifier buffer"
}
return noErr;
    }
4

3 回答 3

2

您的buffer变量是具体RIORecoerdingViewController实例的实例变量。在没有实例的情况下使用它是没有意义的(“缓冲区属于哪个对象?”)。

所以如果你有一个实例,你可以像往常一样引用 ivar(即yourRecoerdingViewController->buffer如果你想走 C 指针路线)。

于 2012-10-30T09:05:48.953 回答
1

这就是你的void * inRefCon论点的recordingCallback目的。当您设置 RemoteIO 回调时,它可能看起来像这样:

AURenderCallbackStruct callbackInfo;
callbackInfo.inputProc = &recordingCallback;
callbackInfo.inputProcRefCon = NULL;

AudioUnitSetProperty(rio,
                     kAudioOutputUnitProperty_SetInputCallback,
                     kAudioUnitScope_Global,
                     0,
                     &callbackInfo,
                     sizeof(callbackInfo));

您可以将用作在回调期间inputProcRefCon将成为指针的任意指针。inRefCon如果您只想访问一个变量,这很容易(您只需传入该变量的地址)。例如,如果您只需要 TPCircularBuffer:

callbackInfo.inputProcRefCon = &buffer;

然后当你recordingCallback被调用时,你可以通过 arg 访问你的缓冲区,inRefCon如下所示:

TPCircularBuffer * bufferPtr = (TPCircularBuffer *)inRefCon;
TPCircularBufferProduceBytes(bufferPtr, abl.mBuffers[0].mData, inNumberFrames * 2 * sizeof(SInt32));

如果您需要访问更多变量(例如recording布尔值),您可以创建一个结构并传递它的地址。

大街上的消息是,您应该避免在 AURenderCallbacks 中调用 Objective-C 调用(由于消息传递开销),但我目前没有任何硬数据来支持这一点。您可以传递selfinputProcRefCon,但 YMMV。

于 2012-10-30T20:26:41.367 回答
1

Objective C 是纯 C 的纯超集。它允许您将对象和实例变量指针复制到标准 C 全局变量、参数变量和结构(等)

一种(被认为是丑陋的)可能性是将缓冲区指针复制到 C 全局变量中(并确保手动将其置空,或者在释放缓冲区时不使用它)。然后从任何地方访问它,任何 C 函数。

其他(可能更优雅)的可能性包括将缓冲区指针复制到传递给 C 回调的结构中,或者将指向对象本身的指针直接或通过结构元素传递给 C 回调。然后,您可以使用 .m 文件中 C 函数的“->”语法来访问传递给标准 C 函数的任何对象的任何实例变量,例如音频单元回调。(必须在 .m 文件中声明 C 函数,以便可以导入用于对象定义的 Objective C 接口。)

还有另一种可能性,但不适合音频回调,是让 C 函数(在 .m 文件中)向单例模型对象发送消息,以获取/设置模型对象状态(包括缓冲区指针)。

于 2012-10-30T21:54:25.010 回答