Comment fonctionnent les sections biquad en cascade pour les filtres d'ordre supérieur?

20

J'essaie d'implémenter un filtre IIR d'ordre 8 et chaque note d'application et manuel que j'ai lu dit qu'il est préférable d'implémenter tout filtre d'ordre supérieur à 2 en tant que sections de second ordre. J'ai utilisé tf2sosdans MATLAB pour obtenir les coefficients pour les sections de deuxième ordre, ce qui m'a donné un coeff 6x4 pour 4 sections de second ordre, comme prévu. Avant la mise en œuvre en tant que SOS, le filtre du 8e ordre exigeait que 7 valeurs d'échantillonnage précédentes soient stockées (et les valeurs de sortie également). Maintenant, lors de l'implémentation en tant que sections de second ordre, comment le flux fonctionne-t-il de l'entrée à la sortie, dois-je stocker uniquement 2 valeurs d'échantillon précédentes? Ou la sortie du premier filtre alimente-t-elle x_inle deuxième filtre et ainsi de suite?

anasimtiaz
la source
vous devez stocker les états précédents pour chaque étape, en fonction de l'ordre du filtre dans cette étape, ce ne serait donc pas seulement 2 comme vous l'

Réponses:

13

C'est la dernière chose que vous avez dite ("Ou la sortie du premier filtre alimente-t-elle en tant que x_in le deuxième filtre et ainsi de suite?"). L'idée est simple: vous traitez les biquades comme des filtres de second ordre séparés qui sont en cascade. La sortie du premier filtre est l'entrée du second, et ainsi de suite, de sorte que les lignes à retard sont réparties entre les filtres. Si vous avez besoin d'optimiser la structure dans un environnement à mémoire limitée, vous pouvez noter que les biquads adjacents ont une mémoire à retard redondante (c'est-à-dire que les derniers échantillons de sortie de l'étape 1 sont les mêmes que les derniers échantillons d'entrée de l'étape 2, donc vous ne pas besoin de les stocker séparément comme vous le feriez si vous implémentez les filtres de manière isolée).

Jason R
la source
Merci! J'ai juste réussi à le faire rapidement dans MATLAB. La cause de la confusion antérieure était que j'avais oublié de multiplier le gain (ugh!) Et donc toutes sortes d'idées ont commencé à se glisser.
anasimtiaz
Si vous ne vous embêtez pas à demander le gain en tant qu'argument de sortie de tf2sos (comme dans mon exemple de code publié), vous n'avez pas besoin de vous soucier de le multiplier à nouveau.
learnvst
9

Il existe en fait deux façons d'implémenter des sections de second ordre: parallèle et série. Dans la version série, les sorties de la section N sont les entrées de la section N + 1. Dans la version parallèle, toutes les sections ont la même entrée (et un seul zéro réel au lieu d'une paire complexe conjuguée de zéros) et la sortie de chaque section est simplement résumée. Les deux méthodes sont liées par l'expansion de fraction partielle de la fonction de transfert de domaine Z. AVERTISSEMENT: c'est un problème numériquement délicat et l'implémentation standard de Matlab "residuez" peut avoir de très grandes erreurs numériques pour les filtres audio typiques qui ont des pôles proches du cercle unitaire.

Hilmar
la source
6

Voici un peu de code de démonstration pour montrer pourquoi il vaut mieux mettre en cascade les sections de 2e ordre.

clc

sr = 44100;
order = 13;

[b,a] = butter(order,1000/(sr/2),'low');
[sos] = tf2sos(b,a);

x = [1; zeros(299,1)]; %impulse


% all in one
Y = filter(b,a,x);

% cascaded biquads
Z = x;
for nn = 1:size(sos,1);
    Z = filter(sos(nn,1:3),sos(nn,4:6), Z );
end


cla; plot(Y, 'k'); hold on; plot(Z,':r'); hold off

Pour le filtre passe-bas donné dans l'exemple ci-dessus, par des ordres d'environ 12 à 13, les erreurs numériques s'accumulent pour donner une réponse impulsionnelle visiblement différente pour la mise en œuvre qui n'utilise pas de biquades en cascade. Selon le filtre, votre kilométrage variera.

COMMANDE = 10

entrez la description de l'image ici

COMMANDE = 13

entrez la description de l'image ici

learnvst
la source
@learvst Corrigez-moi si je me trompe, mais votre code manque les gains. Cela ne devrait-il pas être:[sos gain] = tf2sos(b,a); // Rest of code for nn = 1:size(sos,1); Z = filter(sos(nn,1:3),sos(nn,4:6), Z ); end Z = filter(gain,1,Z);
user915783