2010-10-26 98 views
0

我必須將數字音頻信號的位深度從24位降低到16位。通過截斷減少採樣位深

以僅16個最高位顯著每個樣本(即截斷)等效於做一個比例運算(OUT =在*爲0xFFFF/0XFFFFFF)?

回答

1

我假定你的意思(in * 0xFFFF)/0xFFFFFF,在這種情況下,是的。

+0

當然,遺憾的錯字... – Wizard79 2010-10-26 11:24:29

+0

當然,你可以簡單地位上下移動:'OUT =在>> 8'(未簽名樣本)。 – andrewmu 2010-10-26 11:27:07

+0

爲什麼只適用於未簽名的樣本? – Wizard79 2010-10-26 20:15:21

3

你會加入一個精心製作的噪聲信號與原始信號,略低於截斷門檻,截斷(又名抖動)之前獲得更好的探測結果。

+0

我知道,通過減少比特深度我引入量化噪聲(因此減少的24比特信號聽起來比16位大師最差),但我怎麼能「精心推敲」的抖動噪聲? – Wizard79 2010-10-26 11:45:49

+0

抖動的目標是分配舍入誤差,但是您希望最小化所引入的可聽工件的數量。白噪聲是一個很好的起點,但根據應用的不同,平衡噪聲的頻譜可能會帶來更好的結果。 – tdammers 2010-10-26 19:11:23

1

Dithering加入噪聲一般會給你更好的結果。關鍵是噪音的形狀。人口衆多的數字音頻工作站應用(Cakewalk的SONAR,Logic等)中,抖動算法具有特定的形狀,非常流行。

如果您不需要pow-r的保真度,您可以簡單地生成一些幅度相當低的noise,並將其混合到您的信號中。你會發現這掩蓋了一些量化效應。

0

x * 0xffff/0xffffff過於迂腐,但不是一個好辦法,如果你的樣品簽署 - 也許不是一般的好辦法。

是的,您希望源範圍內的最大值與目標範圍內的最大值相匹配,但這裏使用的值僅適用於無符號範圍,並且量化步驟的分佈意味着它將非常罕見您使用最大可能的輸出值。

樣本是否有簽名,則峯正值是0x7FFF的和0x7fffff,而峯值負值將-0x8000和-0x800000。你的第一個問題是決定+1是否等於0x7fff,或-1等於-0x8000。如果您選擇後者,那麼這是一個簡單的輪班操作。如果你試圖讓零點停止爲零。

之後,你有一個問題,劃分趨向零。這意味着與其他值相比,太多值會舍入到零。這會導致失真。

如果你想根據峯值正值向規模化,正確的形式是:

out = rint((float)in * 0x7fff/0x7fffff); 

如果你逛了一下魚,你也許可以找到一種有效的方式來做到這一點與整數運算和無師。

該表格應該正確地舍入到任何給定輸入的最接近的可用輸出值,並且它應該將最大可能的輸入值映射到最大可能的輸出值,但是它將具有遍佈整個區域的分散的量化步驟的醜陋分佈範圍。

大多數人都喜歡:

out = (in + 128) >> 8; 
if (out > 0x7fff) out = 0x7fff; 

這種形式使事情哪怕一丁點響亮,到如此地步,正值可能略有夾,但量化步幅均勻分佈。

您添加128是因爲右移向負無窮回合。該平均量化誤差爲-128和你加128來糾正這種在精確的0保持0溢出測試是必要的,因爲0x7fffff的輸入值,否則給出爲0x8000的結果,當你保存這個在它將圍繞16位字提供峯值負值。

Ç學究可以戳約右移和分裂行爲的假設洞,但我俯瞰那些清晰。

然而,正如其他人所指出的那樣,你一般不應降低音頻的比特深度不抖動,理想的噪聲整形。 TPDF抖動如下:

out = (in + (rand() & 255) - (rand() & 255)) >> 8; 
if (out < -0x8000) out = -0x8000; 
if (out > 0x7fff) out = 0x7fff; 

此外,隨着rand()這我要忽視爲清晰起見,使用大的問題。