c - 对将用户数据传递到PortAudio回调感到困惑

标签 c audio callback portaudio

这是我在这里的第一篇文章,我对编程特别是C还是陌生的。几周前,我开始阅读《音频编程书》(MIT出版社),并扩展了一些示例以尝试进一步理解事物。

我认为我的问题在于我如何尝试将数据(在初始化函数中从用户检索到)传递给PortAudio回调。我觉得我所做的与示例(书中和PortAudio的示例,例如paex_sine.c)没有什么不同,但是由于某些原因,我的代码无法正常工作,我一直在努力工作试图理解为什么靠在墙上。我已经尝试过广泛地搜索解决方案或示例代码以进行研究,但是我有点不知道我不知道什么,因此返回的并不多。

如何使用户数据进入回调?

我是不是只是不了解指针和结构如何工作,并试图迫使它们去做自己不想做的事情?

还是我只是忽略了一些明显的东西?

下面的代码给出了很高的音调输出,较短的高音调尖音或无(可听)输出:

#include <stdio.h>
#include <math.h>
#include "portaudio.h"

#define FRAME_BLOCK_LEN 64
#define SAMPLING_RATE 44100
#define TWO_PI (3.14159265f * 2.0f)

PaStream *audioStream;
double si = 0;

typedef struct
{
  float frequency;
  float phase;
}
paTestData;

int audio_callback (const void *inputBuffer, void *outputBuffer,
                    unsigned long framesPerBuffer,
                    const PaStreamCallbackTimeInfo* timeinfo,
                    PaStreamCallbackFlags statusFlags,
                    void *userData )
{
  paTestData *data = (paTestData*)userData;
  float *out = (float*)outputBuffer;
  unsigned long i;
  // data->frequency = 400;

  for(i = 0; i < framesPerBuffer; i++){
    si = TWO_PI * data->frequency / SAMPLING_RATE;  // calculate sampling-incr

    *out++ = sin(data->phase);
    *out++ = sin(data->phase);

    data->phase += si; // add sampling-incr to phase
  }

  return paContinue;
}

void init_stuff()
{
  float frequency;
  int i;
  PaStreamParameters outputParameters;
  paTestData data;

  printf("type the modulator frequency in Hz: ");
  scanf("%f", &data.frequency);  // get modulator frequency
  printf("you chose data.frequency %.2f\n",data.frequency);

  data.phase = 0.0;

  printf("initializing Portaudio. Please wait...\n");
  Pa_Initialize();  // initialize Portaudio

  outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
  outputParameters.channelCount = 2;       /* stereo output */
  outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
  outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
  outputParameters.hostApiSpecificStreamInfo = NULL;

  Pa_OpenStream(              // open paStream object
          &audioStream,       // portaudio stream object
          NULL,               // input params
          &outputParameters,  // output params
          SAMPLING_RATE,      // SampleRate
          FRAME_BLOCK_LEN,    // frames per buffer
          paNoFlag,           // set no Flag
          audio_callback,     // callbak function address
          &data );            // user data

  Pa_StartStream(audioStream);  // start the callback mechanism
  printf("running... press space bar and enter to exit\n");
}

void terminate_stuff()
{
  Pa_StopStream(audioStream);   // stop callback mechanism
  Pa_CloseStream(audioStream);  // destroy audio stream object
  Pa_Terminate();               // terminate portaudio
}

int main(void)
{
  init_stuff();
  while(getchar() != ' ') Pa_Sleep(100);
  terminate_stuff();
  return 0;
}

取消注释data->frequency = 400;至少会播放400hz正弦波,但这会忽略在init_stuff()中完成的任何用户输入

如果我在回调中放入printf("%f\n",data->frequency);,它将输出0.000000或-146730090609497866240.000000之类的内容。
这是非常不可预测的,这确实使我认为它与指针相关。

我编写此代码的目标是最终合并包络发生器以改变音高,并可能合并波表振荡器,因此我不会为每次迭代计算sin(x)。
我可以使用书中使用的类似portf的阻塞API来使信封和波形表正常工作,但是尝试改编早期章节中的任何代码以使用PortAudio回调,这让我不禁思索。

非常感谢!

最佳答案

您的回调数据存在的问题是,它超出了范围,并且一旦init_stuff完成执行,内存便被释放。

您应该使用mallocnew为回调数据分配内存,并将指针传递给回调。

例如:

void init_stuff()
{
  float frequency;
  int i;
  PaStreamParameters outputParameters;
  paTestData *data = (paTestData *) malloc(sizeof(paTestData));


  printf("type the modulator frequency in Hz: ");
  scanf("%f", &(data->frequency));  // get modulator frequency
  printf("you chose data.frequency %.2f\n",data->frequency);

  data->phase = 0.0;

  ...

   Pa_OpenStream(              // open paStream object
      &audioStream,       // portaudio stream object
      NULL,               // input params
      &outputParameters,  // output params
      SAMPLING_RATE,      // SampleRate
      FRAME_BLOCK_LEN,    // frames per buffer
      paNoFlag,           // set no Flag
      audio_callback,     // callbak function address
      data );   

  ... 

关于c - 对将用户数据传递到PortAudio回调感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60458785/

相关文章:

javascript - 具有回调功能的欧芹验证器无法正常工作

C++ printf 只出现在最后

c - 是否存在非数组不完整类型?

c - 使用 FreeRTOS 二进制信号量的硬件中断

ios - 检测并读取任何出站音频信号 iOS

android - 在后台播放视频中的音频

c - 如何释放从另一个函数返回的 char*?

math - 主动噪声消除的原理是什么?

node.js - 在从第一个导致未定义的数据中获取数据之前,我的第二个 promise 被调用。不确定我在做什么

javascript - 如何将 SQLite 结果传递给 Nodejs 中的回调