一、问题
当神经网络训练或者音频数据传输时需要把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()
注 意 : m u l a w 变 换 的 数 值 需 要 归 一 化 \color{#FF3030}{注意:mu law变换的数值需要归一化} 注意:mulaw变换的数值需要归一化
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后的结果显示:
Reference
百度百科
mu law和反 mu law的代码