如何在两个 FFT 之间进行插值?

信息处理 fft 插值
2022-02-22 20:25:51

我有两个代表两个脉冲响应的 FFT。我想在它们两者之间进行插值,以如下图所示的方式生成第三个 FFT。这将用于两个 FFT 过滤器之间的实时音频渲染过滤。

每个 FFT 的复系数之间的线性插值不能按预期工作。

FFT plots of two impulse responses 
(x = frequency/coefficient, y = frequency magnitude)

+                                   +                           
|                                   |                           
|        +                          |                           
|        |                          |                           
|        |                          |                           
|        |                          |                           
|        |                          |                           
|        |                          |                   +       
|        |                          |                   |       
|        |                          |                   |       
+--------+------------------+       +-------------------+-------+    
           Input A                              Input B

FFT plots of interpolation between A and B (Linear, and Wanted)
(x = frequency/coefficient, y = frequency magnitude)

+                                   +                                
|                                   |                                
|                                   |                                
|                                   |                                
|                                   |                                
|                                   |             +                  
|        +                          |             |                  
|        |                          |             |                  
|        |          +               |             |                  
|        |          |               |             |                  
+--------+----------+-------+       +-------------+-------------+    
Linear Interpolation (A+B/2)            Wanted Interpolation

如何按照Wanted Interpolation图中的说明进行插值?

2个回答

这是两个频率之间的线性插值作为“加权平均”的解决方案。您只需要根据垂直轴的幅度或 dB 比例来确定您的加权实际是多少。X 是插值频率,向更强的信号加权,Y 是信号强度 a 和 b 的新频率位置处的线性插值。

在此处输入图像描述

这是一个简单的示例,演示了使用给定公式可以实现的结果:

在此处输入图像描述

看看下面的脚本。它不能解决你所有的问题,但它可以作为一个起点:

import scipy.interpolate

# 1) Here, I define some arbitrary initial spectrum, 
#    for example it consts of two paeaks
#    Here, I simplify and set the frequencies to be between 0 and 1 in 100 steps.
f = np.linspace(0,1,100)  
#H_begin = lambda f: 1.5+np.sin(2*np.pi*f)
H_begin = lambda f: (abs(f-0.05) < 0.01) + (abs(f-0.5)<0.005)

# define the matching frequencies: 
#  0 at the beginning remains zero after the warping
#  1 at the beginning remains one after warping
#  frequency 0.5 should be warped to 0.25 
f_matches = [(0,0), (1,1), (0.5,0.25)]

# generate the according inputs and outputs of the 2d function 
# that should be interpolated
f_in = np.array([x[0] for x in f_matches]*2)
t_in = np.array([0]*len(f_matches)+[1]*len(f_matches))
f_out = np.array([x[0] for x in f_matches] + [x[1] for x in f_matches])

# just printout the supporting points we have defined
for n in range(len(f_in)):
    print ("X(f=%f,t=%f)=%f" % (f_in[n], t_in[n], f_out[n]))

# generate the interpolation     
X = scipy.interpolate.interp2d(f_out, t_in, f_in)

# visualize the interpolation
t_range = np.linspace(0,1,100)
img = np.zeros((len(f), len(t_range)))
for n, t0 in enumerate(t_range):
    img[:,n] = H_begin(X(f,t0))
plt.imshow(img)
plt.xlabel('interpolation time')
plt.ylabel('frequency');

输出:

X(f=0.000000,t=0.000000)=0.000000
X(f=1.000000,t=0.000000)=1.000000
X(f=0.500000,t=0.000000)=0.500000
X(f=0.000000,t=1.000000)=0.000000
X(f=1.000000,t=1.000000)=1.000000
X(f=0.500000,t=1.000000)=0.250000

在此处输入图像描述

它执行以下操作:

从 0 增加到 1时,你有一对频率应该从对中的第一个元素扭曲到第二个元素你得到初始光谱,对于,您将获得最终光谱)。因此,给定一些支持的开始频率和结束频率之间的映射,我们可以创建二维插值。对于输入频率和插值时间,它返回到该频率将被扭曲到的位置。tt=0t=1t

什么没有解决:

  • 如何找到支撑点f_match您可能会寻找峰值匹配算法或想出适合您的应用程序的东西
  • 如果这是关于音频处理的,我认为插值应该在对数域而不是线性域中完成。但是,算法不会改变,只是在插值前取每个频率的对数,插值后将其转换回线性频率。
  • 我的脚本假设您对所有频率的频谱都有准确的信息(H_begin是一个函数)。然而,实际上您只能访问频谱的离散频率。因此,如果插值需要您从两个 bin 之间的频率中获取值,则需要对原始频谱进行插值以近似该值。