Un volontaire pour écrire une bibliothèque ?

Alors, je suis en ce moment sur l'analyse du son, voir mon post dans les projets terminés.
Bien sûr, ça passe par l'inévitable FFT, et il y a vraiment peu de solutions pour faire de la FFT sur un Arduino ou un ESP8266.

Pour l'instant, je suis sur l'ESP, pour des raisons de vitesse et de mémoire, qui sont des paramètres importants pour cette application. On trouve la bibliothèque ArduinoFFT, par Kosme, qui ne me donne pas satisfaction. J'ai du mal à jouer avec les paramètres et je suis limité en bande passante, sans comprendre vraiment pourquoi.

J'ai donc cherché ailleurs et j'ai trouvé un code C qui semble simple et efficace : FFT-C, de RS Huston. Je l'ai porté sur ESP8266, en utilisant la bibliothèque complex (pour 2 multiplications et 2 additions, on doit pouvoir s'en passer et accélérer les calculs) et elle semble assez puissante.

Voici des résultats, en temps de calcul : nombre de points du vecteur en entrée et temps de calcul de la FFT :

4 : 0.404000ms
8 : 0.348000ms
16 : 0.561000ms
32 : 1.275000ms
64 : 2.886000ms
128 : 6.614000ms
256 : 15.018000ms
512 : 33.827000ms
1024 : 75.429000ms
2048 : 166.701000ms
4096 : 365.368000ms

Impossible d'aller au-delà de 4096 points avec mon Wemos D1 mini, mais on peut certainement faire mieux avec un ESP32...

La FFT peut se faire selon deux schémas :

  • soit on veut conserver les données initiales, et on appelle certaines fonctions. On est alors limité à 2048 points puisqu'il faut 2 vecteurs (in et out)
  • soit on ne désire pas conserver les données initiales, on appelle une autre fonction et on peut aller à 4096 points.
    Je pense qu'il faut passer à l'étape suivante, créer une bibliothèque pour rendre ça facile d'utilisation. Pour l'instant, c'est basique : il n'y a que ces deux cas, et aucune fonction autour (pas de fenêtre style Hamming, Bessel, pas de traitement : recherche de maximum, etc).

Qui est volontaire ? (moi je n'y connais rien... et je n'ai pas envie de galérer pour ça)
C'est une saine occupation pour le confinement :sunglasses:

FFT.ino (6.03 KB)

faut vraiment avoir le besoin pour se motiver.. et il ya des tas de codes en C effectivement dispos qui ne sont pas super durs à porter quand on a une architecture 32 bits.... je pense que c'est pour cela qu'on n'en trouve pas bcp, ceux qui en ont besoin et comprennent ce qu'ils font savent où chercher je pense :slight_smile:

Bonsoir

Qui est volontaire ? (moi je n'y connais rien... et je n'ai pas envie de galérer pour ça)
C'est une saine occupation pour le confinement

Prévoir la provision d'aspirine !!!

Perso : je me satistait sur ESP8266 et ESP32 de la librairie de Kosme en jouant un peu avec la fréquence d'échantillonnage et le nombre de points de la FFT (la contrainte sur ce dernier point est fixée par la taille de RAM)
Sur un ESP8266 on peut aller avec cette librairie et l'IDE Arduino jusqu'à une FFT de dimension 2048, ça donne 1024 raies au spectre..... de quoi satisfaire pas mal de besoins...
En compilant pour une carte Lolin32 on passe à 4096 points...

Des tentatives infructueuses de portage il ya une quinzaine d'un code conçu à l'origine pour DSP, des histoires de 'papillons'.... ne me donnent pas envie d'y revenir !! jJe fais avec ce qui a le mérite d'exister !!!

Il existe un algorithme plus simple plus rapide ne travaillant que sur les réels. (DFT ? ou DCT ? )

S'il s'agit de détecter une fréquence bien particulière en non de déterminer le spectre l'algorithme de Goertzel est là (il est OK par exemple pour décoder le DTMF)

Bande passante ? quelle est exactement la limite sur laquelle tu buttes ?

Je cherche à aller aux limites de l'ESP8266, vers 10kHz. J'ai mesuré le temps nécessaire à faire un analogRead : il faut de l'ordre de 80 microsecondes en réglant l'IDE sur 16MHz. Donc, ça fait près de 12 kHz, mais je n'arrive pas à les obtenir avec la bibliothèque de Kosme, pour une raison que je ne m'explique pas.

Donc, ça fait près de 12 kHz, mais je n'arrive pas à les obtenir avec la bibliothèque de Kosme, pour une raison que je ne m'explique pas.

tu n'échantilonnes pas à 12kHz comme tu le voudrais ?
Quelle fréquence souhaites-tu atteindre en haut du spectre ?

Lorsque j'ai utilisé FFT avec des ESP c'était toujours pour un spectre entre 100Hz et 1KHz, je n'ai donc pas buté comme toi sur la limite de vitesse d'échantillonage et le temps de calcul , patr ailleurs c'est la résolution d ela mesure de fréquence qui importaitt donc le nombre de raies.(= taille de la FFT /2)

Je commence à me dire que c'est aussi lié au capteur de son. J'ai un truc bas de gamme (MAX4466) et il commence à faiblir vers 4600Hz. Les fréquences sont bonnes jusque là et après ça devient non linéaire : il indique 4600 Hz au lieu de 5000.

Ou bien c'est Shannon qui m'empêche d'aller trop haut, l'ESP8266 doit être à sa limite de vitesse d'acquisition. Je vais tester avec un ESP32...

Sur la notice des MAX4466 la décroissance de la courbe de réponse en fréquence semble commencer au delà des 10kHz , et là c'est l'amplitude qui décroit progressivement.
réponse.png

Si tu échantillonnes à 10 kHz (valeur limite conseillée dans la librairie de Kosme il ne faut pas s'attendre à un résultat correct quand on approche de 5kHz,(théorème de Shannon) çà commence à se dégrader avant cette limite théorique absolue.

réponse.png

toujours pas volontaire ....

Pour ce qui suit :

Je cherche à aller aux limites de l'ESP8266, vers 10kHz. J'ai mesuré le temps nécessaire à faire un analogRead : il faut de l'ordre de 80 microsecondes en réglant l'IDE sur 16MHz. Donc, ça fait près de 12 kHz, mais je n'arrive pas à les obtenir avec la bibliothèque de Kosme, pour une raison que je ne m'explique pas

En poussant à 160MHz l'ESP8266 (option dans l'IDE, du moins pour la carte D1 Mini) on abaisse bien à 80µs la durée d'un AnalogRead(), j'ai vérifié à l'oscilloscope

On peut dont pousser à 12,5 kHz la cadence d'échantillonage de la FFT

#define SAMPLING_FREQUENCY 12500 //Hz

La FFT arrive bien à mesurer une raie d'amplitude maximale à 6kHz (Shannon est content) avec le signal sonore sinusoîdal à 6k. La librairie est OK, encore faut-il que la routine d'affichage suive !!

Dans la fonction d'affichage, la fréquence de la raie la plus grande n'est pas celle issue de la FFT mais une valeur recalculée à partir du nombre de 'colonnes de l'afficheur' ( on a 128 colonnes pour représenter 6250 Hz -> coefficient MULT)

On retrouve bien nos 6kHz affichés en modifiant le coefficient MULT , (j'ai mis 48)

On est sans doutes aux limites du convertisseur analogique/numérique de l'ESP8266 utilsié sous IDE Arduino.
Pour aller au delà avec un ESP8266 microphone sur bus I2S !!

Oui, je vais essayer avec un ESP32 quand j'aurai du temps. J'ai vu qu'on peut monter à 27 kHz sans problème, ce qui est suffisant pour moi, mais un peu décevant pour cette bête de course...
Il semble qu'en enlevant le code superflu dans la commande adc1_get_raw on puisse aller plus haut...

Je viens de tester l'ESP32 : j'ai obtenu de l'ordre de 9 µs pour un analogRead (boucle sur 10000 mesures), ce qui permettrait de monter à 100 kSps (soit 50 kHz utiles), donc suffisant pour de l'audio.