![](/img/trans.png)
[英]Reading binary file into different hex “types” (8bit, 16bit, 32bit, …)
[英]C++ - Reading in 16bit .wav files
我正在嘗試讀取.wav文件,我認為它給了我正確的結果,但是,當我在Matlab或Python中繪制相同的音頻文件時,結果是不同的。
這是我得到的結果:
這是Python(用matplotlib繪制)給出的結果:
結果似乎沒有那么不同,但是,當涉及到分析時,這會弄亂我的結果。
以下是轉換的代碼:
for (int i = 0; i < size; i += 2)
{
int c = (data[i + 1] << 8) | data[i];
double t = c/32768.0;
//cout << t << endl;
rawSignal.push_back(t);
}
我哪里錯了? 因為,這種轉換似乎很好,並且確實產生了類似的結果。
謝謝
編輯:
用於讀取標頭/數據的代碼:
voidreadHeader(ifstream& file) {
s_riff_hdr riff_hdr;
s_chunk_hdr chunk_hdr;
long padded_size; // Size of extra bits
vector<uint8_t> fmt_data; // Vector to store the FMT data.
s_wavefmt *fmt = NULL;
file.read(reinterpret_cast<char*>(&riff_hdr), sizeof(riff_hdr));
if (!file) return false;
if (memcmp(riff_hdr.id, "RIFF", 4) != 0) return false;
//cout << "size=" << riff_hdr.size << endl;
//cout << "type=" << string(riff_hdr.type, 4) << endl;
if (memcmp(riff_hdr.type, "WAVE", 4) != 0) return false;
{
do
{
file.read(reinterpret_cast<char*>(&chunk_hdr), sizeof(chunk_hdr));
if (!file) return false;
padded_size = ((chunk_hdr.size + 1) & ~1);
if (memcmp(chunk_hdr.id, "fmt ", 4) == 0)
{
if (chunk_hdr.size < sizeof(s_wavefmt)) return false;
fmt_data.resize(padded_size);
file.read(reinterpret_cast<char*>(&fmt_data[0]), padded_size);
if (!file) return false;
fmt = reinterpret_cast<s_wavefmt*>(&fmt_data[0]);
sample_rate2 = fmt->sample_rate;
if (fmt->format_tag == 1) // PCM
{
if (chunk_hdr.size < sizeof(s_pcmwavefmt)) return false;
s_pcmwavefmt *pcm_fmt = reinterpret_cast<s_pcmwavefmt*>(fmt);
bits_per_sample = pcm_fmt->bits_per_sample;
}
else
{
if (chunk_hdr.size < sizeof(s_wavefmtex)) return false;
s_wavefmtex *fmt_ex = reinterpret_cast<s_wavefmtex*>(fmt);
if (fmt_ex->extra_size != 0)
{
if (chunk_hdr.size < (sizeof(s_wavefmtex) + fmt_ex->extra_size)) return false;
uint8_t *extra_data = reinterpret_cast<uint8_t*>(fmt_ex + 1);
// use extra_data, up to extra_size bytes, as needed...
}
}
//cout << "extra_size=" << fmt_ex->extra_size << endl;
}
else if (memcmp(chunk_hdr.id, "data", 4) == 0)
{
// process chunk data, according to fmt, as needed...
size = padded_size;
if(bits_per_sample == 16)
{
//size = padded_size / 2;
}
data = new unsigned char[size];
file.read(data, size);
file.ignore(padded_size);
if (!file) return false;
}
{
// process other chunks as needed...
file.ignore(padded_size);
if (!file) return false;
}
}while (!file.eof());
return true;
}
}
這就是“轉換為雙倍”的地方:
if(bits_per_sample == 8)
{
uint8_t c;
//cout << size;
for(unsigned i=0; (i < size); i++)
{
c = (unsigned)(unsigned char)(data[i]);
double t = (c-128)/128.0;
rawSignal.push_back(t);
}
}
else if(bits_per_sample == 16)
{
for (int i = 0; i < size; i += 2)
{
int c;
c = (unsigned) (unsigned char) (data[i + 2] << 8) | data[i];
double t = c/32768.0;
rawSignal.push_back(t);
}
請注意“8位”文件如何正常工作?
我懷疑你的問題可能是data
是一組有符號的 char
值。 所以,當你這樣做時:
int c = (data[i + 1] << 8) | data[i];
......實際上並沒有做你想做的事。 我們來看一些簡單的例子。
如果data[i+1] == 64
且data[i] == 64
,那將是0x4000 | 0x40,或0x4040,都很好。
如果data[i+1] == -64
和data[i] == -64
,那將是0xffffc000 | 0xffffffc0或0xffffffc0,這顯然是錯誤的。
如果您使用的是unsigned char
值,那么這將起作用,因為而不是-64這些數字將是192,並且最終會得到0xc000 | 0xc0或0xc0c0,就像你想要的那樣。 (但是你的/32768.0
會給你0.0到2.0范圍內的數字,當你想要-1.0到1.0時。)
如果不知道你究竟想要做什么,建議“修復”是很困難的。 顯然,您希望將某種16位小端整數格式轉換為某種浮點格式,但很多都依賴於這些格式的確切細節,並且您沒有提供任何此類細節。 默認的.wav格式是16位無符號小端整數,所以只使用unsigned char *
就可以解決方程式中的那部分問題。 但我不知道任何使用從0.0到2.0的64位浮點數的音頻格式,我不知道你實際上的目標是什么音頻格式,所以我不能說/32768.0
應該是什么實際上,只是它可能是錯的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.