我遇到的问题scipy.signal.minimumphase
没有提供与我输入相同的幅度响应,它偏离了很多。
长话短说。我有一种材料,其中所述材料的吸收是在倍频带(6个离散值)中测量的。我需要一个适合这些值的脉冲响应。我想通过使用最小相位FIR滤波器来近似该脉冲响应,因为我没有任何相位信息。
我的程序如下
scipy.signal.minimuphase
创建最小相位冲动样条插值在这里不是问题,问题是最小相位的大小偏离了线性相位,我似乎无法找到错误或原因?运行下面的代码会产生以下响应:
这是代码的最小工作部分,它绘制了插值幅度响应,线性相位幅度和最小相位幅度。
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
plt.close('all')
## Determining Gradient between points
def slope(x1, y1, x2, y2):
m = (y2-y1)/(x2-x1)
return m
## Parameters for designing the frequency response
fs = 48000
N = 4096
alpha = np.array([1,0.07,0.17,0.40,0.55,0.65,0.65,1])
beta = np.sqrt(1-alpha)
f = np.array([0,125,250,500,1000,2000,4000,(fs/2)])
### Spline interpolation
faxis = np.linspace(0,fs/2,np.int64(N))
gradient = np.zeros((np.size(f),1))
x = np.zeros([4,np.size(f)-1])
for n in range(0,np.size(f)-1,1):
gradient[n] = slope(f[n],beta[n],f[n+1],beta[n+1])
for n in range(0,(np.size(f))-1,1):
a = np.array([[f[n]**3,f[n]**2,f[n]**1,1],
[f[n+1]**3,f[n+1]**2,f[n+1]**1,1],
[3*(f[n]**2),f[n]*2,1,0],
[3*(f[n+1]**2),f[n+1]*2,1,0]])
b = np.array([beta[n],beta[n+1],gradient[n],gradient[n+1]])
x[:,n] = np.linalg.solve(a, b)
## Using a,b,c,d coef. to make the polynomials and then crop them to fit
poly = np.zeros([(np.size(faxis)),np.size(beta)])
combined = np.array([])
for n in range(0,np.size(poly,1)-1,1):
poly[:,n] = x[0,n]*faxis**3+x[1,n]*faxis**2+x[2,n]*faxis+x[3,n]
combined = np.append(combined,poly[(faxis >= f[n]) & (faxis <= f[n+1]),n])
## Mirror the single sided frequency response
Full = np.concatenate((combined,np.flipud(combined)))
## ifft the mirrored resposne - No Phase info
impulse = np.real(np.fft.ifft(Full))
## Add linear phase to the impulse - i.e. shift the response and make it causal
impulseshift = np.roll(impulse,np.int(len(impulse)/2)-1)
## Change to minimumphase
minphase = signal.minimum_phase(impulseshift[:-1],method='hilbert',n_fft=fs)
## Plot the results
wLinear, hLinear = signal.freqz(impulseshift,worN=4096)
w, h = signal.freqz(minphase,worN=4096)
plt.figure
plt.semilogx(faxis,combined,label="No Phase")
plt.semilogx((fs * 0.5 / np.pi) * w, abs(h),label="Minimum Phase")
plt.semilogx((fs * 0.5 / np.pi) * wLinear, abs(hLinear),label="Linear Phase")
plt.grid()
plt.legend()
plt.xlabel("Frequency [Hz]")
plt.ylabel("Amplitude [.]")
答案 0 :(得分:0)
除了使用scipy.signal.firwin2
直接基于某些倍频程带增益设计线性相位滤波器(您的第1步至第4步),然后使其成为最小相位外,我在做相同的事情。
如果您查看documentation中的参数详细信息,则会看到:
产生的最小相位滤波器的幅度响应为 近似于原始过滤器幅度的 平方根 响应。
您的情节反映了这种平方根关系。简单的解决方法是在将您的“所需幅度响应”输入scipy.signal.minimuphase
之前对其进行平方。