2014-10-03 51 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; 
    }