PaStreamCallbackTimeInfo成员都是0

时间:2017-03-01 21:40:26

标签: c linux alsa portaudio

来自PortAudio docs

  

流时间信息

     

使用回调I / O方法时,您的流回调函数   通过指向a的指针接收定时信息   PaStreamCallbackTimeInfo结构。这个结构包含了   当前时间以及估计的硬件捕获和回放   输入和输出缓冲区的第一个样本的时间。一直   相对于特定于流的时钟以秒为单位进行测量。该   可以使用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一起使用。

1 个答案:

答案 0 :(得分:0)

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

你还没有说过你在Linux上使用的音频后端,但如果你使用的是 ALSA PulseAudio ,那么获取时间信息就会出现问题与那些(例如,见there)。在 ALSA / PulseAudio 的特定情况下, Pulse 是责备而 PortAudio 与此无关。

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

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