使用 ffmpeg 对音频进行反量化
De-quantising audio with ffmpeg
我正在使用 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位整数的限制:(音频流在前几秒)
我想正在进行某种形式的量化以防止数据被数学解释。我应该怎么做才能对其进行反量化?
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->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]
}
}
我正在使用 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位整数的限制:(音频流在前几秒)
我想正在进行某种形式的量化以防止数据被数学解释。我应该怎么做才能对其进行反量化?
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->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]
}
}