我正在使用FFmpeg库解码和(可能)修改某些音频。

我设法使用以下功能遍历音频文件的所有帧:

avformat_open_input // Obtains formatContext
avformat_find_stream_info
av_find_best_stream // The argument AVMEDIA_TYPE_AUDIO is fed in to find the audio stream
avcodec_open2 // Obtains codecContext
av_init_packet

// The following is used to loop through the frames
av_read_frame
avcodec_decode_audio4

最后,我在每次迭代中都有这三个值
int dataSize; // return value of avcodec_decode_audio4
AVFrame* frame;
AVCodecContext* codecContext; // Codec context of the best stream

我以为这样的循环可以用来遍历所有样本:
for (int i = 0; i < frame->nb_samples; ++i)
{
    // Bytes/Sample is known to be 4
    // Extracts audio from Channel 1. There are in total 2 channels.
    int* sample = (int*)frame->data[0] + dataSize * i;
    // Now *sample is accessible
}

但是,当我使用gnuplot绘制数据时,我没有得到预期的波形,并且某些值达到了32位整数的限制:(音频流在最初的几秒钟内没有保持静音)c&#43;&#43; - 使用ffmpeg量化音频-LMLPHP

我想正在进行某种形式的量化,以防止对数据进行数学解释。我应该怎么做才能量化呢?

最佳答案



好吧……不。所以,首先,我们需要知道数据类型。检查frame->format。这是enum AVSampleFormat,最有可能是flt,fltp,s16或s16p。

那么,如何解释给定格式的frame->data[]?好吧,首先,它是否是平面的?如果它是平面的,则意味着每个通道都在frame-> data [n]中,其中n是通道号。 frame->channels是通道数。如果不是平面的,则意味着所有数据都在frame->data[0]中交织(每个样本)。

其次,什么是存储类型?如果是s16 / s16p,则为int16_t *。如果是flt / fltp,则为float *。因此,对fltp的正确解释是:

for (int c = 0; c < frame->channels; c++) {
    float *samples = frame->data[c];
    for (int i = 0; i < frame->nb_samples; i++) {
        float sample = samples[i];
        // now this sample is accessible, it's in the range [-1.0, 1.0]
    }
}

而对于s16,则为:
int16_t *samples = frame->data[0];
for (int c = 0; c < frame->channels; c++) {
    for (int i = 0; i < frame->nb_samples; i++) {
        int sample = samples[i * frame->channels + c];
        // now this sample is accessible, it's in the range [-32768,32767]
    }
}

09-12 11:03