检测到瞬态时自动调整其带宽的带通滤波器(以避免平滑瞬态)

信息处理 过滤器 过滤器设计 自适应滤波器 信封
2022-02-06 05:00:37

假设我们要隔离 1000 赫兹 +/- 50 赫兹的频带。

显然,通过应用通带滤波器来限制带宽总是会破坏一点尖锐的瞬态(Dirac 或矩形包络/Heavyside 阶跃函数需要所有频率,所以如果限制带宽,我们会损失一部分,它会变得更平滑)。

问题:是否有一些自适应带通滤波器会在检测到瞬态时在短时间内自动扩展其带宽,以免丢失尖锐的瞬态?

在此示例中(由矩形包络调制的 1000 hz 正弦波,蓝色输入):

在此处输入图像描述

滤波器当然仍会专注于 1000hz +/- 50hz 频段,但它会在瞬态附近扩展其带宽,这样瞬态就不会像普通滤波器那样平滑(红色信号)。

是否存在这样的自适应带通,并且在大多数语言(Matlab、Python 等)中是否可以轻松使用?

注意:在这张图上,除了 1000hz 正弦波之外没有其他任何东西,所以您可能想知道“为什么要进行带通滤波?”,但这只是一个示例,在一般情况下,它将是宽带信号。

2个回答

好吧,我想我明白你的意思了。您需要一个 BPF,,它会根据幅度谱中的能量分布自动扩展其带宽。如果您有纯 1k Hz 正弦音调(在频域中,对应于位于 k rad/s 的狄拉克增量),您只想通过 1k中的频率Hz 范围,并且如果您有一个具有类似白噪声分布的瞬态事件,您需要一个全通滤波器来保留尖锐的攻击。H(z)ω0=±2π1±50

您需要的是一个谐振器滤波器 [1]:

H(z)=(1λ)1+λ22λcos(2ω0)1(2λcos(ω0))z1+λ2z2,

值,它的行为如下所示: λ[0,1]在此处输入图像描述

因此对于,您将获得一个平坦的响应来捕捉瞬态事件,对于,您将在所需频率处获得一个局部滤波器。在这里,出于说明目的,我设置了更改所需的频率λ0λ1w0=π/2w0=2πF0/Fs

要自动设置,您可以使用频谱平坦度估计器 [2]:λ

f=(n=0N1x[n])1/N1Nn=0N1x[n],

这是f=1,当幅度谱完全平坦时,并且f=0,当幅度谱完全局部化时。因此,您可以使λ=1f. 我编写了以下代码来举例说明如何应用此控件:

Fs=16e3;
F0=1e3;
w0 = 2*pi*F0/Fs;
x1 = [zeros(1,50),2*rand(1,50)-1];
x2 = 0.7*sin(w0.*[1:100])+0.3*rand(1,100);
x3 = 0.7*sin(3.5*w0.*[1:100])+0.3*rand(1,100);
y = [adaptiveResonatorFilter(x1,w0), adaptiveResonatorFilter(x2,w0), adaptiveResonatorFilter(x3,w0)];
plot([x1,x2,x3],'linewidth',2)
hold on
plot(y,'linewidth',2)
xlabel('Samples')
ylabel('Amplitude')
legend('Original','Filtered')

function y = adaptiveResonatorFilter(x,w0)
    X = fft(x);
    mX = abs(X);
    mX = mX/max(mX);
    sf = mean(mX,'g')/mean(mX,'a')
    lambda = ifelse(0.5<1-sf, 0.99, 0.0)
    B = (1-lambda)*sqrt(1+lambda^2-2*lambda*cos(2*w0));
    A = [1,-2*lambda*cos(w0), lambda^2];
    [H,W] = freqz(B,A,linspace(-pi,pi,length(mX)));
    Y = X .* fftshift(H);
    y = real(ifft(Y));
end

给出以下输出:

在此处输入图像描述

您可以看到瞬态部分保持不变,被噪声污染的 1k Hz 纯音已被清除,并且 3.5k Hz 纯音已被衰减,如您所愿。

注意:将此作为“瞬态攻击”的定义。如果我误解了,请纠正我。


  1. M.维特利,P.普兰多尼。通信信号处理。EPFL 出版社。
  2. https://en.wikipedia.org/wiki/Spectral_flatness

附加资源:这是 JFonseca 用 Python 翻译的代码:

import numpy as np
import matplotlib.pyplot as plt
import scipy, scipy.stats, scipy.signal

def adaptiveResonatorFilter(x,w0):
    X = np.fft.fft(x)
    mX = abs(X)
    mX = mX / max(mX)
    sf = scipy.stats.gmean(mX) / np.mean(mX)
    l = 0.99 if 0.5<1-sf else 0.0
    B = [(1-l)*np.sqrt(1+l**2-2*l*np.cos(2*w0))]
    A = [1, -2*l*np.cos(w0), l**2]
    return scipy.signal.lfilter(B, A, x)

Fs = 16000
F0 = 1000.0
w0 = 2*np.pi*F0/Fs

x1 = np.concatenate((np.zeros(50), 2*np.random.rand(50)-1))
x2 = 0.7*np.sin(w0*np.arange(100))+0.3*np.random.rand(100)
x3 = 0.7*np.sin(3.5*w0*np.arange(100))+0.3*np.random.rand(100)
x = np.concatenate((x1, x2, x3))
y = np.concatenate((adaptiveResonatorFilter(x1,w0), adaptiveResonatorFilter(x2,w0), adaptiveResonatorFilter(x3,w0)))

#x = np.concatenate((np.zeros(int(0.01*Fs)), np.sin(w0*np.arange(int(0.01*Fs)))))
#y = adaptiveResonatorFilter(x, w0)

plt.plot(x)
plt.plot(y)
plt.show()

在此处输入图像描述