c - PaStreamCallbackTimeInfo成员全部为0

标签 c linux alsa portaudio

来自PortAudio docs :

Stream Timing Information

When using the callback I/O method your stream callback function receives timing information via a pointer to a PaStreamCallbackTimeInfo structure. This structure contains the current time along with the estimated hardware capture and playback time of the first sample of the input and output buffers. All times are measured in seconds relative to a Stream-specific clock. The current Stream clock time can be retrieved using Pa_GetStreamTime().

所以 PaStreamCallbackTimeInfo::currentTime 以某种方式指示当前时间,而 PaStreamCallbackTimeInfo::outputBufferDacTime 应该指示当前缓冲区中第一个样本的输出时间。我不知道为什么,但在 Linux 上,这些值对我来说都是零。也许我做错了什么。这是代码和输出:

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

#define PI 3.14159265359
#define SRATE 44100
#define FREQ 440
#define DURATION 5000

int
audio_callback(
    const void* inbuf,
    void* outbuf,
    unsigned long bufsize,
    const PaStreamCallbackTimeInfo* time_info,
    PaStreamCallbackFlags status_flags,
    void* user_data)
{
    (void)inbuf;
    (void)status_flags;

    double* phase = (double*)user_data;
    float* out = (float*)outbuf;

    printf(
        "current time = %f; out time = %f\n",
        time_info->currentTime,
        time_info->outputBufferDacTime);

    for (unsigned long i = 0; i < bufsize; i++)
    {
        *phase += 2 * PI * FREQ / SRATE;
        out[i] = sin(*phase);
    }

    return 0;
}

int     
main(int argc, char** argv)
{
    (void)argc;
    (void)argv;

    PaError pa_error;
    PaStream* stream = NULL;
    int error = 0;    
    double phase = 0;

    pa_error = Pa_Initialize();
    if (pa_error != paNoError)
    {
        return 1;
    }

    pa_error = Pa_OpenDefaultStream(
        &stream,
        0,
        1,
        paFloat32,
        SRATE,
        paFramesPerBufferUnspecified,
        &audio_callback,
        &phase);
    if (pa_error != paNoError)
    {
        error = 1;
        goto exit;
    }

    pa_error = Pa_StartStream(stream);
    if (pa_error != paNoError)
    {
        error = 1;
        goto exit;
    }

    Pa_Sleep(DURATION);

    pa_error = Pa_CloseStream(stream);
    if (pa_error != paNoError)
    {
        error = 1;
        goto exit;
    }

    printf("Done.\n");

exit:
    Pa_Terminate();

    if (pa_error != paNoError)
    {
        printf("PortAudio error: %s\n", Pa_GetErrorText(pa_error));
    }

    return error;
}

输出:

current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
current time = 0.000000; out time = 0.000000
...

附录:同一段代码似乎可以在 Windows 10 中的 Visual Studio 中正常运行。

最佳答案

您的示例在我的 Mac 上编译良好并返回有意义的时间信息,因此问题不在您的代码中。

您还没有说您在 Linux 上使用的是哪个音频后端,但是如果您使用的是 ALSAPulseAudio,那么在获取时间信息时就会出现问题与那些(例如参见there)。在 ALSA/PulseAudio 的这种特定情况下,Pulse 是罪魁祸首,PortAudio 与此无关。

如果您使用不同的音频后端,您可能需要检查 GetStreamTime() 的实现函数在相应的src/hostapi/<your_backend> PortAudio 源文件夹。


作为旁注,切勿在真实产品的音频回调中进行 I/O 操作。 printf是一个巨大的函数,需要花费大量时间来执行(从音频回调的角度来看)。

关于c - PaStreamCallbackTimeInfo成员全部为0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42542601/

相关文章:

c - 32位二进制到十进制的转换

c - 显示在输入的数字之前。 (C语言编程)

安卓 > 4.0 : Ideas how to record/capture internal audio (e. g。 STREAM_MUSIC)?

c - 使用 PCM 格式的 ALSA 进行音频录制

c++ - 静态编译过剩?

c - 无法在 C 中使用 getchar 中断 while 循环

c++ - 嵌入式串行读取操作和台式 PC 之间有什么区别

linux - shell sftp 下载远程文件

linux - dlsym 如何从剥离的二进制库中成功导入函数?

c - 在 Linux 中使用声卡。理解第一个例子(为什么不是 UB?)