python - 具有时变截止频率的低通滤波器,使用 Python

标签 python numpy scipy signal-processing

如何应用截止频率线性变化(或比线性更一般的曲线)的低通滤波器,例如10000hz 到 200hz 随时间,使用 numpy/scipy 并且可能没有其他库?

例子:

  • 在 00:00,000,低通截止频率 = 10000hz
  • 在 00:05,000,低通截止频率 = 5000hz
  • 在 00:09,000,低通截止 = 1000hz
  • 然后截止频率在 10 秒内保持在 1000hz,然后截止频率降低到 200hz

这里是如何做一个简单的 100hz 低通:

from scipy.io import wavfile
import numpy as np
from scipy.signal import butter, lfilter

sr, x = wavfile.read('test.wav')
b, a = butter(2, 100.0 / sr, btype='low')  # Butterworth
y = lfilter(b, a, x)
wavfile.write('out.wav', sr, np.asarray(y, dtype=np.int16))

但是如何使截止值变化呢?

注意:我已经阅读了Applying time-variant filter in Python但答案相当复杂(并且它适用于一般的多种过滤器)。

最佳答案

一种相对简单的方法是保持滤波器固定不变,而是调制信号时间。例如,如果信号时间运行速度快 10 倍,则 10KHz 低通将像标准时间内的 1KHz 低通一样工作。

为此,我们需要求解一个简单的 ODE

dy       1
--  =  ----
dt     f(y)

此处 t 是实时调制时间 yfy 时所需的截止时间。

原型(prototype)实现:

from __future__ import division
import numpy as np
from scipy import integrate, interpolate
from scipy.signal import butter, lfilter, spectrogram

slack_l, slack = 0.1, 1
cutoff = 50
L = 25

from scipy.io import wavfile
sr, x = wavfile.read('capriccio.wav')
x = x[:(L + slack) * sr, 0]
x = x

# sr = 44100
# x = np.random.normal(size=((L + slack) * sr,))

b, a = butter(2, 2 * cutoff / sr, btype='low')  # Butterworth

# cutoff function
def f(t):
    return (10000 - 1000 * np.clip(t, 0, 9) - 1000 * np.clip(t-19, 0, 0.8)) \
        / cutoff

# and its reciprocal
def fr(_, t):
    return cutoff / (10000 - 1000 * t.clip(0, 9) - 1000 * (t-19).clip(0, 0.8))

# modulate time
# calculate upper end of td first
tdmax = integrate.quad(f, 0, L + slack_l, points=[9, 19, 19.8])[0]
span = (0, tdmax)
t = np.arange(x.size) / sr
tdinfo = integrate.solve_ivp(fr, span, np.zeros((1,)),
                             t_eval=np.arange(0, span[-1], 1 / sr),
                             vectorized=True)
td = tdinfo.y.ravel()
# modulate signal
xd = interpolate.interp1d(t, x)(td)
# and linearly filter
yd = lfilter(b, a, xd)
# modulate signal back to linear time
y = interpolate.interp1d(td, yd)(t[:-sr*slack])

# check
import pylab
xa, ya, z = spectrogram(y, sr)
pylab.pcolor(ya, xa, z, vmax=2**8, cmap='nipy_spectral')
pylab.savefig('tst.png')

wavfile.write('capriccio_vandalized.wav', sr, y.astype(np.int16))

示例输出:

Spectrogram of first 25 seconds of BWV 826 Capriccio filtered with a time varying lowpass implemented via time bending.

BWV 826 Capriccio 前 25 秒的频谱图,使用通过时间弯曲实现的时变低通滤波。

关于python - 具有时变截止频率的低通滤波器,使用 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52403589/

相关文章:

python - 为什么这段 Python 代码会出现名称错误?

python - LogisticRegression scikit 学习协变量(列)顺序对训练很重要

python - PyTorch张量高级索引

python - NumPy 数组中滑动窗口中的最大值

python - 使用 NumExpr : An analysis 提高 NumPy 代码的运行时间

Python多维稀疏数组

python - 在 Python 中使用事件监控系统

python - 使用 Python 解密 Windows 无线密码

python - fftpack 中缺少 scipy 函数

python - 使用线性插值调整 numpy ndarray 的大小