如何在 ΔΣ 调制器的噪声整形中实现滤波器极点?

信息处理 过滤器 delta-sigma
2022-02-23 10:47:18

我目前被困在尝试实现滤波器极点以稳定 ΔΣ 调制器。我想我知道的是:

  • 当阶数超过 2 时,沿单位圆仅具有复零的噪声整形滤波器会使 1 位 ΔΣ 调制器不稳定。
  • 滤波器极点可用于降低带外噪声,使调制器更稳定

为了测试这种方法,我试图实现一个具有 2 个零点和 2 个极点的简单二阶调制器。

最初,我在没有极点的情况下尝试了它,只有两个零才有效,我以以下方式实现它以进行测试(使用 python/numpy):

import numpy as np
roots = np.exp(1j*np.array([0.05, -0.05]))                  # two exemplary complex roots
b = np.poly(roots)                                          # and corresponding filter coeffs
errors = np.zeros_like(b)
signal = np.random.rand(100) - 0.5                          # any signal smaller than [-1,1]
samps = np.zeros_like(signal)
for iSAM in range(len(samps)):
    desired = signal[iSAM] + np.dot(b[1:],errors2[:-1])     # add the filtered errors to the input
    samps[iSAM] = np.sign(desired)                          # discretize to 1-bit
    errors = np.roll(errors, 1)
    errors[0] = samps[iSAM] - desired                       # calculate new error

正如预期的那样,在对结果进行 FFT 时,我看到了与所需滤波器类似的频率响应。正如预期的那样,在 exp(i*0)=1 处添加另一个根(创建一个三阶调制器)时,整个事情变得不稳定,即使对于小输入也是如此。

制作带有极点的滤波器并定义它​​们的频率响应没有问题。我还能够使用设计的双二阶滤波器(2 个零点,2 个极点)获取时域信号并对其进行滤波,并获得正确的结果。

问题是:如何在噪声整形算法中使用极点。我什至如何使用简单的双二阶滤波器进行噪声整形?我今天看了很多视频和论文,但还是不明白。每个人都从我观看的视频系列中画出这样的图表:https ://youtu.be/IE8tU_10Hpg?t=63

更详细的流程图见 Stanley Lipshitz 1991 年的论文。

但是,即使我从字面上遵循此流程图,我也没有得到任何结果。状态变量刚刚爆炸。视频系列中的那个人还实现了一个具有 3 个零点和 3 个极点的 3 阶滤波器,以定义一个稳定的 3 阶调制器。虽然我可以重现滤波器系数和噪声传递函数 (NTF),但我不明白如何实际使用滤波器。在一个视频中,他快速评论了在模拟中测试过滤器的性能。他说执行测试是“微不足道的”或类似的事情。所以很明显我在这里遗漏了一些非常基本的东西:)

更新: 经过几天的尝试,我真的很茫然。任何人都可以发布一个使用非常简单的 IIR 滤波器进行噪声整形的示例,即使只有 2 个零点和 2 个极点。成形噪声频谱应再现设计滤波器的幅度响应。我会尽可能多地给它一些赏金。因为互联网上的所有指南都没有帮助我。我不在乎您使用哪种编程语言,但整形频谱应该明显产生正确的幅度。

最好的祝福

1个回答

我相信经过更多研究后,我自己确实找到了答案;)

关键信息如下:H(z)许多模型中显示的滤波器函数并不是实际的噪声滤波器函数。通常噪声滤波器应该是某种高通,我H(z)错误地直接使用它。

相反,噪声是由噪声传递函数塑造的NTF(z) = 1-H(z)

因此,在设计了高通噪声传递滤波器之后NTF(z),需要通过 计算滤波器模型H(z) = 1-NTF(z)

事实证明,如果 NTF 是形式为 的“无极”滤波器(FIR 滤波器)NTF(z) = 1 + Sum(b_n z^-n),那么滤波器函数将非常相似:H(z) = 0 - Sum(b_n z^-n)其中 n 从 1 开始。第一个系数将为 0。我实际上直接实现了这个噪声整形过去,通过忽略前导系数 1 并在求和节点处将滤波器结果的符号与信号反转。我得出了这个结论,因为我在某个地方捡到了它,但不明白它的起源。

然而,当 NTF 包含极点时,H(z)偏差会更大。NTF(z)的分母H(z)实际上是相同的。但是分子将是X(z) = Sum(a_n z^-n) - Sum(b_n z^-n),其中a_n是极点系数,并且b_n是零系数。通常, 的前导系数NTF(z)都为 1(毕竟它是最小相位滤波器), 的前导系数H(z)将变为 0。这自然会产生丢失的第一个系数。

有了这个正确定义H(z),按照 Lipshitz 1991 论文中给出的流程图,给出了正确的结果。我使用 +/- 0.5 的量化器范围作为均匀的白色抖动。

更新: 纠正一些小错误后,一切正常。在 Python 中,我使用逆切比雪夫滤波器模型来制作噪声传递函数。然后我校正系数,将它们变成H(z)滤波器模型:

fDAC=20e6
b, a = signal.cheby2(5, 160, 20000, 'hp', fs=fDAC)
b /= b[0] # normalize according to Gerzon/Craven
b = a - b # turn NTF(z) into H(z) for noise shaping

然后是实际的噪声整形(在代码中留下了一些冗余,以使其更接近 Lipshitz 1991):

l = 200000
ts = np.arange(l)/fDAC
wav = 0.55 * np.sin(2*np.pi*3200*ts)
errbuf = np.zeros_like(b)
samps = np.zeros_like(wav)
for iSAM in range(l):
    desired = wav[iSAM] - np.dot(b, errbuf)
    samps[iSAM] = np.sign( desired )
    error = samps[iSAM] - desired 
    errbuf[0] = - error
    errbuf[0] = - np.dot(a, errbuf)
    errbuf = np.roll(errbuf, 1)

请注意,没有使用附加抖动。即使量化器噪声本身不是白色的,噪声整形也足够有效以消除量化器失真。无抖动 Delta Sigma 调制器确实有一些缺点,例如在固定输入上,这可以从许多来源中读取。如果你想要抖动,它应该在量化之前添加,即在sign()函数内部

5 阶 delta sigma 调制器的示例。 垂直刻度单位为满刻度。 水平是以赫兹为单位的频率。 橙色曲线是设计的 5 阶逆切比雪夫高通滤波器作为噪声传递函数。 蓝色是具有 ~-5dBFS 正弦波的结果。 图:5 阶 delta sigma 调制器示例。垂直刻度单位为满刻度。水平是以赫兹为单位的频率。橙色曲线是设计的 5 阶逆切比雪夫高通滤波器作为噪声传递函数。蓝色是具有 ~-5dBFS 正弦波的结果。

PS:由于我最初在这个问题上设置了赏金,这让我彻夜难眠:请随时纠正我并用你自己的更好答案来索取赏金。