{OpenAL(+ FFmpeg)}如何根据ogg格式对可变大小缓冲区进行排队?

时间:2014-02-10 17:22:34

标签: ffmpeg openal

(首先,我可能会因为英语不好而感到抱歉,因为这不是我的母语。)

我使用FFmpeg解码某些音频文件并通过“流”(即“队列”和“OpenAL的”队列“功能)与OpenAL一起播放。

当我使用我的程序播放.ogg文件时,我发现它有一个变量nb_samples。(由于ogg有可变的比特率??)有128 B,512 B和1024 B的nb_samples。结果,我必须在使用alBufferSamplesSOFT(类似于alBufferData)之前调用alDeleteBuffers和alGenBuffers,因为它无法在不重新创建缓冲区的情况下调用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缓冲区。是否有任何方法可以创建可变大小的缓冲区或大型缓冲区?或者有什么方法可以改变缓冲区的大小吗?

谢谢你们。

1 个答案:

答案 0 :(得分:0)

您可以依赖libavresample的FIFO功能(由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更多的方式从源文件中生成样本来转换音频,那么它也会带来好处。

代码片段来自我的卡拉OK歌词编辑器;如果您需要更多信息,可以查看相应的源文件here