C PortAudio回调,并在别处更改变量

C PortAudio回调,并在别处更改变量,c,thread-safety,portaudio,C,Thread Safety,Portaudio,我正在使用PortAudio的回调API设计一个信号处理环回库 我想添加一个分支,它依赖于回调中的标志,如下所示 int pa_callback(const void *inputuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo,

我正在使用PortAudio的回调API设计一个信号处理环回库

我想添加一个分支,它依赖于回调中的标志,如下所示

int pa_callback(const void *inputuffer,
                 void *outputBuffer,
                 unsigned long frameCount,
                 const PaStreamCallbackTimeInfo *timeInfo,
                 PaStreamCallbackFlags statusFlags,
                 void *userData)
{
  if (do_something_flag) {
    do_something(inputBuffer, outputBuffer, frameCount);
  } else {
    do_something_else(inputBuffer, outputBuffer, frameCount);
  }

  return paContinue;
}
其中,
do\u something\u标志
在我的程序中的其他地方定期设置

PortAudio回调文档说明:

在开始之前,重要的是要认识到回调是一个 微妙的地方。这是因为某些系统在 特殊的线程,或中断处理程序,它很少被 与代码的其余部分相同。对于大多数现代系统,您不会 能够通过在回调中进行不允许的调用而导致崩溃,但是 如果你想让你的代码产生无故障的音频,你必须 请确保避免可能占用无限量的函数调用 有足够的时间来执行。具体是什么取决于您的平台,但 几乎可以肯定包括以下内容:内存 分配/解除分配、I/O(包括文件I/O和控制台 I/O,如printf()),上下文切换(如exec()或yield()), 互斥操作,或任何其他可能依赖操作系统的操作。如果你 认为短的关键部分是安全的,请阅读有关优先级的内容 倒置

我不关心
do\u something\u标志的原子性。也就是说,我不在乎需要多少个周期才能得到正确的值(在合理范围内)。
根据文档,看起来我无法使用互斥体来设置/读取该变量

1) 我有什么选择

2) 如果我将其设置为全局,并将其设置在程序的另一部分(另一个线程),那么最糟糕的情况是什么?同样,我指的是破坏数据,导致程序失败等


有没有一种正确的方法可以做到这一点?

我不完全确定您到底想做什么,但我猜这就是您的标题所要求的——“在其他地方更改变量”

让我们举个例子:您有一个随时间变化的变量
频率。你如何访问这个?在回调中有一个名为
userData
的通用指针。这可以指向任何东西——数据结构、数组等等。我真的不记得回调函数被调用的频率(通常……我不担心速度)但是
userData
允许您在主线程中更改变量,而音频线程中的指针允许您直接在内存中访问它。。。我在线程安全方面的知识不是最好的,如果这不是最好的解释,那么很抱歉,但我至少可以通过代码(如下)向您展示如何做到这一点

这是我通常做的,但你不需要自己做;我在文件顶部设置了一个结构,如下所示:

typedef struct {
    float freq;
    float vol;
}paData;
显然,您将在代码中的某个地方初始化它(可能在
main
函数调用中),并打开音频流(
data
类型为
paData
):

打开后,您可以按如下方式进行回调:

static int pa_callback(const void *inputBffer,
             void *outputBuffer,
             unsigned long frameCount,
             const PaStreamCallbackTimeInfo *timeInfo,
             PaStreamCallbackFlags statusFlags,
             void *userData)
{
    // cast data so we can use it
    paData *data = (paData *)userData;

    // what's our frequency?
    printf("%f\n", data->freq);

    /* Do something with your code here */

    return paContinue;
}

希望能有帮助。

是的,太好了。我非常关心线程安全性、原子性和全局变量,我没有看到简单的答案:PA给了你这个机制。你不用担心,你自己学习一个新的API很难。。。幸运的是,当我学习PortAudio时,我有一位很棒的老师,所以这让事情变得容易多了。祝你好运!您好@yun.cloud,我最近开始使用portaudio进行语音采集和处理,在实现过程中遇到了一些问题。我已经在stackoverflow上发布了这个问题()。非常感谢您的任何帮助。
static int pa_callback(const void *inputBffer,
             void *outputBuffer,
             unsigned long frameCount,
             const PaStreamCallbackTimeInfo *timeInfo,
             PaStreamCallbackFlags statusFlags,
             void *userData)
{
    // cast data so we can use it
    paData *data = (paData *)userData;

    // what's our frequency?
    printf("%f\n", data->freq);

    /* Do something with your code here */

    return paContinue;
}