Sabemos que, en general, la función de transferencia de un filtro viene dada por:
H(z)=∑Mk=0bkz−k∑Nk=0akz−k
Ahora sustituya para evaluar la función de transferencia en el círculo unitario:z=ejω
H(ejω)=∑Mk=0bke−jωk∑Nk=0ake−jωk
Por lo tanto, esto se convierte solo en un problema de evaluación polinómica en un determinado . Aquí están los pasos:ω
- Cree un vector de frecuencias angulares para la primera mitad del espectro (no es necesario subir a ) y guárdelo .ω=[0,…,π]2π
w
- Pre-calcular el exponente en todos ellos y almacenarlo en variable .e−jω
ze
- Use la
polyval
función para calcular los valores de numerador y denominador llamando: polyval(b, ze)
dividirlos y almacenarlos H
. Como estamos interesados en la amplitud, tomemos el valor absoluto del resultado.
- Convierta a escala dB utilizando: - en este caso es el valor de referencia.HdB=20log10H1
Poniendo todo eso en el código:
%% Filter definition
a = [1 -0.5 -0.25]; % Some filter with lot's of static gain
b = [1 3 2];
%% My freqz calculation
N = 1024; % Number of points to evaluate at
upp = pi; % Evaluate only up to fs/2
% Create the vector of angular frequencies at one more point.
% After that remove the last element (Nyquist frequency)
w = linspace(0, pi, N+1);
w(end) = [];
ze = exp(-1j*w); % Pre-compute exponent
H = polyval(b, ze)./polyval(a, ze); % Evaluate transfer function and take the amplitude
Ha = abs(H);
Hdb = 20*log10(Ha); % Convert to dB scale
wn = w/pi;
% Plot and set axis limits
xlim = ([0 1]);
plot(wn, Hdb)
grid on
%% MATLAB freqz
figure
freqz(b,a)
Salida original de freqz
:
Y la salida de mi script:
Y una comparación rápida en escala lineal: ¡se ve genial!
[h_f, w_f] = freqz(b,a);
figure
xlim = ([0 1]);
plot(w, Ha) % mine
grid on
hold on
plot(w_f, abs(h_f), '--r') % MATLAB
legend({'my freqz','MATLAB freqz'})
Ahora puede reescribirlo en alguna función y agregar algunas condiciones para que sea más útil.
Otra forma (propuesta anteriormente es más confiable) sería usar la propiedad fundamental, que la respuesta de frecuencia de un filtro es una Transformada de Fourier de su respuesta de impulso:
H(ω)=F{h(t)}
Por lo tanto, debe alimentar la señal δ(t) su sistema , calcular la respuesta de su filtro y tomar la FFT de la misma:
d = [zeros(1,length(w_f)) 1 zeros(1,length(w_f)-1)];
h = filter(b, a, d);
HH = abs(fft(h));
HH = HH(1:length(w_f));
En comparación, esto producirá lo siguiente: