How do I plot the frequency response of a digital filter in MATLAB? - matlab

I am trying to graph the frequency response. I was asked to use filter in MATLAB, but since I've read the manual, I still don't get how it performs a Z transform.
I have the impulse response of the digital filter written below:
for i=1:22;
y(i)= 0;
end
x(22) = 1;
for k=23:2523
x(k) = 0;
end
for n = 22:2522;
y(n) = ((1/21)*x(n))+((20/21)*y(n-21));
end
plot(y);
It's just a feedback system of y[n] = 1/21*x[n] + 20/21*y[n-21]
Below are my calculations to compute the Z transform of the above system, which ultimately determines the impulse response:
Z(y) = Z((1/21)*x(n)+(20/21)*y(n-21))
Y(Z) = (1/21)X(Z)+(20/21)*Z.^-21Y(Z)
Z(Z)-(20/21)*Z.^-21Y(Z) = (1/21)X(Z)
Y(Z)(1-(20/21)*Z.^-21) = (1/21)X(Z) // divide by X(Z)*(1-(20/21)*Z.^-21)
Y(Z)/X(Z) = (1/21)/(1-(20/21)*Z.^-21)
H(Z) = (1/21)/(1-(20/21)*Z.^-21) // B = 1/21, A = 20/21
H(Z) = (B*Z.^21)/(Z.^21-A)
How can I plot the frequency response of H(Z)? Should I use filter?

If you just need to plot the impulse response it's easy. The impulse response is the response of the digital filter to a Dirac pulse. You already have the difference equation, so you're already in 'z' and you don't care about the 's', you don't have to perform the 's' to 'z' transform (which is a topic in itself!).
So just generate a signal x(n) consisting of zeros everywhere except the first sample x(1) being 1. Pass it through the filter (yes, your difference equation). The y(n) you get is your impulse response h(n). That's basically what you did.
And of course if you FFT this h(n) you get the phase and magnitude response.

Use freqz from the signal processing toolbox (hope you have it). You first need to find the Z-transform, which you have already done here:
Y(Z)/X(Z) = (1/21)/(1-(20/21)*Z.^-21)
freqz takes in a vector of coefficients which correspond to the numerator and denominator of your transfer function. It's called like so:
freqz(b, a);
b and a are the numerator and denominator coefficients of your transfer function. This will produce a figure that shows the magnitude and phase response (hence frequency response) of the above system.
Therefore, all you need is to do this:
b = 1/21;
a = [1 zeros(1,20) -(20/21)];
freqz(b, a)
Take special note of the a vector. It has 1, followed by 20 zeros, then followed by -(20/21). Because you have a coefficient to the power of -21 and nothing else other than the 1 before it, that means that those coefficients between -1 to -20 are zero, and there are 20 of these coefficients that are zero in total, which is why we need to fill in the vector with zeroes between the 1 and -(20/21) term.
We get:
If you want to plot the poles and zeroes of your filter, use a combination of tf and pzmap:
sys = tf(b, a, -1);
pzmap(sys);
tf creates a transfer function by specifying the numerator and denominator coefficients of your filter, and -1 implies it's a discrete-time filter, but we don't know what the sampling time is. pzmap plots the poles and zeroes in the z-domain with the unit-circle overlaid.
We get this:
This makes sense as you have no zeroes in your system, and 21 poles, as you have 21 delay elements when examining the discrete-time sequence in your example.

From Matlab's filter documentation:
filters the input data, x, using a rational transfer function defined by the numerator and denominator coefficients b and a, respectively.
As you might know, filtering an impulse input would give you the impulse response. It then remains to obtain those b and a coefficients.
You could either obtain those directly from the difference equation
y[n] = 1/21*x[n] + 20/21*y[n-21];
(as indicated in the rational transfer function link above) or equivalently from the rational transfer function you have derived:
%H(Z) = (B*Z.^21)/(Z.^21-A)
In either case, you should get the following a and b coefficients:
a = [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20/21];
% or equivalently: a=zeros(22,1); a(1)=1; a(22)=-20/21;
b = [1/21];
Thus,
% setup the impulse input
x = zeros(2500,1);
x(1) = 1;
% compute the impulse response
y = filter(b, a, x);
This impulse response can be plotted as you have done:
plot(y);
As far as how this related to the transform H(Z), the closed form expression you obtained can be evaluated in terms of a Laurent series expansion, which then has the coefficients of the time-domain y (impulse response) series.
However, H(z) is an analytic function defined in the |z| > R (where R=power(20/21,1/21) in your case) region of convergence in the complex plane. It is more typical to plot the frequency response, which corresponds to the H(z) evaluated on the unit-circle (i.e. for complex number satisfying |z|=1 or equivalently z = exp(j * theta) with theta in the [0-2pi] range). An efficient method to compute values of H(z) at regularly spaced points on that unit-circle is to take the FFT of the impulse response:
FrequencyResponse = fft(y);
figure(1);
plot(abs(FrequencyResponse));
figure(2);
plot(phase(FrequencyResponse));
P.S.: the computation of filter and fft can be done in the single call freqz if you have the signal processing toolbox (although you were specifically asked to use filter).

Related

Analytical Fourier transform vs FFT of functions in Matlab

I have adapted the code in Comparing FFT of Function to Analytical FT Solution in Matlab for this question. I am trying to do FFTs and comparing the result with analytical expressions in the Wikipedia tables.
My code is:
a = 1.223;
fs = 1e5; %sampling frequency
dt = 1/fs;
t = 0:dt:30-dt; %time vector
L = length(t); % no. sample points
t = t - 0.5*max(t); %center around t=0
y = ; % original function in time
Y = dt*fftshift(abs(fft(y))); %numerical soln
freq = (-L/2:L/2-1)*fs/L; %freq vector
w = 2*pi*freq; % angular freq
F = ; %analytical solution
figure; subplot(1,2,1); hold on
plot(w,real(Y),'.')
plot(w,real(F),'-')
xlabel('Frequency, w')
title('real')
legend('numerical','analytic')
xlim([-5,5])
subplot(1,2,2); hold on;
plot(w,imag(Y),'.')
plot(w,imag(F),'-')
xlabel('Frequency, w')
title('imag')
legend('numerical','analytic')
xlim([-5,5])
If I study the Gaussian function and let
y = exp(-a*t.^2); % original function in time
F = exp(-w.^2/(4*a))*sqrt(pi/a); %analytical solution
in the above code, looks like there is good agreement when the real and imaginary parts of the function are plotted:
But if I study a decaying exponential multiplied with a Heaviside function:
H = #(x)1*(x>0); % Heaviside function
y = exp(-a*t).*H(t);
F = 1./(a+1j*w); %analytical solution
then
Why is there a discrepancy? I suspect it's related to the line Y = but I'm not sure why or how.
Edit: I changed the ifftshift to fftshift in Y = dt*fftshift(abs(fft(y)));. Then I also removed the abs. The second graph now looks like:
What is the mathematical reason behind the 'mirrored' graph and how can I remove it?
The plots at the bottom of the question are not mirrored. If you plot those using lines instead of dots you'll see the numeric results have very high frequencies. The absolute component matches, but the phase doesn't. When this happens, it's almost certainly a case of a shift in the time domain.
And indeed, you define the time domain function with the origin in the middle. The FFT expects the origin to be at the first (leftmost) sample. This is what ifftshift is for:
Y = dt*fftshift(fft(ifftshift(y)));
ifftshift moves the origin to the first sample, in preparation for the fft call, and fftshift moves the origin of the result to the middle, for display.
Edit
Your t does not have a 0:
>> t(L/2+(-1:2))
ans =
-1.5000e-05 -5.0000e-06 5.0000e-06 1.5000e-05
The sample at t(floor(L/2)+1) needs to be 0. That is the sample that ifftshift moves to the leftmost sample. (I use floor there in case L is odd in size, not the case here.)
To generate a correct t do as follows:
fs = 1e5; % sampling frequency
L = 30 * fs;
t = -floor(L/2):floor((L-1)/2);
t = t / fs;
I first generate an integer t axis of the right length, with 0 at the correct location (t(floor(L/2)+1)==0). Then I convert that to seconds by dividing by the sampling frequency.
With this t, the Y as I suggest above, and the rest of your code as-is, I see this for the Gaussian example:
>> max(abs(F-Y))
ans = 4.5254e-16
For the other function I see larger differences, in the order of 6e-6. This is due to the inability to sample the Heaviside function. You need t=0 in your sampled function, but H doesn't have a value at 0. I noticed that the real component has an offset of similar magnitude, which is caused by the sample at t=0.
Typically, the sampled Heaviside function is set to 0.5 for t=0. If I do that, the offset is removed completely, and max difference for the real component is reduced by 3 orders of magnitude (largest errors happen for values very close to 0, where I see a zig-zag pattern). For the imaginary component, the max error is reduced to 3e-6, still quite large, and is maximal at high frequencies. I attribute these errors to the difference between the ideal and sampled Heaviside functions.
You should probably limit yourself to band-limited functions (or nearly-band-limited ones such as the Gaussian). You might want to try to replace the Heaviside function with an error function (integral of Gaussian) with a small sigma (sigma = 0.8 * fs is the smallest sigma I would consider for proper sampling). Its Fourier transform is known.

Matlab - Plotting filtered audio

I'm trying to plot a filtered audio, but I'm doing something wrong because the second plot shows nothing.
[wave,fs]=wavread('my-audio.wav');
t=0:1/fs:(length(wave)-1)/fs;
figure(1);plot(t,wave);
b = [1.1 1];
a = [-0.1 0 1];
FIR = filter(b,a,wave);
figure(2);plot(t,FIR);
The function I'm using is: H(z)=(z + 1.1)/(z^2 - 0.1)
What am I missing?
Thanks!
It looks like you've inverted the order of the coefficients in the a and b vectors. Inverting the order of coefficients is particularly dramatic for the feedback coefficients a which define the poles of the transfer function (and hence determine the stability of the filter). The resulting filtered output FIR thus likely exceeds numerical float capacity, which plot has trouble with.
According to filter's documentation, the a and b coefficients are defined using a transfer function of the form:
Since your transfer function is
you should be using the coefficients
b = [0 1 1.1]
a = [1 0 -0.1]

Questions about lowpass filters using 'butter' function in Matlab

I am trying to design a lowpass filter in Matlab:
fc = 100; % Cutoff frequency
fs = 4020; % Sampling frequency
w_norm = 2*fc/fs;
filter_order = 1;
[num,denom] = butter(filter_order,w_norm)
sys = tf(num, denom)
[z,p,k] = zpkdata(sys)
Matlab gives me a pole at:
s = 0.8541
My questions are:
Where does this number come from? Shouldn't the pole be at w = 2*pi*fc = 628 rad/s (normalised to 1 if divided by wc)?
Shouldn't it be negative since butterworth LP filter poles are in the left half plane?
Why does Matlab also give me a zero at -1?
Many thanks.
By default, butter produces a discrete-time filter design. Therefore the transfer function is defined in terms of z (z-transform), not s (Laplace transform).
A discrete-time Butterworth filter of order n has an n-order zero at z=-1 and n poles within the unit circle. This is in accordance with your results. (In contrast, a continuous-time Butterworth filter would have an n-order zero at infinity and n poles in the left-hand unit semicircle).

How to find the frequency response of the Rosenberg Glottal Model

Is there an easy way to calculate the frequency response of the following function?
I tried using heaviside function but with no luck.
Basically I want to write a function to return the frequency response based on input N1 and N2 and also the number of points (lets say x) between 0 and pi
The output would be a vector which returns x values for the frequency response for corresponding frequencies => 0:pi/x:pi
Assuming that N1 + N2 < num_points, where num_points is the length of the sequence, you can simply write the function like so:
function [gr] = rosenburg(N1, N2, num_points)
gr = zeros(num_points,1);
range1 = 0:N1;
range2 = N1+1:N1+N2;
gr(range1+1) = 0.5*(1 - cos(pi*range1/N1));
gr(range2+1) = cos(pi*(range2-N1) / (2*N2));
end
The function prototype, rosenburg takes in N1, N2 and the total number of points you want this function to take in, num_points. How this code works is that we first allocate an array that is all zeroes of size num_points. We then compute two linear ranges: One from 0 <= n <= N1 and the other from N1 < n <= N2. Note that the second range starts by offsetting N1 by 1 because we have already computed the value at n = N1. Once we compute these ranges, we simply apply the right relationship in the right ranges. Note that when I'm assigning the relationships to the correct intervals in the array, I need to offset by 1 because MATLAB begins indexing arrays at index 1. The rest of the values are zero due to the initialization at the beginning of the function.
Now, if you want to find the frequency response of this signal, just use fft which is the Fast Fourier Transform. It's the classic method to find the frequency domain version of a discrete input signal on a numerical basis. As such, once you create your signal using the rosenburg function, then throw this into the FFT function. How you call it is like so:
X = fft(gr);
This computes the N point FFT, where N is the length of the signal gr. Alternatively, you can provide the number of points you want to compute the FFT for. Specifically:
X = fft(gr, N);
Basically, the higher N is, the finer or granular the frequency components will be. Note that the frequency axis is normalized between 0 to 2*pi, and so the higher N is, the finer resolution you will have between neighbouring points on the axis. Specifically, each point on this axis has the following frequency:
w = i*(2*pi)/x;
i would be the index on the x-axis (0, 1, 2, ..., num_points-1) and x would be the total number of points for the FFT. Normally, people show the spectrum between -pi <= w <= pi, and so some people apply fftshift to shift the spectrum so that the DC component is located at the centre of the spectrum, which is how we naturally perceive the spectrum to be.
When you say "frequency response", I believe you are referring to the magnitude, and so use abs to calculate the complex magnitude of each value, as the fft is generally complex valued. Therefore, assuming that you wish to compute the FFT to be as many points as the length of your signal, and let's say we choose N1 = 4, N2 = 8 and we want 64 points, and we want to plot the spectrum. Simply do this:
gr = rosenburg(4, 8, 64);
X = fft(gr);
Xshift = fftshift(X);
plot(linspace(-pi,pi,64), abs(Xshift));
grid;
The above code will shift the spectrum, then plot its magnitude between -pi to pi. This is what I get:
As an illustration, this is what the spectrum looks like before we apply fftshift:
Here's the code to generate the above figure:
plot(linspace(0,2*pi,64), abs(X));
grid;
You can see that the spectra is symmetric. Right at the frequency pi, you can see that it is mirror reflected, which makes sense as the range from pi to 2*pi, precisely maps to -pi to 0. Because the signal is real, the spectrum is symmetric. In fact, we can call this signal Hermitian symmetric. Obviously, the frequency components are a bit sparsely spaced. It may be better to increase the total number of points to something like 256. This is what I get when I change the number of points to 256:
Pretty smooth! Now, if you want to extract the frequency components from 0 to pi, you need to extract half of the frequency decomposition that is stored in X. Therefore, you would simply do:
f = X(1:numel(X)/2);
numel determines how many elements are in an array or matrix. However, remember that each frequency point was defined as:
w = i*(2*pi)/x
You specifically want:
w = i*pi/x
As such, you'll need to compute the FFT at twice the size of your signal first, then extract half of the spectra in the same way. For example, for 64 points:
gr = rosenburg(4, 8, 64);
X = fft(gr, 128);
f = X(1:numel(X)/2);
This should hopefully get you started. Good luck!

How to make a Simple FIR Filter using Matlab?

How can I make a simple low-pass FIR filter using Matlab (without using the built-in function) ?
Problem example:
Implement a FIR LPF with cut-off frequency 250Hz
it may also be necessary that, sampling freq is given...
Solution attempt or what I already know:
x = [...] -> input signal
A = 1; -> Since this is FIR
B = [?????]
y = filter(B, A, x) -> Output signal
Afaik, B should contain the coefficients for the FIR filter. But; how do I calculate these coefficients given that I only have the cut-off frequency?
The simplest thing is a "windowed sinc" filter:
fs = 44100;
cutoff = 250;
t = -256:256; % This will be a 513-tap filter
r = 2*cutoff/fs;
B = sinc(r*t).*r .* blackman(length(t))';
freqz(B);
The length of the filter (see t=...) controls the width of the transition band. cutoff is in this case the -6 dB point. blackman is the name of a popular window. You can check out this Wikipedia page for more infos on window functions. They basically have different trade-offs between transition band width and stopband rejection.
If you wan't a different shape of the amplitude spectrum, do exactly as sellibitze suggested, only replace the sinc function with the real part of the inverse Fourier-transform of the desired amplitude response (delayed to get causal symmetrical impulse response).
Since the Coefficients to a LTI filter are the time domain impulse response, you could create the frequency response in matlab by specifying an Amplitude vector, and and Phase Vector, then Inverse FFT them to get your coefficients, for example, soemthing like A = [ 1 .9 .8 .5 .2 .1 0], theta=[0 0 0 0 0 0 0], then H=A.*exp(j*theta) then coefs = ifft(H)