Portaudio回调函数示例

时间:2014-10-03 02:36:15

标签: 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*/

良好的回调函数的一个例子非常有用,但当然可以提供任何帮助,

由于

1 个答案:

答案 0 :(得分:0)

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

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

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

  • 流样本格式为paFloat,即使您可能只是在源短路时输出paInt16。 scale变量可以转换为paFloat [-1,1]
  • 的适当范围
  • 令人讨厌的强制转换,以保持data_struct-&gt;数据为char *,即使它很短也应该是短*。
  • 循环覆盖framesPerBuffer*2个样本(因为1帧是所有通道,我假设是立体声)。这并不能使代码非常清晰(请查看其他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;
    }
    
相关问题