之前已经写过一篇使用overlap-add方法计算两个信号的卷积示例
本篇将卷积部分的计算从时域改为频域,基本操作步骤不变
示例代码如下:
import numpy as np
def get_blocks(signal, block_length):
a_length = len(signal)
padding_length = block_length - 1
segments = -(-a_length // block_length)
result = np.zeros((segments, block_length + padding_length))
for i in range(segments):
b = signal[i * block_length: (i + 1) * block_length]
p = block_length + padding_length - len(b)
b = np.pad(b, (0, p), 'constant', constant_values=(0, 0))
result[i] = b
return result
def fft_H(h, length):
if len(h) < length:
h = np.pad(h, (0, length - len(h)), 'constant', constant_values=(0, 0))
return np.fft.fft(h)
def convolve_blocks(blocks, H):
'''
该方法改为了从频域计算
'''
result = np.zeros((blocks.shape[0], blocks.shape[1]))
for i in range(blocks.shape[0]):
X = np.fft.fft(blocks[i])
Y = X * H
y = np.fft.ifft(Y)
result[i] = y.real
return result
def convolve_overlap_add(a, h):
a_length = len(a)
h_length = len(h)
o_length = h_length - 1
blocks = get_blocks(a, h_length)
length = blocks.shape[1]
H = fft_H(h, length)
cb = convolve_blocks(blocks, H)
result = np.zeros(length * length)
read_offset = 0
overlap_add = np.zeros(length)
for i in range(cb.shape[0]):
if i == 0:
result[0:length] = cb[i]
read_offset = h_length
else:
result[read_offset:read_offset + length] = overlap_add + cb[i]
read_offset = read_offset + h_length
overlap_add = cb[i][h_length:]
overlap_add = np.pad(overlap_add, (0, length - len(overlap_add)), 'constant', constant_values=(0, 0))
return result[:a_length + o_length]
a = np.asarray([1, 3, -1, 2, 5, 3, -2, -4, -2, 1])
h = np.asarray([1, 2, -1])
c1 = convolve_overlap_add(a, h)
print('convolve_overlap_add:', c1)
c2 = np.convolve(a, h)
print('np.convolve:', c2)