使用 openFrameworks +核心音频

发布于 2024-11-19 17:22:44 字数 1445 浏览 5 评论 0原文

我的 C++ 技能很薄弱,但我设法完成工作 - 直到我碰壁。当前的墙:

我正在使用 CoreAudio 来做一些 Midi 播放的事情。我已经完成了很多工作,但仍停留在一件简单的事情上。 (我不知道正确的 C++ 术语,所以请耐心等待......)。

我在 CoreAudio 中使用渲染回调函数来指示 AU 何时渲染 MIDI 音符事件。如果我将它定义为非类函数并将其粘贴到 main.cpp (或 testApp.cpp ),它就会起作用 - 我会收到事件。问题是我需要能够让 testApp 的实例获取这些事件。

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

或者是否有一些 C++ 巫术让类中的非类函数调用实例的方法?例如,如果下面的函数在我的类中,它如何调用类实例上的方法...

    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, 音频缓冲区列表*)

my C++ skills are pretty light but I manage to get stuff done - until I run into a wall. The current wall:

I am using CoreAudio to do some stuff with Midi playback. I've got lots of it working but am stuck on a simple thing. (I don't know the right C++ terminology so bear with me...).

I'm using a render callback function in CoreAudio to indicate when a midi note event is being rendered by an AU. If I define it as a non-class function and stick it main.cpp (or testApp.cpp for that matter) it works - I get the events. The problem is I need to be able to have the instance of testApp get those events.

So.. is there a way to get at the instance of testApp from main.cpp so I can call the testApp method I need?

OR is there some C++ voodoo to have a a non-class function residing within a class call a method of an instance? For example, if the function below is in my class, how can it call a method on the instance of the class...

    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

}

I don't know for sure but I think the CoreAudio stuff doesn't take instance methods as callbacks - at least that's what I've gleaned from the error msg (below). I'm fine doing it anyway that works.

thanks for any tips!

error: argument of type OSStatus (testApp::)(void*,
AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32,
AudioBufferList*)' does not match 'OSStatus ()(void,
AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32,
AudioBufferList*)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

本宫微胖 2024-11-26 17:22:44

您不需要搞乱静态实例来执行此操作。添加渲染回调时,将 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
}

You don't need to mess with static instances to do this. When you add the render callback, pass your C++ object as the refcon, and then cast the refcon to your object in the callback:

// 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
}
偏爱你一生 2024-11-26 17:22:44

您是正确的,您不能在此处使用指向实例方法的指针(无法向成员函数提供隐式“this”指针,因为回调实际上并未通过对象调用)。

您可以为此使用静态成员函数(然后您需要某种方式为该函数提供指向 testApp 实例的指针(全局变量、静态实例等))。

You're correct that you can't use a pointer to an instance method here (there's no way of providing the implicit 'this' pointer to the member function since the callback isn't actually getting called through an object).

You can use a static member function for this (then you'll need some way of providing that function with a pointer to an instance of your testApp (global variable, static instance, etc)).

你列表最软的妹 2024-11-26 17:22:44

如果您可以安装 boost,boost::bind 可以为您完成此操作。

If you can install boost, boost::bind can do this for you.

对岸观火 2024-11-26 17:22:44

sbooth 的答案答案api 设计者为您提供了一个很好的技巧。不过,如果您将回调传递到设计较差的 C 库中,下面的答案可能会有所帮助。

您需要从指向成员函数的指针转换为指向函数的指针。

C++ faq lite 此处这里有您的答案

您可以:

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。我希望在我开始时有人向我推荐它。

sbooth's answer is the anwser here as the api designers have provided you with a nice trick. If you were passing a callback into a less well designed c library, though, the answer below may help.

You need to get from a pointer-to-member-function to pointer-to-function.

The c++ faq lite here and here has your answer

You can either:

1. Make someMethod() static and keep a static instance of testApp (if you need to twiddle instance data)
2. Store a testApp pointer globally and use it from the global function you are already using

Here is an example of method 1, which I would recommend

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;
}

Given where you are with your c++ knowledge, I would really recommend reading all of the faq lite and then the fqa. I wish someone had recommended it to me when I started.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文