2014-10-03 109 views
0

我目前正在使用live555,mpg123和portaudio构建一个mp3流式传输器/接收器,并开始流式传输,解码和播放mp3的概念。Portaudio回调函数示例

我的问题是当我需要播放声音与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; 
} 

回调函数接收包含在一个无符号的字符阵列和字节数的解码数据一个结构解码:

typedef struct 
{ 
    unsigned char* data; 
    unsigned long cursor; 
    unsigned long num_frames; 
} 
paTestData; 

该编解码器的功能如下:

mpg123_decode(m,fBuffer,frameSize,out,OUTBUFF,&size); 

所以它返回一个无符号字符(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*/ 

一个很好的回调函数的一个例子是非常有用的,但当然任何帮助表示赞赏,

谢谢

+0

你需要清楚走出你的编解码器的数据格式和通道数,而PortAudio配置为预期的数据格式和通道数。编解码器的输出是无符号字符吗?或者是其他东西?是立体声还是单声道? – 2014-10-03 07:41:02

+0

谢谢Ross,我添加了缺少的部分。感谢您的帮助! – louis 2014-10-03 12:01:51

+0

我在我的解释中加入了缺少的部分,当然不是我的程序;)。 – louis 2014-10-04 00:19:50

回答

0

我想你可以相当有信心,从mpg123_decode输出的实际音频数据格式不是无符号字符。它很可能是作为通用指针来声明的。你应该研究什么是实际类型。这可能是你可以配置的东西。

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

请注意,我已对代码进行了最小更改以使其正常工作。这不是一个很好的例子。我的代码存在问题:

  • 流示例格式是paFloat,即使您应该输出paInt16(如果源是短路)。 scale变量有转换为paFloat的适当范围[-1,1]
  • 令人讨厌的转换以保持您的data_struct->数据为char *,即使它应该可能是短的*,如果源是短路。
  • Loop covers framesPerBuffer*2 samples(因为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; 
    }