使用openFrameworks + CoreAudio

时间:2011-07-14 02:50:17

标签: c++ core-audio openframeworks

我的C ++技能很轻但我设法完成任务 - 直到我碰壁。目前的墙:

我正在使用CoreAudio来做一些Midi播放的东西。我有很多工作,但我坚持一个简单的事情。 (我不知道正确的C ++术语,所以请耐心等待......)。

我在CoreAudio中使用渲染回调函数来指示何时由AU渲染midi音符事件。如果我将它定义为非类函数并坚持使用main.cpp(或testApp.cpp),它就可以了 - 我得到了事件。问题是我需要能够让testApp的实例获得这些事件。

那么..有没有办法从main.cpp获取testApp的实例,所以我可以调用我需要的testApp方法?

OR是否有一些C ++ voodoo有一个非类函数驻留在类中调用实例的方法?例如,如果下面的函数在我的类中,它如何调用类的实例上的方法...

    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()不匹配(void ,   AudioUnitRenderActionFlags *,const AudioTimeStamp *,UInt32,UInt32,   AudioBufferList *)

4 个答案:

答案 0 :(得分:2)

您不需要乱用静态实例来执行此操作。添加渲染回调时,将C ++对象作为refcon传递,然后将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
}

答案 1 :(得分:0)

sbooth的answer anwser,因为api设计师为您提供了一个很好的技巧。但是,如果您将回调传递给设计较差的c库,则下面的答案可能有所帮助。

你需要从指向成员的函数到指向函数的指针。

c ++ faq lite herehere有你的答案

你可以:

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 ++知识,我建议你阅读所有faq lite,然后阅读fqa。我希望有人在我开始时向我推荐它。

答案 2 :(得分:0)

你是正确的,你不能在这里使用指向实例方法的指针(由于回调实际上没有通过对象调用,所以无法提供隐式的'this'指向成员函数的指针)。

你可以使用静态成员函数(然后你需要一些方法来提供指向testApp实例的指针(全局变量,静态实例等))。

答案 3 :(得分:0)

如果你可以安装boost,boost :: bind可以为你做这个。