【问题标题】:How to store audio data in a wrapped PortAudio callback如何在包装的 PortAudio 回调中存储音频数据
【发布时间】:2015-10-20 15:45:55
【问题描述】:

我正在尝试使用 GUI 构建一个应用程序来使用 PortAudio 库录制一些音频,因此我使用的是 Qt (c++)。为此,我必须包装 PortAudio 库以使其具有面向对象的样式,并且我遇到了一些与音频回调有关的问题。

初步解释:

PortAudio 使用这样的回调函数:

static int recCallback(const void *inputBuffer,
                          void *outputBuffer,
                          unsigned long framesPerBuffer,
                          const PaStreamCallbackTimeInfo* timeInfo,
                          PaStreamCallbackFlags statusFlags,
                          void *userData)

然后,在PortAudio函数Pa_OpenStream中调用这个回调:

Pa_OpenStream(
            &stream,
            &inputParameters,
            NULL,                  
            SAMPLE_RATE,
            FRAMES_PER_BUFFER,
            paClipOff,     
            recordCallback,
            &data );

回调函数中的*userData 与Pa_OpenStream 中的&data 指针相同,Pa_OpenStream 是一个存储音频缓冲区的数组,以便可以将音频写入文件。这可以在 recCallback 中完成:

static int recordCallback( const void *inputBuffer, void *outputBuffer,
                       unsigned long framesPerBuffer,
                       const PaStreamCallbackTimeInfo* timeInfo,
                       PaStreamCallbackFlags statusFlags,
                       void *userData )
{
//POINTER TO DATA DESTINATION
paTestData *data = (paTestData*)userData;
//POINTER TO INPUT BUFFER
SAMPLE *rptr = (SAMPLE*)inputBuffer;
... //MANIPUALTE AUDIO HERE

将回调函数设为类的成员时会出现问题,例如 WrapperClass。我从here获取了包装模板。

class WrapperClass
{
 virtual int processingCallback(const void *inputBuffer,
                             void *outputBuffer,
                             unsigned long framesPerBuffer,
                             const PaStreamCallbackTimeInfo* timeInfo,
                             PaStreamCallbackFlags statusFlags);

  //portaudio need a static member function as callback,
  //this calls the non-static processing callback 
  method bypassing the object via userData
  static int paStaticCallback(const void *inputBuffer,
                          void *outputBuffer,
                          unsigned long framesPerBuffer,
                          const PaStreamCallbackTimeInfo* timeInfo,
                          PaStreamCallbackFlags statusFlags,
                          void *userData)
{return((WrapperClass*)userData)->processingCallback(inputBuffer,                              outputBuffer, framesPerBuffer, timeInfo, statusFlags,data);
  }

因此,静态回调将 de *userdata 参数作为另一个回调的对象。 现在,在 Pa_OpenStream 中调用回调函数如下:

Pa_OpenStream(&stream,
                  &inputStreamParam,
                  &outputStreamParam,
                  sampleRate,
                  frameLength,
                  paNoFlag,
                  &WrapperClass::paStaticCallback,
                  this);

我认为这样我会向 staticCallback 发送一个 WrapperClass 对象,然后调用虚拟回调。

我不明白的是,现在我错过了用于在非静态回调中存储音频的参数 *userData,我无法弄清楚如何在“有效”回调函数中管理指向数组的指针(非静态的)

谢谢你,希望已经足够清楚了

【问题讨论】:

    标签: callback wrapper portaudio


    【解决方案1】:

    PortAudio 发行版在 bindings/cpp 目录中包含一个 C++ 包装器。

    您没有包装 PortAudio 以赋予其 OO 风格。 PortAudio C API 在 C++ 中运行良好。

    回答您的问题:我希望您的代码的客户端将继承 WrapperClass,覆盖 processingCallback 函数,并将其数据(例如数组)作为成员变量。

    【讨论】:

      猜你喜欢
      • 2016-06-27
      • 1970-01-01
      • 2012-12-16
      • 2012-09-18
      • 2022-06-15
      • 2016-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      相关资源
      最近更新 更多