On sait qu'en général la fonction de transfert d'un filtre est donnée par:
H(z)=∑Mk=0bkz−k∑Nk=0akz−k
Remplacez maintenant z=ejω pour évaluer la fonction de transfert sur le cercle unitaire:
H(ejω)=∑Mk=0bke−jωk∑Nk=0ake−jωk
Cela devient donc seulement un problème d'évaluation polynôme à une donnée ω . Voici les étapes:
- Créez un vecteur de fréquences angulaires ω=[0,…,π] pour la première moitié du spectre (pas besoin de monter jusqu'à 2π ) et enregistrez-le
w
.
- Pré-calculer l'exposant e−jω sur chacun d'eux et le stocker dans une variable
ze
.
- Utilisez la
polyval
fonction pour calculer les valeurs du numérateur et du dénominateur en appelant polyval(b, ze)
:, divisez-les et enregistrez-les H
. Parce que nous nous intéressons à l'amplitude, prenons alors la valeur absolue du résultat.
- Convertir en échelle dB en utilisant: HdB=20log10H - dans ce cas, 1 est la valeur de référence.
Mettre tout cela dans le code:
%% 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)
Sortie originale de freqz
:
Et la sortie de mon script:
Et une comparaison rapide à l'échelle linéaire - a fière allure!
[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'})
Vous pouvez maintenant le réécrire dans une fonction et ajouter quelques conditions pour le rendre plus utile.
Une autre façon (précédemment proposée est plus fiable) serait d'utiliser la propriété fondamentale, que la réponse en fréquence d'un filtre est une transformée de Fourier de sa réponse impulsionnelle:
H(ω)=F{h(t)}
Par conséquent, vous devez alimenter le signal δ(t) votre système , calculer la réponse de votre filtre et en prendre la FFT:
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 comparaison, cela produira ce qui suit: