使用openFrameworks+;核心音频 我的C++技能很轻,但我设法把事情做完——直到我撞到墙上。当前墙:
我正在使用CoreAudio做一些Midi播放的事情。我有很多工作要做,但我只做了一件简单的事情。(我不知道正确的C++术语,所以请容忍我……) 我在CoreAudio中使用一个render回调函数来指示AU渲染midi音符事件的时间。如果我将它定义为一个非类函数并将其粘贴到main.cpp(或testApp.cpp)上,它就可以工作了——我得到了事件。问题是我需要能够让testApp实例获取这些事件 所以。。有没有办法从main.cpp获取testApp实例,以便调用所需的testApp方法使用openFrameworks+;核心音频 我的C++技能很轻,但我设法把事情做完——直到我撞到墙上。当前墙:,c++,core-audio,openframeworks,C++,Core Audio,Openframeworks,我正在使用CoreAudio做一些Midi播放的事情。我有很多工作要做,但我只做了一件简单的事情。(我不知道正确的C++术语,所以请容忍我……) 我在CoreAudio中使用一个render回调函数来指示AU渲染midi音符事件的时间。如果我将它定义为一个非类函数并将其粘贴到main.cpp(或testApp.cpp)上,它就可以工作了——我得到了事件。问题是我需要能够让testApp实例获取这些事件 所以。。有没有办法从main.cpp获取testApp实例,以便调用所需的testApp方法
还是有一些C++ Vodoo有一个类中的非类函数调用一个实例的方法?例如,如果下面的函数在我的类中,它如何调用类实例上的方法
OSStatus renderCallback(void *inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
someClassMethod(); // doesn't work
this.someClassMethod(); // doesn't work
self.someClassMethod(); // doesn't work
}
我不确定,但我认为CoreAudio并没有将实例方法作为回调——至少这是我从错误消息(如下)中收集到的。不管怎么说,我都很好,这很有效
谢谢你的提示
错误:OSStatus类型的参数(testApp::)(void*,
AudioUnitRenderActionFlags*,const AudioTimeStamp*,UInt32,UInt32,
AudioBufferList*)'与'OSStatus()(无效,
AudioUnitRenderActionFlags*,const AudioTimeStamp*,UInt32,UInt32,
音频缓冲列表*)
sbooth是这里的anwser,因为api设计师为您提供了一个很好的技巧。但是,如果将回调传递到设计不太好的c库中,下面的答案可能会有所帮助
您需要从指向成员函数的指针到指向函数的指针
C++ FAQ Lite,并有你的答案< /P> 您可以:
1.使someMethod()保持静态,并保留testApp的静态实例(如果需要旋转实例数据) 2。全局存储testApp指针,并从已使用的全局函数中使用它 下面是我推荐的方法1的一个示例class Test
{
public:
Test();
void InstanceCallback();
static void StaticCallbackMethod();
private:
static Test* instance;
};
// Normally in cpp
Test* Test::instance = 0;
Test::Test()
{
instance = this;
}
void Test::InstanceCallback()
{
// do stuff;
}
void Test::StaticCallbackMethod()
{
if (instance)
{
instance->InstanceCallback();
}
}
int main()
{
Test* t = new Test();
void (*mf)();
mf = &Test::StaticCallbackMethod;
mf();
return 0;
}
在你的C++知识的基础上,我真的建议阅读所有的,然后。我希望在我开始时有人向我推荐它。
您是正确的,您不能在这里使用指向实例方法的指针(无法提供指向成员函数的隐式“this”指针,因为回调实际上不是通过对象调用的)您可以为此使用静态成员函数(然后您需要某种方式为该函数提供指向testApp实例(全局变量、静态实例等)的指针)。如果您可以安装boost,boost::bind可以为您做到这一点。您不需要使用静态实例来完成此操作。添加渲染回调时,将C++对象作为ReFCON传递,然后将回调映射到回调中的对象:
// The actual callback is defined as a static function
static OSStatus
myAURenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
MyClass *object = static_cast<MyClass *>(inRefCon);
return object->Render(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}
// When adding the render callback pass this as the context
AURenderCallbackStruct cbs = { myAURenderCallback, this };
OSStatus result = AUGraphSetNodeInputCallback(graph, node, 0, &cbs);
// The callback will look like
OSStatus MyClass::Render(AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
// Do something
}
//实际回调被定义为静态函数
静态骨状态
myAURenderCallback(在Refcon中无效*,
AudioUnitRenderActionFlags*ioActionFlags,
常量音频时间戳*inTimeStamp,
UInt32 InBunsNumber,
UInt32数字帧,
音频缓冲列表*ioData)
{
MyClass*object=static\u cast(inRefCon);
返回对象->渲染(ioActionFlags、inTimeStamp、inBusNumber、inNumberFrames、ioData);
}
//添加渲染回调时,将其作为上下文传递
AURenderCallbackStruct cbs={myAURenderCallback,this};
OSStatus结果=AUGraphSetNodeInputCallback(图形、节点、0和cbs);
//回调将如下所示
OSStatus MyClass::Render(AudioUnitRenderActionFlags*ioActionFlags,
常量音频时间戳*inTimeStamp,
UInt32 InBunsNumber,
UInt32数字帧,
音频缓冲列表*ioData)
{
//做点什么
}
这是一个漂亮的API技巧,显然有人在考虑人们如何使用它。在我的回答中,我假设询问者正在调用一个常规的c库。是的,苹果清楚地意识到这个API通常是如何使用的。我似乎还记得在Pascal工具箱编程时代的这种模式,所以我认为它已经存在了一段时间。谢谢大家的回复。我能够用上面的方法使它工作。CoreAudio一开始用所有的指针让我困惑,但我已经掌握了窍门。