【问题标题】:De-quantising audio with ffmpeg使用 ffmpeg 去量化音频
【发布时间】:2016-09-06 04:51:26
【问题描述】:

我正在使用 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 位整数的限制:(音频流在前几秒内没有静音)

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

【问题讨论】:

  • 在 44.1kHz 的典型采样率下,18,000 个样本大约需要 4.3 秒,因此您当然看不到典型波形。尝试放大,看看它是否与您预期的不同。
  • @Linuxios 我放大到大约100ms(4410 个样本),图表确实显示了一些周期性,但幅度并不反映音频的音量,因为它经常达到 +/- 2147483647
  • 这不一定是真的。有些东西可以覆盖 24 位音频的全部范围,并且仍然可以安静地播放。如果您以 Audacity 之类的方式打开原始文件,如果您查看波形的同一部分,您会看到什么?
  • @Linuxios 第一个80ms 沉默,[80,100]ms 范围有一点波动。
  • 好的。这很奇怪:)。别管我……

标签: c++ audio ffmpeg signal-processing libavcodec


【解决方案1】:
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
}

嗯...不。所以,首先,我们需要知道数据类型。检查frame-&gt;format。这是一个enum AVSampleFormat,很可能是 flt、fltp、s16 或 s16p。

那么,在给定格式的情况下,您如何解释frame-&gt;data[]?嗯,首先,它是平面的还是不是平面的?如果它是平面的,则意味着每个通道都在 frame->data[n] 中,其中 n 是通道号。 frame-&gt;channels 是通道数。如果它不是平面的,则意味着所有数据都在frame-&gt;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]
    }
}

【讨论】:

  • 边缘值对应的幅度是多少? (+/-1.0 用于浮点,-32768,32767 用于整数)
  • 边缘值是信号的尺度,信号的幅度(相对于尺度)是音频信号的响度(音量)。
  • 读取FLTP时遇到NaN和越界值正常吗?
  • NaN:不,不应该发生。 OOB:是的,这可能发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2011-06-27
  • 2019-09-01
相关资源
最近更新 更多