如何在包装的PortAudio回调中存储音频数据

时间:2015-07-29 15:02:39

标签: callback wrapper portaudio

我正在尝试使用GUI构建一个appilcation来使用PortAudio库录制一些音频,因此我使用的是Qt(c ++)。要做到这一点,我必须包装PortAudio库以使其具有面向对象的样式,并且我遇到了一些使用audiocallback的问题。

初步解释:

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中的&数据是相同的指针,Pa_OpenStream是一个存储audiobuffer的数组,因此可以将音频写入文件。这可以在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,我无法弄清楚如何在“有效”回调函数中设置指向数组的指针(非静态的)

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

1 个答案:

答案 0 :(得分:1)

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

你没有拥有来包装PortAudio以赋予它OO风格。 PortAudio C API在C ++中运行良好。

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