{OpenAL (+ FFmpeg)} Как поставить буфер переменного размера в очередь из-за формата ogg?

(Во-первых, я могу пожалеть о своем плохом английском, потому что это не мой родной язык.)

Я использую FFmpeg для декодирования некоторого аудиофайла и воспроизведения его с помощью OpenAL «потоком» (то есть функцией «очередь» и «исключение из очереди» OpenAL).

Когда я использую свою программу для воспроизведения файла .ogg, я обнаруживаю, что в нем есть переменная nb_samples. (Из-за того, что ogg имеет переменную скорость передачи ??). Имеется 128, 512 и 1024 байта nb_samples. В результате я должен вызвать alDeleteBuffers и alGenBuffers, прежде чем использовать alBufferSamplesSOFT (аналогично alBufferData), потому что он не смог бы вызвать alBufferSamplesSOFT без воссоздания буфера. Примечания: alBufferSamplesSOFT предоставляется OpenAL Soft. Вы можете просто увидеть это как alBufferData.

Тем не менее, я считаю, что это будет глупо и неэффективно. Есть какой-нибудь умный метод? Я вставляю часть кода:

while (av_read_frame(...) == 0){
  avcodec_decode_audio4(...);
  swr_convert(...);  // to convert PCM format from FLTP to FLT
  alDeleteBuffers(1, theBuffers[?]);
  alGenBuffers(1, theBuffers[?]);
  alBufferSamplesSOFT(...);  // put those data into OpenAL buffer
}

если я этого не сделаю, он не сможет обновить буфер OpenAL. Есть ли способ создать буфер переменного размера или буфер большого размера? Или есть способ изменить размер буфера?

Спасибо за вас, ребята.


person user3293833    schedule 10.02.2014    source источник


Ответы (1)


Вы можете положиться на функциональность FIFO libavresample (поддерживаемую FFmpeg), например:

... decode the audio into srcaudio frame...
// Resample the input into the audioSampleBuffer until we proceed the whole decoded data
if ( (err = avresample_convert( audioResampleCtx,
                                NULL,
                                0,
                                0,
                                srcaudio.data,
                                0,
                                srcaudio.nb_samples )) < 0 )
{
    warning( "Error resampling decoded audio: %d", err );
    return -1;
}

while( avresample_available( audioResampleCtx ) >= audioFrame->nb_samples )
{
    // Read a frame audio data from the resample fifo
    if ( avresample_read( audioResampleCtx, audioFrame->data, audioFrame->nb_samples ) != audioFrame->nb_samples )
    {
        warning( "Error reading resampled audio: %d", err );
        return -1;
    }

Таким образом, вы всегда получите буфер фиксированного размера через avresample_read. Это также имеет преимущество, если вы конвертируете аудио таким образом, чтобы из исходного файла генерировалось больше сэмплов, чем nb_samples.

Часть кода взята из моего редактора текстов песен караоке; при необходимости вы можете проверить соответствующий исходный файл здесь Дополнительная информация.

person George Y.    schedule 11.02.2014