如何在C#中使用PaStreamCallbackDelegate

时间:2014-01-24 15:47:55

标签: c# callback delegates stream portaudio

我需要使用 PaStreamCallbackDelegate 将回调函数传递给 Pa_OpenDefaultStream ,以便我可以启动Stream。 我像你一样在互联网上查看,但也按照描述进行操作,它给了我这个错误:

对应于委托PortAudio.PaStreamCallbackDelegate

的StreamCallback没有重载

我不知道如何解决它。我对 C#语言知之甚少,我现在才开始使用库 PortAudio

我在这里发布我的代码:

unsafe public PortAudio.PaStreamCallbackResult StreamCallback(
        IntPtr* input,
        IntPtr* output,
        uint frameCount,
        ref PortAudio.PaStreamCallbackTimeInfo timeInfo,
        PortAudio.PaStreamCallbackFlags statusFlags,
        IntPtr* userData) 
    {
        //Aggiungi roba
        int i;

        for (i = 0; i < frameCount; i++)
        {
             output++;           //LEFT
             output = input++;

             output++;           //RIGHT
             output = input++;
        }
        return PortAudio.PaStreamCallbackResult.paContinue;
    }

    unsafe private void btnStream_Click(object sender, EventArgs e)
    {
        //Dichiarazioni
        IntPtr* input;
        IntPtr* output;
        uint frameCount;
        PortAudio.PaStreamCallbackTimeInfo timeInfo;
        PortAudio.PaStreamCallbackFlags statusFlags;
        IntPtr* userData;

        IntPtr stream;

        PortAudio.PaError err = PortAudio.Pa_Initialize();
        if (err != PortAudio.PaError.paNoError)
            PortAudio.Pa_Terminate();

        err = PortAudio.Pa_OpenDefaultStream(out stream, 
                                                      1,
                                                      1,
               (uint)PortAudio.PaSampleFormat.paFloat32,
                                                  44100,
                 PortAudio.paFramesPerBufferUnspecified,
 new PortAudio.PaStreamCallbackDelegate(StreamCallback),  //In this row it gives me the error
                                          (IntPtr)null);

如果有人知道如何帮助我,我将非常感激,谢谢。

1 个答案:

答案 0 :(得分:1)

您的输入,输出和用户数据参数应为IntPtr类型,而不是IntPtr*

此外,我认为你并没有在你的回调方法中制作副本。我真的认为你应该使用一些IntPtr方法。我从未在.Net中使用不安全的类型,但是查看copy sample我相信你的算法会是这样的:

unsafe public PortAudio.PaStreamCallbackResult StreamCallback(
        IntPtr input,  IntPtr output,  uint frameCount,
        ref PortAudio.PaStreamCallbackTimeInfo timeInfo,
        PortAudio.PaStreamCallbackFlags statusFlags,
        IntPtr userData) 
{
    byte *src = (byte *)input.ToPointer();
    byte *dst = (byte *)output.ToPointer();
    for (int i = 0; i < frameCount; i++)
    {
         *dst++ = *src++;//in c this could be written dst[i] = src[i] maybe you can try that.
    }
    return PortAudio.PaStreamCallbackResult.paContinue;
}

编辑:根据Hans Passant的说法,您还应该将您的代理人保存在一个字段中,这样就不会收集垃圾。但 AFAIK 将它存储在变量中就足够了,因为只要至少有一个对象的引用,垃圾收集就不会清理你的对象。这仅适用于回调发生在定义它的同一方法中,否则您应该存储在他声明的字段中。

unsafe private void btnStream_Click(object sender, EventArgs e)
{
    //Dichiarazioni
    IntPtr* input;
    IntPtr* output;
    uint frameCount;
    PortAudio.PaStreamCallbackTimeInfo timeInfo;
    PortAudio.PaStreamCallbackFlags statusFlags;
    IntPtr* userData;

    IntPtr stream;

    PortAudio.PaError err = PortAudio.Pa_Initialize();
    var callback = new PortAudio.PaStreamCallbackDelegate(StreamCallback);
    if (err != PortAudio.PaError.paNoError)
        PortAudio.Pa_Terminate();

    err = PortAudio.Pa_OpenDefaultStream(out stream,  1, 1,
           (uint)PortAudio.PaSampleFormat.paFloat32,
                                              44100,
             PortAudio.paFramesPerBufferUnspecified,
                          callback,
                                      (IntPtr)null);