c++ - Portaudio 回调函数示例

标签 c++ audio mp3 portaudio

我目前正在使用 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/

    相关文章:

    android - 共享对象、符号、C/C++ lib 链接和加载

    java - 确定何时关闭 Java 中的声音播放线程

    c# - 通过C#中的串行端口从电话到PC的音频流

    c++ - Gstreamer appsrc : odd behaviour of need-data callback

    c - 通过C中的套接字发送mp3文件

    java - jLayer——播放 mp3 导致文件开头失真

    c++ - 另一个线程是否可以通过其地址访问本地函数\此优化是否有效\我是否遗漏了一些重要的东西?

    c++ - stringstream 的第一个字符串参数被保存为指针/垃圾

    c++ - bool 函数之前预期的不合格 id?

    android - 如何从 mp3 中提取元数据?