一、問題
當神經網絡訓練或者音頻數據傳輸時需要把16位的音頻數據轉降低至8位,更加廣泛的說是把抽樣信號的幅度離散化,即量化。
二、方法
1.均勻量化
對編碼範圍內小信號或大信號都採用等量化級進行量化 ,因此小信號的“信號與量化噪聲比”小 ,而大信號的“信號與量化噪聲比”大 ,這對小信號來說是不利的。爲了提高小信號的信噪比 ,可以將量化級再細分些 ,這時大信號的信噪比也同樣提高 ,但這樣做的結果使數碼率也隨之提高 ,將要求用頻帶更寬的信道來傳輸。
對於16位的音頻數據降低至8位,直接將數據右移8位,即將數據除以2^8,這樣會使得聲音的噪音變大。
2.非均勻量化
對於均勻量化存在的問題則採樣非均勻量化解決。它的基本思想是對大信號進行壓縮而對小信號進行較大的放大。由於小信號的幅度得到較大的放大 ,從而使小信號的信噪比大爲改善。目前常用的壓擴方法是對數型的 A律壓縮和 μ律壓縮 ,其中 μ律壓縮公式:
y=ln(1+μx)/ln(1+μ)
其中 x 爲歸一化的量化器輸入 , y 爲歸一化的量化器輸出。常數 μ愈大 ,則小信號的壓擴效益愈高 ,目前多采用 μ= 255。
其中μ255 /15折線壓縮特性曲線如圖 1所示:
三、mu law 與反mu law的代碼實現
1.wav數據的原始波形圖
2.mu law代碼實現
def mu_law(x, mu=255):
x = numpy.clip(x, -1, 1)
x_mu = numpy.sign(x) * numpy.log(1 + mu*numpy.abs(x))/numpy.log(1 + mu)
return ((x_mu + 1)/2 * mu).astype('int16')
# mu law前先將數據歸一化,即幅值範圍下降
ret = [mu_law(x / 2 ** 15) for x in used_data]
ret = numpy.array(ret,dtype=numpy.float)
print(max(ret),min(ret))
plt.figure(figsize=(12, 8))
librosa.display.waveplot(ret, sr=16000)
plt.xlim(0, 1)
plt.tight_layout()
mu law後的結果顯示:
3.反 mu law代碼實現
def inv_mu_law(x, mu=255.0):
x = numpy.array(x).astype(numpy.float32)
y = 2. * (x - (mu+1.)/2.) / (mu+1.)
return numpy.sign(y) * (1./mu) * ((1. + mu)**numpy.abs(y) - 1.)
# 幅值恢復
new_ret = inv_mu_law(ret)*(2**15)
plt.figure(figsize=(12, 8))
librosa.display.waveplot(new_ret, sr=16000)
plt.xlim(0, 1)
plt.tight_layout()
反mu law後的結果顯示: