从libav收集解码的音频作为双精度

时间:2015-07-27 17:17:09

标签: c++ audio ffmpeg decode libav

我目前正在尝试收集解码后的音频数据(来自多种格式)以执行某些音频操作(使用* .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 *改为double的代码)

使用Scilab打开相同的文件将显示字节向量的一半大小为双倍。

  

Scilab中的wav文件作为双打数组显示:   
-0.1,-0.099,-0.098,...,0.099,+ 0.1

     

与字节向量:
  51,243,84,243,117,243,......

51和243能否真正形成双重?关于如何解决这个问题的任何建议?

以下代码供参考:

 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);
    }

2 个答案:

答案 0 :(得分:0)

快速将两个字节转换为 float

byte bits[] = {195,255}; //first sample in the test s16 wav file
int16_t sample;
memcpy(&sample,&bits,sizeof(bits));
std::cout<<sample*(1.0f/32768.0f)<<std::endl;

此代码在打印时产生-0.001861572265625(具有更高精度的setprecision(xx);),这是Scilab使用相同文件给出的第一个数字。

我希望这有助于任何有类似问题的人。

答案 1 :(得分:0)

音频数据以多种不同格式存储。你得到一个uint8_t[]数组意味着很少。每个阵列不是一个字节。相反,您需要知道格式。这里-b16告诉我uint8_t[]数据实际上是16位PCM编码数据,即从-32768到+32767的等级。 Scilab似乎更喜欢浮点刻度,因此除以32768.0。这只是一种表征变化;它只是将比例缩小到-1.0,+ 1.0。

将它与角度进行比较:在pi / 2弧度上直角为90度;确切的数字并不重要,但两者都是整圆的1/4。