【发布时间】:2015-10-18 00:07:48
【问题描述】:
我目前正在尝试收集解码的音频数据(来自多种格式)以执行某些音频操作(使用 *.wav 文件进行测试)。
我有一个通过 FFmpeg libav 处理所有解码的类。如果我将数据作为 unit8_t 提取到向量中,并且
for (int i = 0; i < bytevector.size(); i++) {
fwrite(&bytevector[i], sizeof (uint8_t), 1, outfile2);
}
到一个原始文件并通过它播放
play -t raw -r 44100 -b16 -c 1 -e signed sound.raw 听起来很好。
但是,当文件是每个样本 2 个字节并且frame->data 信息以 uint8_t 形式给出时,如何将所有 正确信息 加倍?我测试过的 wav 文件是 44100/16bits/1 通道。 (我已经有将 uint8_t* 更改为双精度的代码)
使用 Scilab 打开相同的文件将显示一半大小的字节向量作为双精度数。
Scilab 中的 wav 文件作为双精度数组显示:
-0.1, -0.099, -0.098, ..., 0.099, +0.1与字节向量:
51, 243, 84, 243, 117, 243, ...
51和243真的可以组成一个double吗?有关如何解决此问题的任何建议?
以下代码供参考:
while ((av_read_frame(formatContext, &readingPacket)) == 0) {
if (readingPacket.stream_index == audioStreamIdx) {
AVPacket decodingPacket = readingPacket;
while (decodingPacket.size > 0) {
int gotFrame = 0;
int result = avcodec_decode_audio4(context, frame, &gotFrame, &decodingPacket);
if (result < 0) {
break;
}
decoded = FFMIN(result, decodingPacket.size);
if (gotFrame) {
data_size = (av_get_bytes_per_sample(context->sample_fmt));
if (data_size < 0) {
}
// Only for 1 channel temporarily
for (int i = 0; i < frame->nb_samples; i++) {
for (int ch = 0; ch < context->channels; ch++) {
for (int j = 0; j < data_size; j++) {
bytevector.push_back(*(frame->data[ch] + data_size * i + j));
}
}
}
} else {
decodingPacket.size = 0;
decodingPacket.data = NULL;
}
decodingPacket.size -= result;
decodingPacket.data += result;
}
}
av_free_packet(&readingPacket);
}
【问题讨论】:
-
double?这可能是 52 位精度、11 位动态范围或 6000 dB。那太疯狂了。而命令行中的-b16表示 16 位,不是 8 位。 -
Double 对于对音频所做的事情来说绝对是矫枉过正。当在查看器中打开数组时,Scilab 将值显示为“双精度值”,这让我感到震惊。但是,是的,下面是关于如何以与 Scilab 相同的方式(范围从 -1.0 到 +1.0)表示两个 uint8_t(或 2 个字节)的数据的答案。谢谢。
-
@MSalters - 大多数体面的 DAW 应用程序使用 64 位内部处理,这样即使您仍然输出 24 位母版,您也会损失更少的精度。
-
@ddriver:那可能是 64 位 PCM。动态范围为 190 dB,而不是 6000。相比之下,广岛约为 250 dB。一颗正在形成超新星的恒星不超过 1000 分贝。
标签: c++ audio ffmpeg decode libav