2014-10-03 3 views
0

В настоящее время я создаю mp3-стример/приемник с использованием live555, mpg123 и portaudio и только начинаю концепцию потоковой передачи, декодирования и воспроизведения mp3.Portaudio Callback Function Example

Моя проблема в том, когда мне нужно воспроизвести звук с помощью 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); 

Таким образом, он возвращает данные в unsigned char (out), причем байты декодируются в переменной размера. 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*/ 

Пример хорошей функции обратного вызова будет очень полезно, но, конечно, любая помощь приветствуется,

Thanks

+0

Вы должны иметь четкое представление о формате и количестве каналов данных, поступающих из вашего кодека, а также формат и количестве каналов данных, которые Portaudio был настроен ожидать. Является ли вывод символов без знака кодека? или что-то другое? это стерео или моно? –

+0

Спасибо, Росс, я добавил недостающие части. Спасибо за помощь! – louis

+0

Я добавил недостающие части в своем объяснении, конечно, не в мою программу;). – louis

ответ

0

Я думаю, вы можете быть достаточно уверены, что фактический формат аудиоданных вывода от mpg123_decode не является символом без знака. Скорее всего, он объявлен таким образом как общий указатель. Вы должны исследовать, что такое фактический тип. Это может быть то, что вы можете настроить.

Мое первое предположение состояло в том, что выход mpg123_decode представляет собой стерео 16-битные int (при условии стереофонического источника). В этом случае может работать следующий код.

Обратите внимание, что я внес минимальные изменения в код, чтобы заставить его работать. Это не хороший пример того, как это сделать. Проблемы с моим кодом:

  • Формат образца потока является paFloat, хотя вы, вероятно, должны просто вывести paInt16, если источником являются шорты. Переменная scale есть, чтобы преобразовать в правильный диапазон для paFloat [-1,1]
  • Неприятное литье, чтобы сохранить данные data_struct-> как 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; 
    } 
    

 Смежные вопросы

  • Нет связанных вопросов^_^