freqz() magnitude plot behavior for estimated filter coefficients
3 views (last 30 days)
Show older comments
I am working on a project involving estimating a digital filter representation of an experimentally-determined frequency response.
The system in question has a frequency response that, interestingly, has a slight increase in magnitude as frequency increases, like the following plot:

I've estimated FIR filter coefficients using the invfreqz() function with denominator n = 0, and numerator m = 200. This results in a set of coefficients, a and b, respectively.
Given a set of frequencies used in the initial experiment in which we obtained the frequency response, stored and normalized in the vector w -> [0,pi], validating these coefficients using the function freqz() in the following manner results in the following plot. It appears to be pretty consistent with the initial frequency response data.
h = freqz(b,a,w);
subplot(2,1,1); plot(w,abs(h)); grid on; ylabel('Magnitude'); xlabel('Frequency (Hz)');
subplot(2,1,2); plot(w,angle(h)); grid on; ylabel('Phase (rad)'); xlabel('Frequency (Hz)');

However, when I don't input the frequency vector, and instead let freqz() output the frequency bins, the resulting plot is quite different:
[h,w] = freqz(b,a);
subplot(2,1,1); plot(w,abs(h)); grid on; ylabel('Magnitude'); xlabel('Frequency (Hz)');
subplot(2,1,2); plot(w,angle(h)); grid on; ylabel('Phase (rad)'); xlabel('Frequency (Hz)');

The frequency vector from the experiment consists of only 101 points between 60 and 10060 Hz, so I suspect the freqz() function is interpolating to fill out the default size-512 frequency output vector in the latter case. But I'm not sure why that results in such a strong sinusoidal pattern, or why the phase appears to tend around 0 radians for the entire spectrum, rather than a slight linear decrease.
What could be going on here?
3 Comments
Paul
on 4 Jan 2024
Except I thought the w vector was in rad from 0->pi, not rad/s?
In any case, I suggest uploading your b, a, and w vectors in .mat file using the paper clip icon on the Insert menu.
Answers (1)
Star Strider
on 3 Jan 2024
The third argument to freqz (when the first two are the transfer function coefficients, different with a second-order-section matrix or a digital filter object) is the number of points at which to evalate the transfer function (in this instance). Ideally, that should be a scalar.
Experimenting with that idea —
b = fir1(200, 0.9, 'high'); % Prototype filter
a = 1;
w = linspace(60, 1E+4, 101)/(2*pi) % Radian Frequency Vector (Guess)
figure
h = freqz(b,a,w);
subplot(2,1,1); plot(w,abs(h)); grid on; ylabel('Magnitude'); xlabel('Frequency (Hz)');
subplot(2,1,2); plot(w,angle(h)); grid on; ylabel('Phase (rad)'); xlabel('Frequency (Hz)');
figure
[h,w] = freqz(b,a);
subplot(2,1,1); plot(w,abs(h)); grid on; ylabel('Magnitude'); xlabel('Frequency (Hz)');
subplot(2,1,2); plot(w,angle(h)); grid on; ylabel('Phase (rad)'); xlabel('Frequency (Hz)');
figure
freqz(b, 1, 2^16, 10000) % High-Resolution Version
What you are seeing may be a very low resolution version of the actual transfer function in the first instance, although I have no idea how freqz interprets a vector input for the third argument, since it expects a scalar, and apparently doesn’t check to be sure that it is, or that the value is an integer. When you leave freqz to its own devices, it produces a higher resolution version.
Without your code (or your ‘b’ vector), this is only a guess on my part, however it could explain the discrepancy.
The problem is likely not with freqz, and is instead what you are giving it.
.
0 Comments
See Also
Categories
Find more on Digital Filter Analysis 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!