2011-01-06 50 views
3

我有一個問題。 在Java中,我需要從wav文件中讀取樣本。 文件格式爲:wav,PCM_SIGNED,2bytes = 16bits的有符號整數,小端... 對象讀取BYTES中的音頻採樣,我需要將這兩個字節轉換爲一個double值。 我試圖用這個公式,但它並不完全正確:以雙倍格式轉換signed int(2bytes,16位)。用Java

mono = (double)((audioBytes[k] & 0xFF) | (audioBytes[k + 1] << 8)); 

用Matlab的結果進行比較,我總是注意到Matlab和實際值的轉換一個用Java之間的差異。 有人可以幫我嗎? 謝謝, 戴夫

+2

您是否有一個短字節序列的示例,您期望的輸出是什麼,以及您的實際輸出是什麼? – 2011-01-06 15:22:37

+0

如果audioBytes [k]是一個字節,audioBytes [k]&0xFF == audioBytes [k],那麼mask就沒用了。 – 2011-01-06 15:34:26

+0

如果audioBytes [k] == -1,audioBytes [k]&0xFF == 255(在將結果傳遞給System.out.println之後)。 – 2011-01-06 15:50:36

回答

2

你還沒有給我們足夠的信息來知道你爲什麼在Matlab中得到不同的結果和Java的。通常,您會將短通道數據[-32768..32767]縮放到[-1..1]範圍內的雙精度值,這看起來像是您正在嘗試執行的操作。您的java結果:-3.0517578125E-5對於短值-1:-1/32768是正確的。我不知道你的Matlab結果爲什麼不同。你沒有告訴我們你是如何得到你的Matlab結果的。

如果你有大量的字節序列(我猜你是這麼做的),而且你不想擔心BIG-ENDIAN和LITTLE-ENDIAN或者移位和字節,那麼讓java來處理它爲您提供:

import java.nio.*; 
... 
ByteBuffer buf = ByteBuffer.wrap(audioBytes); 
buf.order(ByteOrder.LITTLE_ENDIAN); 

while (buf.remaining() >= 2) { 
    short s = buf.getShort(); 
    double mono = (double) s; 
    double mono_norm = mono/32768.0; 
    ... 
} 

ByteBuffer.getShort()讀取緩衝區的下兩個字節,照顧小尾數排序,字節轉換爲短,將自身定位爲下一個的getXXX()調用。

-1

不能只是做most_significant字節* 256 + least_significant_byte,然後強制轉換爲雙?

0

這是正確的做法:

double sampleValue = (double)((bytes[0]<<8) | (bytes[1]&0x00FF)); 

(變化指數掉小/大)