Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带Python的时变截止频率低通滤波器_Python_Numpy_Scipy_Signal Processing - Fatal编程技术网

带Python的时变截止频率低通滤波器

带Python的时变截止频率低通滤波器,python,numpy,scipy,signal-processing,Python,Numpy,Scipy,Signal Processing,如何应用低通滤波器,截止频率沿时间从10000hz到200hz呈线性变化(或具有比线性更一般的曲线),使用numpy/scipy,可能没有其他库 例如: 00:00000时,低通截止=10000hz 00:05000时,低通截止=5000hz 00:09000时,低通截止=1000hz 然后在10秒内切断保持在1000hz,然后切断降低到200hz 以下是如何进行简单的100hz低通: from scipy.io import wavfile import numpy as np from

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

例如:

  • 00:00000时,低通截止=10000hz
  • 00:05000时,低通截止=5000hz
  • 00:09000时,低通截止=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))
但是如何使截止值不同呢


注意:我已经读过了,但答案相当复杂(通常适用于多种过滤器)。

您可以使用scipy.fftpack.fftfreq和scipy.fftpack.rfft设置阈值

fft = scipy.fftpack.fft(sound)
freqs = scipy.fftpack.fftfreq(sound.size, time_step)
对于时间步,我做了两倍的声音采样率

fft[(freqs < 200)] = 0
fft[(频率<200)]=0
这会将所有小于200 hz的频率设置为零

对于时变截止,我会分割声音,然后应用过滤器。假设声音的采样率为44100,5000hz滤波器将在采样220500(5秒)时启动

10ksound=声音[:220500]
10kfreq=scipy.fftpack.fftreq(10ksound.size,时间步长)
10kfft=scipy.fftpack.fft(10ksound)
10kfft[(10kfreqs<10000)]=0
然后,对于下一个过滤器:

5ksound = sound[220500:396900]
5kfreq = scipy.fftpack.fftreq(10ksound.size, time_step)
5kfft = scipy.fftpack.fft(10ksound)
5kfft[(5kfreqs < 5000)] = 0
5ksound=声音[220500:396900]
5kfreq=scipy.fftpack.fftreq(10ksound.size,时间步长)
5kfft=scipy.fftpack.fft(10ksound)
5kfft[(5kfreqs<5000)]=0


编辑:要使其“滑动”或逐渐滤波,而不是分段滤波,您可以使“分段”更小,并对相应的分段(5000->5001->5002)应用越来越大的频率阈值。

一个相对简单的方法是保持滤波器固定并改为调制信号时间。例如,如果信号时间比标准时间快10倍,10KHz低通将起到1KHz低通的作用

要做到这一点,我们需要解决一个简单的ODE

dy       1
--  =  ----
dt     f(y)
这里
t
是实时调制时间
y
f
时间
y
的期望截止

原型实现:

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))
样本输出:


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

感谢您的回答,几句话:1)调零仓不是很好的滤波方式(但它可以工作),请参阅DSP相关主题,2)低通意味着我们可以消除更高的频率最大的问题:3)事实上,你的过滤器在声音的每一部分上都有2到3个标准过滤器。你有一个“分段恒定截止”,这很容易。困难在于有一个“滑动”截止(见问题)。你是对的,在小块上进行(例如1024个样本,即在44.1Khz采样率下约23ms)使其在“滑动情况”下工作。重要的是要关心初始条件参数。始终使用二阶butterworth?@Stephernauch任何IIR或FIR都可以,只要截止点C(t)可以沿时间t平稳变化(即C(t)不是分段常数函数)。听起来像是一项工作,但我对它们的经验不足,无法给出一个好的答案。不幸的是,
pywavelets
pywt
似乎是一种死标签。初始采样率是多少?@DanielF 44.1 Khz或48 Khz或96 Khz是典型值,这将非常有用。感谢您的回答。当我们处理音频时,使信号运行速度加快10倍,然后再将其重新降低,这将具有严重的破坏性(类似于44.1 Khz=>4.1 Khz=>44.1 Khz的重新采样)。无论如何,如果我们采用1000 Hz的低通滤波器,问题可能不会太大,但一般来说,这种方法不适用于更通用的时变滤波器(例如:您希望与原始问题相同,但使用高通或通带!那么这种解决方案的破坏性太大)@Basj三件事:(1)你的问题是关于低通的。(2) 即使不是,我认为你的问题可以通过(a)将过滤器固定在最低位置来解决。然后,只会减慢速度,即信号的上采样会发生,或者(b)先对信号进行上采样,然后再进行其他操作,或者(c)将(a)和(b)组合在一起(相当于(a),但通过安全系数将滤波器固定得更慢)(3)通过两次应用该方法,可以实现具有独立变化截止值的带通。你的评论是对的。尽管如此,在音频环境中,重采样是一件非常关键的事情(即使只做一次,甚至对于接近采样率的48 Khz=>44.1 Khz),创建混叠或其他人工制品等,并且需要特定的工具(关于这一点有很多深入的研究,目前最流行的解决方案之一是这个库:)。这就是为什么我宁愿不需要这样一个破坏性的工具,只是为了应用高通或低通。@Basj我在这里可能是错的,但是你不能把(2c)中的安全系数设置得太大以至于你几乎不丢失任何信息吗?别名不应该是一个问题,因为在最后我们将回到原始的时间网格。这就变成了计算成本的问题。在某种程度上,通过与稀疏的
total_no_samples x total_no_samples
矩阵相乘来强制执行可能会变得更便宜。以下是您的代码应用于巴赫的高尔伯格变奏曲的音频结果:。正如您所看到的,它是相当分散的(但不是经过过滤的!)。。。是的,古尔德;)
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))