[英]C++ reading 16bit Wav file
我在讀取16位.wav文件時遇到問題。 我已閱讀標題信息,但轉換似乎不起作用。
例如,如果在Matlab中讀取波形文件,則會得到以下類型的數據:
-0.0064, -0.0047, -0.0051, -0.0036, -0.0046, -0.0059, -0.0051
但是,在我的C ++程序中,返回以下內容:
0.960938, -0.00390625, -0.949219, -0.00390625, -0.996094, -0.00390625
我需要以相同的方式表示數據。 現在,對於8 bit
.wav文件,我執行了以下操作:
uint8_t c;
for(unsigned i=0; (i < size); i++)
{
c = (unsigned)(unsigned char)(data[i]);
double t = (c-128)/128.0;
rawSignal.push_back(t);
}
但是,當我為16bit執行此操作時,這很有用:
uint16_t c;
for(unsigned i=0; (i < size); i++)
{
c = (signed)(signed char)(data[i]);
double t = (c-256)/256.0;
rawSignal.push_back(t);
}
不起作用,並顯示輸出(上方)。
我遵循這里找到的標准
我的data
是char
數組,而rawSignal
是std::vector<double>
我可能只是在處理轉換錯誤,但似乎找不到位置。 有人有什么建議嗎?
謝謝
編輯:
這是現在顯示的內容(在圖中):
這是它應該顯示的內容:
這里有一些問題:
假設是一個低端架構,您的代碼將看起來像這樣(非常接近卡爾的答案):
for (int i = 0; i < size; i += 2)
{
int c = (data[i + 1] << 8) | data[i];
double t = c/32768.0;
rawSignal.push_back(t);
}
對於大端架構:
for (int i = 0; i < size; i += 2)
{
int c = (data[i] << 8) | data[i+1];
double t = c/32768.0;
rawSignal.push_back(t);
}
該代碼未經測試,請LMK如果不起作用。
(首先關於little-endian / big-endian-ness。WAV只是一種容器格式,其中編碼的數據可以是無數格式。大多數編解碼器都是無損的(MPEG Layer-3又稱MP3,是的,流可以“打包”成WAV,各種CCITT和其他編解碼器。。你假設你處理某種PCM格式,你看到RAW格式的實際波形,沒有進行無損轉換。字節順序取決於在編解碼器上生成流。 是否在RIFF WAV文件中保證格式參數的字節順序? )
這也是一個問題,如果一個PCM樣本是線性比例采樣整數或者它背后有一些縮放,對數比例或其他轉換。 我遇到的常規PCM wav文件是簡單的線性比例樣本,但是我不在音頻錄制或制作行業工作。
所以你的解決方案的路徑:
確保您正確解釋和處理循環迭代器變量和大小。 看起來大小告訴您有多少字節。 你只有一半的短整數樣本。 注意,正因為如此,Bjorn的解將i正確地增加了2。
16位的數量范圍為-32,768至32,767,而不是-256至255(僅為9位)。 采用:
for (int i = 0; i < size; i += 2)
{
c = (data[i + 1] << 8) + data[i]; // WAV files are little-endian
double t = (c - 32768)/32768.0;
rawSignal.push_back(t);
}
你可能想要更像這樣的東西:
uint16_t c;
for(unsigned i=0; (i < size); i++)
{
// get a 16 bit pointer to the array
uint16_t* p = (uint16_t*)data;
// get the i-th element
c = *( p + i );
// convert to signed? I'm guessing this is what you want
int16_t cs = (int16_t)c;
double t = (cs-256)/256.0;
rawSignal.push_back(t);
}
您的代碼將8位值轉換為有符號值,然后將其寫入無符號變量。 你應該看一下,看看它是不是你想要的。
我的工作代碼是
int8_t* buffer = new int8_t[size];
/*
HERE buffer IS FILLED
*/
for (int i = 0; i < size; i += 2)
{
int16_t c = ((unsigned char)buffer[i + 1] << 8) | (unsigned char)buffer[i];
double t = c/32768.0;
rawSignal.push_back(t);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.