EDIT: I can get the corrections accuratly when i take the difference after abs(fft(x1)) and I am able to ahieve correct values for either power correciton or dB SPL correciton as vectors but by that point I am no longer able to ifft back to the time domain.
Hi, How can I create an FIR from difference of two impulse responses?
43 views (last 30 days)
Show older comments
Hello, I am trying to create an FIR and assocaited waveform for a trasnfer fucntion that is the magnitude difference between the two impulses responses. I have recorded both IR's but am struggling with getting the correction factor to be correct. Here is my code and results of the IRs and difference which is clearly wrong because it is reducing magntiude incorrectly. I can see kind of where it is going wrong which seems to be in taking the difference between them which results in the following magnitude graph and DBFS graph. I have inlcuded wav files as csv if trying to run.
when i mak apply 20*log(x) to each vector to find DBFS
% Define the sampling frequency
close all
%[x1,fs] = audioread('711_Tap1024.wav');
%[x2,fs] = audioread('5128_Tap1024.wav');
x1 = readmatrix('711_Tap1024.csv');
x2 = readmatrix('5128_Tap1024.csv');
fs = 48000;
Nfft = length(x1);
% Frequency vector (assume frequencies are normalized, or you need to normalize by fs/2)
f = linspace(0, fs, Nfft);
f = f';
% Define or import the frequency responses H1 and H2
H1 = fft(x1,Nfft);
H2 = fft(x2,Nfft);
% Compute the difference in frequency responses
H_diff = H1-H2;
% Inverse FFT to obtain the impulse response
y = real(ifft(H_diff,Nfft));
% Normalize the impulse response
y_new = 0.99*y/max(abs(y));
% Save the impulse response as a WAV file
audiowrite('impulse_response_diff.wav', y, fs);
% Plot the impulse response (optional)
figure;
plot(y)
y1=abs(fft(x1,Nfft));
y2=abs(fft(x2,Nfft));
y3=abs(fft(y,Nfft));
y1= 20*log10(y1);
y2= 20*log10(y2);
y3= 20*log10(y3);
figure
plot(f(1:Nfft/2), y1(1:Nfft/2));
hold on
plot(f(1:Nfft/2), y2(1:Nfft/2));
hold on
plot(f(1:Nfft/2), y3(1:Nfft/2));
xlim([20 20000])
xticks([100 1000 10000])
grid on
set(gca, 'XScale', 'log')
xlabel ('Frequency (Hz)');
ylabel ('Amplitude ');
3 Comments
Star Strider
on 22 Nov 2024 at 18:39
You need to subttract the complex results, not the abs results. Then, you should be able to invert the difference. (This is essentiially frequency-domain filtering, and while not recommended, is possible.)
That aside, it is difficult to understand what you want to do.
Answers (1)
Star Strider
on 22 Nov 2024 at 18:25
I slightly changed your original code here, in order to define my questions about it.
It is possible to use the firls function to approximatee the ‘y3’ plot. If you want to use it on your existing data, be miindful of the filter length (in this instance the filter order), since it should be less than one-third of the signal length.
This result is far from perfect, however it should provide a startiing point —
x1 = readmatrix('711_Tap1024.csv');
x2 = readmatrix('5128_Tap1024.csv');
fs = 48000;
Nfft = length(x1);
% Frequency vector (assume frequencies are normalized, or you need to normalize by fs/2)
f = linspace(0, fs, Nfft);
f = f';
% Define or import the frequency responses H1 and H2
H1 = fft(x1,Nfft);
H2 = fft(x2,Nfft);
% Compute the difference in frequency responses
H_diff = H1-H2;
% Inverse FFT to obtain the impulse response
y = H_diff;
% % y = real(ifft(H_diff,Nfft));
% Normalize the impulse response
y_new = 0.99*y/max(abs(y));
% Save the impulse response as a WAV file
% % audiowrite('impulse_response_diff.wav', y, fs);
% Plot the impulse response (optional)
% % figure;
% % plot(y)
y1=abs(fft(x1,Nfft));
y2=abs(fft(x2,Nfft));
y3=abs(fft(y,Nfft));
y1= 20*log10(y1);
y2= 20*log10(y2);
y3= 20*log10(y3);
figure
plot(f(1:Nfft/2), y1(1:Nfft/2), DisplayName='y_1');
hold on
plot(f(1:Nfft/2), y2(1:Nfft/2), DisplayName='y_2');
hold on
plot(f(1:Nfft/2), y3(1:Nfft/2), DisplayName='y_3');
xlim([20 20000])
xticks([100 1000 10000])
grid on
set(gca, 'XScale', 'log')
xlabel ('Frequency (Hz)');
ylabel ('Amplitude ');
legend('Location','best')
% ylim([-50 50])
format shortG
fn = fs/2
Lv = f < fn;
fstop = (y3(Lv) < -275);
stopbands = f(fstop)
firn = 150;
fv = f < fn;
firf = f(fv);
a = y3(fv);
ftype = 'hilbert';
b = firls(firn, firf, a, ftype);
figure
freqz(b, 1, 2^16, fs)
.
4 Comments
Star Strider
on 22 Nov 2024 at 22:09
My pleasure!
I am having problems understanding what you are doing. The filter based on ‘H_diff’ has a lowpass characteristic with a cutoff frequency of abour 18.5 kHz. It might be easier to just design a filter to do that, using the fir1 function. I did that as well here.
As I understand it, you want to do something liike this —
x1 = readmatrix('711_Tap1024.csv');
x2 = readmatrix('5128_Tap1024.csv');
fs = 48000;
Nfft = length(x1);
% Frequency vector (assume frequencies are normalized, or you need to normalize by fs/2)
f = linspace(0, fs, Nfft);
f = f';
% Define or import the frequency responses H1 and H2
H1 = fft(x1,Nfft);
H2 = fft(x2,Nfft);
% Compute the difference in frequency responses
H_diff = H1-H2;
fn = fs/2;
fp = f <= fn; % Logical Vector<
figure
plot(f(fp), mag2db(abs(H1(fp))*2), DisplayName='H_1');
hold on
plot(f(fp), mag2db(abs(H2(fp))*2), DisplayName='H_2');
hold on
plot(f(fp), mag2db(abs(H_diff(fp))*2), DisplayName='H_{diff}');
xlim([20 20000])
xticks([100 1000 10000])
grid on
set(gca, 'XScale', 'log')
xlabel ('Frequency (Hz)');
ylabel ('Amplitude ');
legend('Location','best')
format shortG
a = mag2db(abs(H_diff(fp))*2);
an = a - max(a);
idx = find(diff(sign(an + 6)));
hpf = f(idx)
figure
plot(f(fp), mag2db(abs(H_diff(fp))*2))
hold on
plot(f(fp), an)
hold off
grid
yline(-6, '--k', '-6 dB')
xlabel('Frequency (Hz)')
ylabel('Magnitude (dB)')
title('H_{diff}')
fn = fs/2;
firn = fix(numel(x1)/4);
firf = f(fp)/fn;
% a = mag2db(abs(H_diff(fp)));
% a = a - max(a);
ftype = 'hilbert';
b1 = firls(firn, firf, an, ftype);
figure
freqz(b1, 1, 2^16, fs)
b1 = firls(firn, firf, an);
figure
freqz(b1, 1, 2^16, fs)
b2 = fir1(firn, max(hpf)/fn);
figure
freqz(b2, 1, 2^16, fs)
% set(subplot(2,1,1), 'XScale','log', 'XLim',[20 20000])
% set(subplot(2,1,2), 'XScale','log', 'XLim',[20 20000])
.
See Also
Categories
Find more on Single-Rate Filters in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!