将频率响应转换为脉冲响应

信息处理 傅里叶变换 频率响应 冲动反应
2022-02-08 22:09:38

我正在运行声学模拟。我输入一个频率并得到一个复数;该频率的频率响应。

我希望生成 1024 个样本的脉冲响应(假设我的输出采样率为 44.1kHz)

我该怎么做?

我想我已经迈出了第一步:取奈奎斯特频率 22.05kHz,并将其切成 512 等份。所以每个切片的带宽为 22050/512 Hz

现在我将这些频率输入模拟器并返回 512 个复数;第一个将是 0+0i 对应于 0Hz

现在我遵循的指令是:'现在将 0Hz 视为对称点,并添加 511 个负频率。

所以我有 { Re(511) + i.Im(511), ..., Re(1) + i.Im(1), 0 + 0i, Re(1) + i.Im(1), .. ., Re(511) + i.Im(511), }

1023 个频率。

现在我很困惑。我不知道我在做什么了。

显然我需要 IFFT 这个,这会给我一个 1023 样本脉冲响应?

有人可以帮我把脚放回地面吗?

MatLab 代码会是什么样子?

(另外,有没有什么方法可以从 Bash shell 使用 Python 或类似的东西来做到这一点?)

2个回答

这是一个 MATLAB 示例。低效的代码,但希望易于阅读

%% Example: first order bandpass from 200 to 2000 Hz sampled at 44.1 kHz
n = 1024; % FFT length
fs = 44100; % sample rate
f0 = [200 2000]; % bandpass range
[b,a] = butter(1,2*f0/fs); % these are the difference equation coefficients
b0 = b(1); b1 = b(2); b2 = b(3);
a0 = a(1); a1 = a(2); a2 = a(3);  % for easier readability

% Step 1: build normalized frequency vector
om = 2*pi*(0:n/2)'/n;

% step 2: calculate the frequency response at every frequency
z = exp(j*om); % this is the "z" of the z-transform
% calculate the Z transform , 
H = (b0+ b1*z.^-1 + b2*z.^-2)./(a0+ a1*z.^-1 + a2*z.^-2);

% Step 3: make it conjugate symmetric
H = [H; conj(H(end-1:-1:2))];

% Step 4: inverse FFT
h = real(ifft(H));

% Step 5: verify against direct evaluation of the time domain difference equation
d0 = zeros(n,1); d0(1) = 1; % unit impulse
href = filter(b,a,d0);
err = 10*log10( sum((h-href).^2)./sum(href.^2));
fprintf('Error = %6.2f dB\n',err);

我已经在https://stackoverflow.com/questions/21209017/python-convert-frequency-response-to-impulse-response提出了答案

基本上,如果我的频率是:

{ f_dc, f_1, ..., f_k, f_nyquist }  

    (f_dc=0, f_nyquist for me = 22050 a.k.a freq limit for 44.1kHz audio)

我必须构建:

{ DC, f_1, ..., f_k, nyquist, f_k*, ..., f_1* }

    with DC = nyquist = 0 (note: z* is the complex conjugate of z)

然后我iFFT。