Auteur Sujet: Free-FIR-Filter-Generator  (Lu 2344 fois)

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Free-FIR-Filter-Generator
« le: septembre 17, 2015, 14:26:14 pm »
Bonjour,

J'ai développé un nouveau programme en java pour générer facilement des filtres FIR (pour l'instant au format .txt seulement).

Vous pouvez le télécharger ici : https://drive.google.com/file/d/0B_qpfrOOECB0c3YwUVRiOHZnaTA/view?usp=sharing

Le programme permet de générer des filtres :

- de type Butterworth (fc à -3dB et pente de 6dB/octave à l'ordre 1) ou Linkwitz-Riley (le carré d'un Butterworth en amplitude dans le domaine fréquentiel soit une fc à -6dB et pente de 12dB/octave à l'ordre 1)
- et de type passe-bas/passe-haut ou passe-bande,
- de longueur souhaitée
- pour une fréquence de sampling de 44100/48000/88200/96000/192000 Hz.
- avec l'application d'un fenêtrage Rectangulaire/Triangulaire/Welch/Hanning/Hamming/Blackman/Nuttall/Blackman-Nuttall/Blackman-Harris/Flat-top.

Le code source du programme (sous licence open source BSD-3 clauses) se trouve sur github sur un dépôt public ici : https://github.com/jeanibarz/FreeFirFilterGenerator.git

Normalement le programme doit fonctionner (si vous avez la possibilité d'exécuter des programmes java, donc que vous avez un Java Runtime Environment). Sinon vous devez en télécharger un pour l'utiliser (google : jre windows !).

Si vous trouvez des bugs ou que vous pensez que je pourrais améliorer certaines choses n'hésitez pas.

Aussi si vous le souhaitez vous pouvez contribuer à l'amélioration du projet étant donné que le dépôt est public...

Pour visualiser le filtre générer vous pouvez l'importer sur HolmImpulse :

- dans l'onglet "measurements", cliquez sur "import/impulse"
- cliquez sur "browse" et indiquez l'emplacement du fichier
- dans la section "File format", choisissez "ASCII text-file"
- dans "Textfile options", indiquez le Samplerate défini pendant la génération du filtre.
« Modifié: septembre 05, 2016, 22:19:37 pm par LeChacal619 »

Francisbr

  • Invité
Re : Free-FIR-Filter-Generator
« Réponse #1 le: septembre 17, 2015, 19:01:07 pm »
Bonjour,

Apparemment il s'agit d'un FIR à phase linéaire.

Un projet pour un FIR à phase minimale ?

Cordialement.

Francis Brooke

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #2 le: septembre 17, 2015, 19:39:51 pm »
Bonjour,

Oui c'est le cas. Quel est l'intérêt d'un filtre a phase minimale ? Je n'ai jamais compris le principe ni l'utilité de ce type de filtre  :refl:
« Modifié: septembre 17, 2015, 20:44:17 pm par LeChacal619 »

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #3 le: septembre 17, 2015, 20:54:17 pm »
Je viens de regarder sur wikipédia, et par définition un filtre FIR ne peut pas être à phase minimale (ou bien j'ai mal compris), puisqu'un filtre est dit à phase minimale s'il est causal. Hors un filtre FIR ne peut être causal puisque pour l'appliquer à un signal il faut faire une convolution et toute convolution d'un signal nécessite de connaître des samples à l'avance (autant que la taille du filtre).

Le seul moyen est de réaliser le filtrage en "analogique", éventuellement en numérique avec un filtre IIR.

La seule chose que je puisse faire c'est donc de réaliser un filtre FIR de même réponse qu'un filtre IIR.... Mais comme en FIR on ne peut pas mémoriser les samples précédents, il faudra probablement un filtre de taille non négligeable du coup il faudrait que je vois quels liens il y a entre taille de filtre / qualité de filtrage / délai. Pour résumé : vous obtiendrez un filtre IIR avec tout les inconvénients d'un filtre FIR (seuls avantages minimes seraient des erreurs de précisions dûes aux erreurs d'arrondies plus faibles : inutile, et l'assurance d'un filtre stable : inutile aussi puisqu'on est en numérique).

Vous êtes sûr de le vouloir ce filtre ?  ;)
« Modifié: septembre 17, 2015, 21:00:51 pm par LeChacal619 »

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #4 le: septembre 17, 2015, 21:21:34 pm »
J'ajouterai (enfin) plusieurs derniers petits détails :

- le générateur de filtre que je propose est à la base dédié pour l'audio (mais si d'autres ont besoin d'avoir un minimum phase pour d'autres domaines : pourquoi pas !). A ce sujet, en général les filtres sont utilisés pour faire du filtrage actif (crossover) et donc des filtres à phase linéaires permettent de combiner les voies entre elles sans interférences destructrices pour peu que les voies sont correctement alignées temporellement. Je vous défie de combiner correctement 2 voies filtrer par phase minimale dès que la pente de coupure devient un peu plus raide que 18dB/octave !

- que si les voies sont correctement alignées entre elles et que leur réponse sur la bande passante utilisée est linéaire, alors leur phase sera linéaire et donc leur somme fera aussi une réponse linéaire sur l'ensemble du spectre, ce qui signifie que les "pseudos" preringing et postringing ne seront pas audibles pour peu que les pentes de coupures ne soient pas exagérément importantes (à 48db/octave je pense qu'ils sont largement inaudibles, en tout cas sur mon système c'est inaudible pour mes oreilles), ni mesurables une fois les voies utilisées de façon combinée (cas normal d'utilisation xD).

- sauf pour la coupure sur le haut du spectre (18-20-22khz) il pourrait y avoir du "preringing". Dans le pire des cas si vous voulez vraiment éviter ce phénomène de "preringing", il existerait une méthode simple : utiliser sur la voie qui reproduit le plus haut du spectre un filtre passe-haut plutôt qu'un filtre passe-bande et utiliser un filtre passe-bas IIR (on trouve sans mal des plugins VST gratuits qui le font très bien comme EasyQ, on peut même en chainer plusieurs à la suite pour augmenter l'ordre de filtrage ;)). Je finirai par dire que pour moi le "preringing" est un mythe : voici le preringing d'un filtrage passe-bas de pente 96dB/octave à 20khz (bien regarder les échelles ;)) :

Filtre FIR à phase linéaire (Linkwitz-Riley), taille 16384, sampling rate 44,1khz, fc = 20000Hz, ordre = 40 (240dB/octave) : https://picasaweb.google.com/lh/photo/HUERQ5ZERcHxHDMeGbC_XdMTjNZETYmyPJy0liipFm0?feat=directlink
Filtre FIR à phase linéaire (Linkwitz-Riley), taille 16384, sampling rate 192khz, fc = 20000Hz, ordre = 40 (240dB/octave) : https://picasaweb.google.com/lh/photo/aVh7xDH56_JN4twXVq6NONMTjNZETYmyPJy0liipFm0?feat=directlink

A -1 ms l'amplitude du preringing est déjà inférieure à -65dB, autrement dit bien en deça du seuil d'audibilité - quand bien même vous entendez jusqu'à 20-22khz, ce qui n'est pas mon cas et je n'ai que 28 ans- même si vous écoutez votre système à 110dB.... (et encore il s'agit ici d'aigus, quand bien même on pourrait écouter un système à 110dB il ne s'agirait certainement pas du niveau sonore des fréquences du haut du spectre, puisqu'en général l'énergie décroît de 3dB/octave sur une musique normale) et je doute que notre oreille ne fasse une différence à cette échelle de temps ! Enfin la pente du filtre est plutôt importante (c'est celle que j'utilise, mais il faut savoir que plus la pente est grande plus le "preringing" est important !).
« Modifié: septembre 17, 2015, 21:55:27 pm par LeChacal619 »

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #5 le: septembre 19, 2015, 16:48:50 pm »
J'ai essayé de trouver des infos pour designer les filtres IIR en FIR. Je n'ai pas réussi à en trouver de convaincantes (toutes faisaient appels à des notions que je ne connais pas comme la transformée de Hilbert etc.), donc j'ai décidé de faire à ma façon :

- j'ai pris la fonction de transfert d'un filtre butterworth sur wikipédia
- j'ai mis le dénominateur au carré pour avoir une coupure à -6dB au lieu de -3dB (pour avoir une réponse de type Linkwitz-Riley)
- puis j'ai calculé par l'intermédiaire de 2 boucles les complexes pour chaque composante dans le domaine de fourrier, et une autre boucle le polynome de butterworth. Il me suffit ensuite de faire une transformée inverse de Fourrier pour obtenir le filtre dans le domaine temporel.

J'ai vérifié le design la pente de coupure me semble bonne, la phase me semble correcte également. Le délai du filtre est relativement faible (de l'ordre de 2-5ms mais ça dépend de la pente, de la fc, et de la fréquence considérée puisque le délai de groupe varie...). Il faut cependant faire attention à la taille du filtre qui doit être suffisante sinon il y aura le "postringing" qui se retrouvera au départ dans le domaine temporel. Pour ça j'ai déterminé expérimentalement une formule pour recommander une taille minimale à un utilisateur (elle est majorée car la formule prédit une taille avec une erreur variable suivant la fréquence et l'ordre choisi, j'ai donc majoré de 20% le résultat).

A priori si on respecte cette taille recommandée le filtre générée serait correct. Je pense qu'il vaut mieux malgré tout vérifier en important le filtre sous HolmImpulse et vérifier dans le domaine temporel en échelle logarithmique qu'il n'y à aucune oscillation visible avant le pic principal (la résolution de visualisation est de -70dB). Si vous voyez une oscillation, vous pouvez essayer d'augmenter la taille du filtre.

Je vais essayer d'implémenter le filtre passe-haut, passe-bande, puis modifier l'interface utilisateur pour permettre à l'utilisateur de choisir le filtre à réaliser. Dans le cas ou l'utilisateur génère un filtre à phase minimale, il faudrait également que je désactive le fenêtrage, car pour le moment la fenêtre est centrale et symétrique, ce qui ne serait pas bon pour fenêtrer le filtre à phase minimale (il faudrait que je fasse une recherche du pic central du filtre dans le domaine temporel, puis que je modifie mon algorithme de génération de fenêtrage pour pouvoir générer des fenêtres excentrées... ce qui est relativement long.

Je vous tiens au courant quand j'aurai implémenté tout ça et réalisé la mise à jour !

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #6 le: septembre 20, 2015, 09:58:59 am »
Quelques nouvelles au sujet du design des filtres à phase minimale :

- Filtre passe-bas :

Aucun souci après quelques minutes / heures de réflexions, j'ai pu implémenter le code et tester la réponse qui me semblait à vue de nez correcte. J'ai souhaité malgré tout valider mon design en faisant une comparaison avec un filtre IIR. Pour cela j'ai mis un plugin EasyQ avec un filtre IIR passe-bas de 12dB/octave avec une fc à -6dB (qui correspond à mon filtre passe-bas d'ordre 1 en Linkwitz-Riley). J'ai fais une mesure en loopback pour obtenir sous HolmImpulse la réponse du filtre IIR de EasyQ, puis je l'ai comparé à mon filtre FIR que j'ai importé également sous HolmImpulse. Voici le graphe de comparaison :

https://picasaweb.google.com/lh/photo/Mm3rqvl5IMnUNvhMip2S5dMTjNZETYmyPJy0liipFm0?feat=directlink

- Filtre passe-haut :

Là je me suis heurté à un gros problème : la réponse en temporel semblait indiquer des artefacts, et je pensais que mon design n'était pas correct (erreurs d'arrondis de calcul numérique ou autres). J'ai donc trituré mon code dans tout les sens pour essayer de voir d'où venait le problème et j'obtenais toujours les mêmes artefacts. Voici un graphe montrant le problème :

https://picasaweb.google.com/lh/photo/keKui9l6VgxtIutyMBxy4tMTjNZETYmyPJy0liipFm0?feat=directlink

Un deuxième graphe sur la réponse impulsionnelle avec une échelle logarithmique et une échelle de temps différente :

https://picasaweb.google.com/lh/photo/B_ZzJb_OatQG4Dqtpet8rdMTjNZETYmyPJy0liipFm0?feat=directlink

Bon... après quelques heures de souffrance, j'ai eu l'idée de regarder la réponse du filtre IIR d'EasyQ (à l'ordre 1) pour voir si mon filtre était correct. Voici une comparaison des 2 filtres :

https://picasaweb.google.com/lh/photo/egfuQhk__vpPUbuY4jf4I9MTjNZETYmyPJy0liipFm0?feat=directlink

La réponse en amplitude/phase et temporelle sont similaires. Donc à priori mon filtre FIR généré serait juste. Il semblerait que ce soit la "phase" apporté par le filtre IIR qui apporte ces oscillations temporelles (modérément faibles à l'ordre 1 comme on peut le constater, mais très importantes dès que l'ordre augmente au dessus de 2-3-4). Le problème n'apparaît plus (ou très peu) si on suréchantillonne énormémement (fs 192khz pour une coupure modérée à 20khz avec un filtre à phase linéaire) :

https://picasaweb.google.com/lh/photo/hIipOLgTSti1fiDBf1L6bdMTjNZETYmyPJy0liipFm0?feat=directlink

Probablement que le fait que le spectre atteigne la fréquence de nyquist pose des problèmes dans l'IFFT et que le signal temporel ne peut pas être correctement reconstitué. Peut-être que cela met en évidence l'intérêt du suréchantillonnage pour obtenir "en pratique" un signal correct après transformée de Fourrier ?
« Modifié: septembre 20, 2015, 10:11:14 am par LeChacal619 »

LeChacal619

  • Hero Member
  • *****
  • Messages: 2004
    • E-mail
Re : Free-FIR-Filter-Generator
« Réponse #7 le: septembre 05, 2016, 22:20:22 pm »
Petite mise à jour du programme et du post initial.