[英]From audio PCM 16 bit to 8 bit - getting noise
我實現了以下算法,將PCM 16位音頻數據轉換為8位:
if(encoding == AudioFormat.ENCODING_PCM_8BIT){
int len = data.length;
data1 = new byte[len/2];
int tempint;
for (int k = 0, i=1; i < len; i+=2, k++) {
tempint = ((int)data[i]) ^ 0x00000080;
data1[k] = (byte)tempint;
}
data=null;
}
其中data is byte[]
。 運行這段代碼后,輸出中contains a lot of noise
並提示我在這里做錯了什么。 What should I do besides dropping the lower byte?
[編輯]:修改了代碼:
if(encoding == AudioFormat.ENCODING_PCM_8BIT){
int len = data.length;
data1 = new byte[len/2];
for (int i = 0; i < len/2; i++) {
data1[i] = data[i*2+1];
}
}
the input/output looks like:
Original data(counter:0) = 4
Original data(counter:1) = -1
Original data(counter:2) = 75
Original data(counter:3) = -1
Original data(counter:4) = 16
Original data(counter:5) = -1
Original data(counter:6) = 44
Original data(counter:7) = -1
Original data(counter:8) = 7
Original data(counter:9) = -1
Original data(counter:10) = 22
Original data(counter:11) = -1
Original data(counter:12) = 22
Original data(counter:13) = -1
Original data(counter:14) = 12
Original data(counter:15) = -1
Output data:(counter:0) = -1
Output data:(counter:1) = -1
Output data:(counter:2) = -1
Output data:(counter:3) = -1
Output data:(counter:4) = -1
Output data:(counter:5) = -1
Output data:(counter:6) = -1
Output data:(counter:7) = -1
Output data:(counter:8) = -1
Output data:(counter:9) = -1
Output data:(counter:10) = -1
Output data:(counter:11) = -1
Output data:(counter:12) = -1
Output data:(counter:13) = -1
Output data:(counter:14) = -1
Output data:(counter:15) = -1
我丟棄第一個字節還是第二個字節都沒有關系,噪聲仍然存在。 在這里,我刪除了第一個字節(而不是第二個)
以下算法已大大降低了噪聲量,但無法完全消除它:
if(encoding == AudioFormat.ENCODING_PCM_8BIT){
ShortBuffer intBuf = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] samples16Bit = new short[intBuf.remaining()];
intBuf.get(samples16Bit);
data1 = new byte[samples16Bit.length];
for (int i = 0; i < samples16Bit.length; i++) {
data1[i] = (byte)((samples16Bit[i] / 256)+128);
}
}
您所遇到的噪音僅僅是由您將音頻轉換到的位范圍引起的。 16Bit信號的本底噪聲為-96dB,而8Bit信號的本底噪聲為-48dB。 就這些數字而言,這看起來似乎並不多,但這是一個巨大的差異。 降采樣算法幾乎總是采用某種抖動來減少與轉換相關的噪聲量。 通過以編程方式或使用任何合適的音頻程序在8Bit中創建正弦波,您可以輕松地演示質量(和噪聲水平)的差異。 您會發現8Bit並不是真正的質量。 用16Bit正弦波重復實驗以進行比較。 不是您,而是位距。
為什么不只是這個呢?
int len = data.length;
data1 = new byte[len/2];
for (int i=0; i < len/2; ++i)
data1[i] = data[i*2];
我假設您的數據是Bigendian。 如果是LE,這應該可以工作:
int len = data.length;
data1 = new byte[len/2];
for (int i=0; i < len/2; ++i)
data1[i] = data[i*2+1];
由於多種原因,您會有很多雜音。 首先,您僅填充數組的每個其他值,未填充的值自動為零,這會極大地扭曲波形。 其次,您只選擇原始數據的前8位,這意味着如果數據點的前8位碰巧全部為零,則您將丟失所有數據,而該信息可能位於較高位。
天真的建議是縮放所有數據點(如果有符號,則除以2 ^ 7),以使最高數據點最多為8位,您仍然會丟失信息並引入失真,因為您被迫將數據保存為整數,並且整數除法將迫使除后相同(接近)范圍內的值相等,但這應少很多噪音:)
感謝下面的評論,如果僅從原始數據中獲取所有其他數據點,則會引入一種稱為Aliasing的失真。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.