gpt4 book ai didi

c++ - Portaudio 回调函数示例

转载 作者:行者123 更新时间:2023-12-03 02:08:30 26 4
gpt4 key购买 nike

我目前正在使用 live555、mpg123 和 portaudio 构建一个 mp3 流媒体/接收器,并且刚刚开始流式传输、解码和播放 mp3 的概念。

我的问题是当我需要用 portaudio 播放声音时。我不知道如何编写一个回调函数来播放我解码的 mp3。

这是我在某处找到并尝试过的回调函数,但这并没有给我带来好的结果(只有噪音和嗡嗡声)。

static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data_struct = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused variable warning. */

for( i=0; i<framesPerBuffer; i++ )
{
if(data_struct->cursor < data_struct->num_frames)
{
out[i] = data_struct->data[data_struct->cursor];
data_struct->cursor++;
}
else
{
out[i] = 0; // if you've used up all the data, just fill the rest with silence.
//finished = paComplete;
}
}
return 0;
}

回调函数接收一个结构,该结构包含 unsigned char 数组中的解码数据和解码的字节数:
typedef struct
{
unsigned char* data;
unsigned long cursor;
unsigned long num_frames;
}
paTestData;

编解码器函数如下所示:
mpg123_decode(m,fBuffer,frameSize,out,OUTBUFF,&size);

因此它以 unsigned char (out) 形式返回数据,字节在 size 变量中解码。 fBuffer 是编码的数据,而 frameSize 是编码的字节数。

我已经以与 portaudio 教程中相同的方式配置了 portaudio 流:
err = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
2, /* stereo output */
paFloat32, /* 32 bit floating point output */
SAMPLE_RATE,
paFramesPerBufferUnspecified, /* frames per buffer, i.e. the number
of sample frames that PortAudio will
request from the callback. Many apps
may want to use
paFramesPerBufferUnspecified, which
tells PortAudio to pick the best,
possibly changing, buffer size.*/
patestCallback, /* this is your callback function */
&paData ); /*This is a pointer that will be passed to
your callback*/

一个好的回调函数的例子将非常有用,但当然感谢任何帮助,

谢谢

最佳答案

我认为您可以相当确信 mpg123_decode 输出的实际音频数据格式不是无符号字符。很可能它被声明为通用指针。您应该研究实际类型是什么。它可能是您可以配置的。

我的第一个猜测是 mpg123_decode 的输出是立体声 16 位整数(假设是立体声源)。如果是这种情况,以下代码可能会起作用。

请注意,我对您的代码进行了最小的更改以使其正常工作。这不是一个很好的例子来说明如何做到这一点。我的代码有问题:

  • 流样本格式是 paFloat,即使如果源是短裤,您可能应该只输出 paInt16。 scale变量是否可以转换为 paFloat [-1,1]
  • 的正确范围
  • 将你的 data_struct->data 保留为 char* 的讨厌的转换,即使它可能应该是一个 short* 如果源是短裤。
  • 循环盖framesPerBuffer*2样本(因为 1 帧是所有 channel ,我假设是立体声)。这不会使代码非常清晰(查看其他 PA 示例以了解通常如何处理立体声)。
    static int patestCallback( const void *inputBuffer, void *outputBuffer,
    unsigned long framesPerBuffer,
    const PaStreamCallbackTimeInfo* timeInfo,
    PaStreamCallbackFlags statusFlags,
    void *userData )
    {
    /* Cast data passed through stream to our structure. */
    paTestData *data_struct = (paTestData*)userData;
    float *out = (float*)outputBuffer;
    unsigned int i;
    (void) inputBuffer; /* Prevent unused variable warning. */
    static const float scale = 1./32768.;

    for( i=0; i<framesPerBuffer*2; i++ ) // source and dest are interleaved
    {
    if(data_struct->cursor < data_struct->num_frames)
    {
    out[i] = *((short*)(&data_struct->data[data_struct->cursor])) * scale;
    data_struct->cursor += sizeof(short);
    }
    else
    {
    out[i] = 0; // if you've used up all the data, just fill the rest with silence.
    //finished = paComplete;
    }
    }
    return 0;
    }
  • 关于c++ - Portaudio 回调函数示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26172522/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com