为什么此代码会在波形序列中引入嘶嘶声/噪声

Why does this code introduce hiss/noise into wave sequence

提问人:GDN9 提问时间:11/8/2023 最后编辑:GDN9 更新时间:11/9/2023 访问量:59

问:

我正在尝试从不同的文件中提取 PCM 波形序列(不是音频文件但包含音频数据和其他数据的文件都在一个文件中),虽然此代码确实提取了预期的音频,但它似乎在序列中引入了非常可听的嘶嘶声/噪音。

我试图找到类似的主题,但我遇到的唯一问题是“混叠”或“抖动”?我已经用一堆不同的文件和格式尝试了这段代码,它似乎在所有内容中都添加了相同的嘶嘶声,所以嘶嘶声绝对不包含在我试图从中提取数据的原始文件中。

我知道原始文件包含 MONO 16 位 48Khz PCM 数据。

int main()
{
const int               lenght  = 180; //file length, just a "long enough" number to make sure there's enough space for the whole sequence from the original file

const unsigned short    bits    = 16;
const unsigned int      bitrate = 48000;
const unsigned short    channels= 1;

std::ifstream file("samplesfile.img", std::ios::binary); //the original file that contains all sorts of data, plus a simple wave sequence

// Offset 1byte to align with the wave sequence bytes
unsigned int offsetAmount = 1;

if (offsetAmount > 0)
{
    unsigned char tmp[bits];
    file.read(reinterpret_cast<char*>(tmp), sizeof(unsigned char) * offsetAmount);
}


// Read everything from file after the offset and interpret it as a wave sequence
unsigned char* samples = new unsigned char[bitrate * lenght];
file.read(reinterpret_cast<char*>(samples), sizeof(unsigned char) * bitrate * lenght);
file.close();


// creating a .wav file, calculating chunk data

unsigned short  PCM         = 1;
unsigned int    chunk1size  = 16;
unsigned int    chunk2size  = lenght * bitrate;
unsigned int    chunkSize   = chunk2size + 40;
unsigned int    byteRate    = (bitrate * channels * bits) / 8;
unsigned short  blockAlign  = (bits * channels) / 8;    



std::ofstream file2("res.wav", std::ios::binary);

if (file2.good())
{
    file2.flush();
    file2.write("RIFF", sizeof(char) * 4);
    file2.write(reinterpret_cast<const char*>(&chunkSize), sizeof(unsigned int));
    file2.write("WAVE", sizeof(char) * 4);

    file2.write("fmt ", sizeof(char) * 4);
    file2.write(reinterpret_cast<const char*>(&chunk1size), sizeof(unsigned int));
    file2.write(reinterpret_cast<const char*>(&PCM),        sizeof(unsigned short));
    file2.write(reinterpret_cast<const char*>(&channels),   sizeof(unsigned short));
    file2.write(reinterpret_cast<const char*>(&bitrate),    sizeof(unsigned int));
    file2.write(reinterpret_cast<const char*>(&byteRate),   sizeof(unsigned int));
    file2.write(reinterpret_cast<const char*>(&blockAlign), sizeof(unsigned short));
    file2.write(reinterpret_cast<const char*>(&bits),       sizeof(unsigned short));

    file2.write("data", sizeof(char) * 4);
    file2.write(reinterpret_cast<const char*>(&chunk2size), sizeof(unsigned int)); // 40 bytes up to here
    file2.write(reinterpret_cast<const char*>(samples),     chunk2size);
}

file2.close();

delete[] samples;

return 0;
}

结果:

enter image description here

C++ 音频 WAV 文件转换

评论

2赞 Jeremy Friesner 11/8/2023
您可以将原始音频文件和程序输出的文件一起加载到 Audacity 中,以便比较两个波形显示。如果您的代码正确,它们应该是相同的,但假设不正确,则两个波形之间的视觉差异可能会提供信息。
0赞 GDN9 11/8/2023
我已经澄清了我的问题,我试图从不是音频文件但确实包含隐藏在其中的一些音频的文件中提取音频
1赞 Jeremy Friesner 11/8/2023
我的怀疑是原始文件的音频数据并不完全是您认为的格式;例如,它们可能在每个音频数据样本(交错)之后包含一个样本的元数据,而您的程序将该元数据解释为额外的音频样本,这听起来像是失真。Audacity的波形图(最好是正弦波或类似波)可以清楚地表明这种情况是否发生。(或者他们可能正在做一些非常偷偷摸摸的事情,比如将其他数据编码到音频样本的低位中,然后在播放时将其屏蔽)
1赞 GDN9 11/8/2023
我也开始这么想了,我只是尝试使用相同的代码来提取具有所有正确设置的常规波形文件的音频,并且没有额外的噪音,所以我假设这不是代码出错,这是我对原始文件中内容的预测 - 这可能是你在说的, 我明天会试着修补它,然后报告:)到目前为止谢谢你!
1赞 fdcpp 11/8/2023
@JeremyFriesner的想法是正确的,但我可能会更进一步,尝试简单地编写然后提取 3 或 4 个已知的音频样本值,例如 16 位 PCM 的等效值(-2^15、0、+2^14)。然后,您应该能够编写一些测试,这些测试将有助于确定输入的数据是否相同,以及是否以任何方式填充。-10+0.5

答: 暂无答案