IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

mesurer la fréquence du son reçu par le micro d'un appareil android


Sujet :

Delphi

  1. #21
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par _alx_ Voir le message
    Bonjour,

    Le mathématicien Joseph Fourier, à la fin du 18ème siècle, a réalisé que (presque) tout signal (et (presque) toute fonction mathématique) pouvait être considérée comme la somme d'une infinité de sinusoïdes.
    Cela s'exprime mathématiquement par une intégrale faisant intervenir des nombres complexes, un concept théoriquement très puissant mais qui se prête mal au calcul pratique. C'est la Transformée de Fourier.

    Dans le cas pratique d'un signal échantillonné sur N points (un signal ''discret'' sur lequel on peut faire des calculs), on voit bien qu'on ne pourra pas déterminer plus de N sinusoïdes puisqu'on dispose seulement de N informations sur le signal.
    Ces sinusoïdes sont toutes les sinusoïdes de périodes comprises entre 1 et N, donc de fréquence 2*pi/N à 2*pi.

    On définit alors la transformée de Fourier discrète (DFT) par la fonction obtenue comme étant la valeur moyenne de ces sinusoïdes pondérée par les valeurs du signal. Il y a ici une subtilité, sur le détail de laquelle je passe, due au fait qu'il faut deux nombres pour définir une sinusoïde (une amplitude et une phase), d'où l'utilisation des nombres complexes. On tourne cette difficulté en calculant séparément les parties réelle I et imaginaire Q des ces valeurs complexes, pat les formules suivantes:

    0<=n<=N-1, 0<=k<=N-1 Ik = somme(n=0..N-1){x(n)*cos(2*pi*k*n/N)} et Qk = somme(n=0..N-1){x(n)*sin(2*pi*k*n/N)}

    La phase de la kième fréquence est atan(Qk/Ik) et son amplitude est sqrt(Ik^2 + Qk^2).
    C'est cette dernière formule que vous cherchez.

    Le F dans FFT veut dire rapide (''fast''), cela correspond à l'utilisation d'un algorithme (très) optimisé pour effectuer (beaucoup) plus rapidement le calcul des sommes précédentes, surtout quand N est grand. Inutile si vous êtes patient !

    Bon courage, en espérant vous avoir été utile.
    alx.
    Déjà, merci de vous intéresser à mon problème et pour ces explications très didactiques.
    Merci de bien vouloir excuser l'utilisation de ma part de mauvais termes mathématiques dans la suite.
    Cela confirme ce que j'avais cru comprendre en lisant pas mal de littérature sur le sujet.
    Pour l'amplitude, j'avais bien compris qu'il fallait que je calcule "l'hypoténuse du triangle dont les deux côtés de l'angle droit sont I et Q" si je peux me permettre cette analogie.
    En revanche je n'arrive pas à traduire en code la "formule" que vous m'avez fourni.
    Mon problème de compréhension se trouve au niveau de x(n). Que représente x(n) ? est-ce un complexe ? est ce un entier ?
    Si c'est un complexe, doit-on utiliser sa partie réelle pour I et sa partie imaginaire pour Q ?
    Mon échantillon étant de 4096 octets, avec un "échantillonage" sur 16bits, soit 2 octets.
    J'obtiens donc un tableau de 2048 entiers que je transforme en un tableau de 2048 complexes (on va l'appeler x comme vous utilisez x(n)) avec la partie réelle et la partie imaginaire séparées.
    Si je comprends bien il faudrait que je calcule pour chaque indice de x cette formule en créant deux autres tableaux (I et Q) ?
    pour I ce serait :
    I[0]=(x(0).reel*cos(2*pi*0*n/N)) + (x(1).reel*cos(2*pi*0*n/N)) + ... + (x(n-1).reel*cos(2*pi*0*n/N))
    I[1]=(x(0).reel*cos(2*pi*1*n/N)) + (x(1).reel*cos(2*pi*1*n/N)) + ... + (x(n-1).reel*cos(2*pi*1*n/N))
    ....
    I[k-1]=(x(0).reel*cos(2*pi*(k-1)*n/N)) + (x(1).reel*cos(2*pi*(k-1)*n/N)) + ... + (x(n-1).reel*cos(2*pi*(k-1)*n/N))

    et la même chose pour Q avec la partie imaginaire de x(n) ?

    en ce qui concerne la phase, est ce que ça représente l'espace entre 2 passage par la valeur 0 (ou bien est-ce une demi-phase ?) et à quoi cela peut servir dans l'analyse du spectre audio ?

    Mais je crois aussi avoir compris que ces calculs allaient être beaucoup plus lent que la FFT ?
    Ce serait pour analyser un son en "live", donc le temps de calcul est peut-être rédhibitoire ?

    Merci de me dire si j'ai bien compris le sens de votre message.

  2. #22
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Dans les formules que je vous ai parachutées, x est le vecteur réel des amplitudes (sonores) du signal échantillonné en fonction du temps.
    Le codage va dépendre de l'outil d'acquisition utilisé. Le plus courant est un codage en entiers signés (complément à deux) représentant un signal sonore fluctuant autour de zéro. Cela peut être vérifié en en calculant l'histogramme.

    Les formules pourraient être traduites en un code Delphi comme ci-dessous (mais syntaxe pas testée !), dans lequel les tableaux sont pré-initialisés dans le code appelant.
    J'ai renommé I et Q en Re et Im pour être plus clair.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    uses
      System.Generics.Collections;
     
    procedure SlowFT(x: TArray<smallint>;  //signal réel (par ex. 4096 entiers 16 bits)
      var Re,Im,                           //parties réelles et imaginaires de la TF
      freq,                                //fréquences du signal
      ps: Tarray<Single>);                 //spectre du signal
    var om: extended;
    begin
      var N := Length(x);
      for var k := 0 to N-1 do begin
        Re[k] := 0; Im[k] := 0;
        for var i := 0 to N-1 do begin
          om := 2*pi*k*i/N;
          Re[k] := Re[k] + x[i]*cos(om);
          Im[k] := Im[k] + x[i]*sin(om);
        end;
        Re[k] := Re[k]/N; Im[k] := Im[k]/N;
        ps[k] := Re[k]*Re[k] + Im[k]*Im[k];
        freq[k] := k/N ;
        if (k > N/2) then freq[k] := 1 - freq[k];    //par convention
      end;
    end;
    Notez qu'à cause de la symétrie des sinus et cosinus autour de N/2, il suffit de considérer seulement la partie du spectre (fréquences positives) allant de 0 à N/2 (mais en en doublant la valeur).

    Pour ce qui concerne votre souci de temps réel, je ne crois pas qu'il y ait problème: les fréquences acoustiques sont très inférieures aux vitesses d'horloge des ordinateurs actuels.
    La FFT est nécessaire dans des cas plus exigeants comme le traitement d'images pour lequel les débits sont bien plus importants.
    Et un code analoque au code ci-dessus peut être largement optimisé, par exemple si N est constant au cours de vos expériences, vous pouvez précalculer (sous forme de tableaux) les sinus et cosinus qui sont des coefficients ne dépendant pas du signal d'entrée.

    alx.

  3. #23
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Merci beaucoup !
    C'est à peu près ce que j'avais fait sauf la ligne 18 de votre code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        Re[k] := Re[k]/N; Im[k] := Im[k]/N;
    Comme il y avait juste écrit Ik = somme(n=0..N-1){x(n)*cos(2*pi*k*n/N)} je n'avais pas compris qu'il fallait diviser la somme de nouveau par N, comme pour calculer la moyenne ?
    Pour ma gouverne personnelle, comment déduire de votre notation qu'il fallait diviser par N car je ne connais pas très bien les notations mathématiques ?

    Merci d'avance pour cette précision, je teste ce code dès que possible.

  4. #24
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par navyg Voir le message
    Merci d'avance pour cette précision, je teste ce code dès que possible.
    La division par N est là pour être conforme à la définition et, surtout, pour rester homogène dans les unités physiques du signal: puissance sonore en W/m^2 (l'intensité que vous mesurez) et puissance spectrale en W/Hz (celle que vous voulez calculer).
    Mais ici, ça n'a pas beaucoup d'importance puisque votre signal n'est pas étalonné en absolu. Vous pouvez sans doute rester en valeurs relatives.
    alx.

  5. #25
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Merci pour la précision. J'allais juste m'attaquer à la modif !
    J'aurai peut-être une autre question à vous poser ensuite. Pourrais-je me permettre ?

  6. #26
    Membre actif
    Homme Profil pro
    libre
    Inscrit en
    Juin 2019
    Messages
    205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : libre

    Informations forums :
    Inscription : Juin 2019
    Messages : 205
    Points : 292
    Points
    292
    Par défaut
    Tu peux jeter un coup d'oeil sur les codes suivants:

    lisez premièrement l'aide accompagné
    https://www.unilim.fr/pages_perso/je...th/dmat086.zip

    un tuto bien détaillé en c++

    https://www.codeproject.com/Articles...-audio-signals

  7. #27
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par _alx_ Voir le message
    Bonjour,

    Dans les formules que je vous ai parachutées, x est le vecteur réel des amplitudes (sonores) du signal échantillonné en fonction du temps.
    Le codage va dépendre de l'outil d'acquisition utilisé. Le plus courant est un codage en entiers signés (complément à deux) représentant un signal sonore fluctuant autour de zéro. Cela peut être vérifié en en calculant l'histogramme.

    Les formules pourraient être traduites en un code Delphi comme ci-dessous (mais syntaxe pas testée !), dans lequel les tableaux sont pré-initialisés dans le code appelant.
    J'ai renommé I et Q en Re et Im pour être plus clair.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    uses
      System.Generics.Collections;
     
    procedure SlowFT(x: TArray<smallint>;  //signal réel (par ex. 4096 entiers 16 bits)
      var Re,Im,                           //parties réelles et imaginaires de la TF
      freq,                                //fréquences du signal
      ps: Tarray<Single>);                 //spectre du signal
    var om: extended;
    begin
      var N := Length(x);
      for var k := 0 to N-1 do begin
        Re[k] := 0; Im[k] := 0;
        for var i := 0 to N-1 do begin
          om := 2*pi*k*i/N;
          Re[k] := Re[k] + x[i]*cos(om);
          Im[k] := Im[k] + x[i]*sin(om);
        end;
        Re[k] := Re[k]/N; Im[k] := Im[k]/N;
        ps[k] := Re[k]*Re[k] + Im[k]*Im[k];
        freq[k] := k/N ;
        if (k > N/2) then freq[k] := 1 - freq[k];    //par convention
      end;
    end;
    Notez qu'à cause de la symétrie des sinus et cosinus autour de N/2, il suffit de considérer seulement la partie du spectre (fréquences positives) allant de 0 à N/2 (mais en en doublant la valeur).

    Pour ce qui concerne votre souci de temps réel, je ne crois pas qu'il y ait problème: les fréquences acoustiques sont très inférieures aux vitesses d'horloge des ordinateurs actuels.
    La FFT est nécessaire dans des cas plus exigeants comme le traitement d'images pour lequel les débits sont bien plus importants.
    Et un code analoque au code ci-dessus peut être largement optimisé, par exemple si N est constant au cours de vos expériences, vous pouvez précalculer (sous forme de tableaux) les sinus et cosinus qui sont des coefficients ne dépendant pas du signal d'entrée.

    alx.
    Désolé d'être un peu neuneu ;o)
    Que représente la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        freq[k] := k/N ;
        if (k > N/2) then freq[k] := 1 - freq[k];    //par convention
    Cela va toujours donner un nombre entre 0 et 0.5 ?
    Est ce l'objet de la phrase suivante... dont je n'ai pas compris toute la portée ?
    Sinon, les données résultats de ps (importés dans excel pour gagner du temps) me donne une courbe complètement symétrique depuis le point milieu, qui ne correspond pas vraiment à la note que j'ai enregistré.
    En effet, j'ai joué un sol3 qui a normalement une fréquence de 392Hz.
    L'échantillonage étant réglé à 48000Hz, les résultats sur un échantillon de 4096 octets en PCM 16 bits, soit 2048 valeurs sur 2 octets devraient indiquer un pic vers le 17ème élément du tableau (392*2048/48000=16.72533333) ... si j'ai bien compris ! or la courbe des valeurs de ps donne une image de ce genre :Nom : courbe_ps.jpg
Affichages : 197
Taille : 51,5 Ko

    J'ai dû merder quelque part ... sur les valeurs en entrée peut-être ?
    J'ai un tableau de 4096 bytes que je combine pour former des valeurs sur 16 bytes. Je prend le premier élément du tableau que je mets en poids fort et je lui ajoute le deuxiième él"ments du tableau et ainsi de suite 3 et 4, 5 et 6, etc ..
    C'est peut-être là que je merde ...
    Si quelqu'un a des infos à ce sujet je suis preneur.

  8. #28
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par wheel Voir le message
    Tu peux jeter un coup d'oeil sur les codes suivants:

    lisez premièrement l'aide accompagné
    https://www.unilim.fr/pages_perso/je...th/dmat086.zip

    un tuto bien détaillé en c++

    https://www.codeproject.com/Articles...-audio-signals
    Merci beaucoup pour ces liens ! C'est quasiment exactement ce que je cherche depuis plusieurs semaines !
    Même si pour le premier tout est en anglais, langue que je maîtrise ... pas du tout et que pour le deuxième, je ne comprends pas grand chose au C, je te remercie car cela va sûrement m'aider.

    Encore pas mal de choses à lire et à apprendre.

  9. #29
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Bon, j'ai fouillé un peu et il semblerait que les données en PCM 16 sont recueillies sous forme d'octets.
    Mais là où est l'astuce, c'est que le format du 16 bits serait en native-endian, et en l'occurence en little-endian (l'octet de poids fort en deuxième)
    Or je reconstituais mes groupes de deux octets en big-endian (octet de poids fort en premier)

    Je faisais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    asi[i]:=smallint(((pb^[(i*2)]) shl 8) or pb^[(i*2)+1]);
    alors qu'il faut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    asi[i]:=smallint(((pb^[(i*2)+1]) shl 8) or pb^[(i*2)]);
    Donc j'ai corrigé et j'avais des résultats encore plus bizarre, mais en regardant bien, au bout d'un très long moment, je me suis aperçu que m'étais trompé dans le codage et j'avais mis le +1 en dehors des crochets ! Donc tous les octets à 0 0 devenaient 1 0 donc devenaient 256 .... grrr
    Deux heures de plus à chercher ... et puis une fois qu'on est passé dessus ...
    Bon, toujours pour cette même note de sol3 (392Hz) voilà le graphique :
    Nom : courbe_ps2.jpg
Affichages : 276
Taille : 134,0 Ko
    Et donc le pic n'est pas là où il devrait être ...
    J'avance, petitement mais j'avance.
    je crois que je vais refaire mes échantillons.

  10. #30
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Bon j'ai refait un échantillon de la2 220Hz et ça paraît un peu mieux, mais on dirait qu'un schéma se répète.
    Nom : courbe_ps-la.jpg
Affichages : 184
Taille : 79,4 Ko
    Si quelqu'un peut m'expliquer pourquoi ? J'ai lu un truc sur les harmoniques, mais ça n'a peut-être rien à voir ?
    Comme c'est pour un accordeur de guitare, je vais travailler sur des fréquences allant du Mi2 au Mi4, c'est à dire de 164.81Hz à 659.26Hz, donc je n'ai pas besoin des plus hautes fréquences.
    Je peux me contenter de chercher le maximum dans une plage qui va du rang 5 au rang 90 par exemple.
    Mais même comme ça, le maximum se trouve au point 32, soit une fréquence de 750Hz au lieu de 220 Hz attendu...
    Peut-être faut-il que je travaille sur un échantillon plus important ou que je calibre le micro de mon téléphone ?
    Encore du travail en perspective, mais je suis content du travail accompli.
    Bon allez au lit !

  11. #31
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par navyg Voir le message
    alors qu'il faut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    asi[i]:=smallint(((pb^[(i*2)+1]) shl 8) or pb^[(i*2)]);
    plus simplement, il y a les fonctions Lo() et Hi() pour adresser les octets dans un mot de 16 bits
    et encore plus simplement la fonction Swap du langage Pascal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     for i := 0 to N-1 do asi[i] := System.Swap(asi[i])
    Citation Envoyé par navyg Voir le message
    Bon, toujours pour cette même note de sol3 (392Hz) voilà le graphique :
    Nom : courbe_ps2.jpg
Affichages : 276
Taille : 134,0 Ko
    .
    Comme je l'ai indiqué auparavant, le spectre (ou la TF) d'un signal réel est symétrique en miroir par rapport à la fréquence 0. Il suffit donc de considérer uniquement la moitié de ce spectre (entre les fréquences 0 et N/2). Le reste se trouve entre les fréquences N/2+1 et N-1, une autre manière d'écrire les fréquences "négatives" -N/2+1 à -1.
    Avec la convention de signe utilisée dans l'exemple de code, le spectre aux fréquences positives se trouve dans la moitié droite (abscisses 1024 à 2048).
    Le pic semble se trouver à 1091, soit 1091 - 1024 = 67 en réalité.
    Comme vous avez numérisé 2048 points à 48000 Hz, cela donne une fréquence de 48000*67/2048 = 1570 très proche de 4 fois 392

    Etes-vous sur d'avoir enregistré le bon sol ?

  12. #32
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par _alx_ Voir le message
    plus simplement, il y a les fonctions Lo() et Hi() pour adresser les octets dans un mot de 16 bits
    et encore plus simplement la fonction Swap du langage Pascal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     for i := 0 to N-1 do asi[i] := System.Swap(asi[i])


    Comme je l'ai indiqué auparavant, le spectre (ou la TF) d'un signal réel est symétrique en miroir par rapport à la fréquence 0. Il suffit donc de considérer uniquement la moitié de ce spectre (entre les fréquences 0 et N/2). Le reste se trouve entre les fréquences N/2+1 et N-1, une autre manière d'écrire les fréquences "négatives" -N/2+1 à -1.
    Avec la convention de signe utilisée dans l'exemple de code, le spectre aux fréquences positives se trouve dans la moitié droite (abscisses 1024 à 2048).
    Le pic semble se trouver à 1091, soit 1091 - 1024 = 67 en réalité.
    Comme vous avez numérisé 2048 points à 48000 Hz, cela donne une fréquence de 48000*67/2048 = 1570 très proche de 4 fois 392

    Etes-vous sur d'avoir enregistré le bon sol ?
    Pour Hi, Lo et Swap, il faut déjà travailler sur des entiers 16 bits. Là je constitue un entier 16 bits à partir de 2 octets consécutifs dans un tableau de bytes. Et selon les conventions des différents systèmes, cela peut être little endian ou big endian. Bien entendu j'avais faux au départ ;o)
    Mais je ne connaissais pas swap ! En fait, pour beaucoup de choses, j'en suis resté au turbo-pascal de l'amstrad 6128 en 1986, quand je faisais aussi un peu d'assembleur pour processeur 8bits Z80. Cette fonction ne devait pas exister ;o)

    Pour le sol, sur un autre accordeur que j'ai le sol d'une guitare normale (3eme corde) est noté Sol3, ce qui correspond il me semble à 392HZ. Effectivement le sol5 est à 1567.98 Hz selon les références que j'ai trouvées..
    Je vais faire des échantillons dans de bonnes conditions car à 2h du matin si j'avais fait sonner fort, j'aurai entendu parler du pays

  13. #33
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    @_alx_
    J'ai essayé plusieurs algorithmes de fft, et aucun ne donne les mêmes résultats avec les mêmes données en entrée !!
    Notamment l'échelle de sortie n'est pas du tout la même.
    Certaines courbes se ressemblent beaucoup mais il y a toujours quelques différences.
    C'est à se poser des questions.
    Finalement, il semblerait que la méthode qui prête le moins à controverse soit ta méthode "slow fft" car il y a application pure et dure de la formule.

    A ce propos, juste une demande de précision, pour la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps[k] := Re[k]*Re[k] + Im[k]*Im[k];
    , il s'agit bien du calcul de l'amplitude tel que vous l'avez décrit dans votre message initial,
    La phase de la kième fréquence est atan(Qk/Ik) et son amplitude est sqrt(Ik^2 + Qk^2).
    C'est cette dernière formule que vous cherchez.
    il faudrait calculer la racine carrée de Re[k]*Re[k] + Im[k]*Im[k] ? Merc de me dire si j'ai raison de corriger.

    Si j'ai bien compris votre précédent message, la plage significative serait la plage de rang 1024 à 2047 ?
    Et dans cette plage, les seules fréquences qui m'intéressent seraient celles comprises entre 130Hz et 2093hz, du do2 au do6 en gros, soit entre les rangs 1024+6 et 1024+90 environ.
    Le do6 à 2093Hz est déjà très aigu si je ne me trompe pas.
    J'ai donc limité la boucle de 1024 à 1024+90 et en comparant les méthodes entre elles, c'est celle qui est la plus rapide !
    Cela étant, même avec des échantillons que j'essaye de capter au mieux, je n'arrive pas aux résultats escomptés ???
    Merci de me dire si j'ai bien compris afin que je continue dans cette voie.

  14. #34
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Bonjour,
    1) Comprendre le signal:
    Le signal sonore qui est émis par la vibration d'une corde est constitué d'une multitudes de fréquences différentes (appelées harmoniques) qui ont chacune une amplitude différente. Les fréquences des harmoniques sont des multiples de la fréquences fondamentale qu'on cherche à mesurer.
    Au moment ou l'on pince la corde, la fréquence fondamentale se distinct des autres par son amplitude qui dominent puis avec le temps, celle-ci diminue pour arriver au même niveau que les harmoniques et même passer en dessous.
    Il suffit d'utiliser une pédale d'octaver pour s'en rendre compte, on dit que le son "décroche" mais en fait ce sont les harmoniques qui dominent et l'octaver se perd.

    2) Principe de mesure:
    Donc pour simplifier la recherche de fréquence, il faut déjà commencer par éliminer celle dont on ne veut pas faire la mesure, c'est à dire qu'il faut filtrer le signal en éliminant les fréquences abérantes.
    Je pense qu'il doit exister des algorithmes autre que les FFT pour effectuer cette tâches.
    Ca, c'est la première étape, ça va "nettoyer" et préparer le signal.

    - Mesure élémentaire: Ensuite un moyen le plus simple pour calculer la fréquence est de déterminer les points les plus haut en fixant un seuil mobile calculé sur une moyenne glissante.
    - Mesure complexe: il faut un mécanisme qui va extraire la fréquence fondamentale en la sélectionnant par son amplitude et c'est là qu'interviennent les FFT.

    3) pour aller plus loin
    Pour réaliser un accordeur sophistiqué, il faudrait mémoriser la première fréquence trouvée et continuer à la suivre même si son amplitude passe en dessous des autres fréquences et abandonner la tache lorsque l'enveloppe du signal augmente brutalement ce qui signifie qu'on a gratté une nouvelle corde.

    Bon courage, c'est un sujet difficile mais passionnant.

  15. #35
    Membre actif
    Homme Profil pro
    libre
    Inscrit en
    Juin 2019
    Messages
    205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : libre

    Informations forums :
    Inscription : Juin 2019
    Messages : 205
    Points : 292
    Points
    292
    Par défaut
    J'ai essayé plusieurs algorithmes de fft, et aucun ne donne les mêmes résultats avec les mêmes données en entrée !!
    D'abord il faut faire des tests dans des conditions idéales : lecture constante, pas d'harmonies pour savoir si votre algo fonctionne correctement et si la lecture du fichier s'est bien déroulée .. regarder dans le fichier joint contenant un fichier audio avec deux tonalités 440hz et 2000hz, 16 bits mono, échantillonnage: 48000.

    Après l'analyse par le fft les deux piques se trouvent dans les positions 20 et 86 dans le ficher Excel ..
    L'indice dans l'Excel commence par 1 il faut le décrémenter pour faire le calcul exacte.
    1) 19 * 48000 / 2048 = 445,31 hz
    2) 85 * 48000 / 2048 = 1992,18 hz



    Le pic semble se trouver à 1091, soit 1091 - 1024 = 67 en réalité.
    Si j'ai bien compris et si les deux parties sont en miroir le bon calcul serait :
    2048 - 1091 = 957
    Fichiers attachés Fichiers attachés

  16. #36
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    @Franckcl
    Merci beaucoup de vous intéresser à mes "recherches".
    Autant lorsque je me suis dis "je vais me programmer un accordeur" je pensais que ça serait tout simple, autant quelques semaines plus tard je prend conscience que ce serait tout sauf simple !
    Mais ce n'est pas pour ça que je vais lâcher l'affaire.
    Je te remercie donc pour ces précisions.
    Je m'étais bien rendu compte qu'il fallait des conditions d'enregistrement correctes ou à tout le moins filtrer le résultat car en fonction de la façon dont je capte le son la courbe est vraiment différente avec le même son théorique.
    Je vais donc m'attaquer à ce nouveau problème ;o)

    @wheel
    Merci pour ces explications et ce fichier qui va me permettre de vérifier et "calibrer" mon algorithme.
    Je vais vite voir si ce sont mes prises de son qui sont trop mauvaises (ce que je pense) et nécessitent un filtrage (encore un chantier ;o) ou bien si c'est ma programmation qui est erronée
    (fort possible aussi !)

    Merci encore à vous pour toutes ces informations qui confirment que la tâche est beaucoup plus complexe que je ne le pensais, mais c'est ce qui fait la passion d'un retraité avec du temps en hiver.

    Mais je vais mettre en pause quelques heures (jours ?) car la famille arrive pour les fêtes et il va falloir que je troque mon ordinateur contre le tablier de cuisine.
    Déjà cet après-midi c'est préparation des terrines de foie gras et du confit .... quelques canards attendent de se faire tailler en pièce
    Une corvée ... très plaisante aussi

    Passez tous de bonnes fêtes.

  17. #37
    Membre du Club

    Profil pro
    senior scientist
    Inscrit en
    Mai 2003
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : senior scientist

    Informations forums :
    Inscription : Mai 2003
    Messages : 79
    Points : 67
    Points
    67
    Billets dans le blog
    1
    Par défaut
    Juste avant la décollation des canards

    Citation Envoyé par navyg Voir le message
    A ce propos, juste une demande de précision, pour la ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps[k] := Re[k]*Re[k] + Im[k]*Im[k];
    , il s'agit bien du calcul de l'amplitude tel que vous l'avez décrit dans votre message initial, il faudrait calculer la racine carrée de Re[k]*Re[k] + Im[k]*Im[k] ? Merc de me dire si j'ai raison de corriger.
    .
    sqrt(Re*Re+Im*Im) est l'amplitude de la Transformée de Fourier proportionnelle à l'intensité signal. Son carré est l'amplitude de son spectre, homogène à une puissance.

    J'ai appliqué le code "SlowFT" à l'exemple Test.wav (mille excuses pour la coquille de la dernière ligne; il fallait lire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (k > N/2) then freq[k] := freq[k] - 1;
    On retrouve bien les deux fréquences 0.009 (435 Hz) et 0.04 (1920 Hz) et leur réplique aux fréquences négatives:
    Nom : test.png
Affichages : 139
Taille : 117,6 Ko

    Joyeux Noël

  18. #38
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Bon les agapes n'ont pas pris fin mais ça se calme.
    Joyeux Noël à tous.

    Alors il y a un peu de nouveau. En captant le son émis par le générateur de fréquence, en 4096, ça me donne pour chaque son qui m'intéresse une courbe assez intéressante et en lecture "directe", c'est à dire qu'il ne faut pas aller chercher les points à partir de 1024. Pourquoi ces différences ? Mystère ...
    En effet, sur un la 220Hz, voilà ce que me donne le spectre :Nom : coube_la2_220_complet.JPG
Affichages : 122
Taille : 32,6 Ko, et si on zoome sur les 100 premières valeurs on obtiensNom : coube_la2_220_100t.JPG
Affichages : 119
Taille : 74,6 Ko
    On voit bien que la dominante est l'indice 9, ce qui correspond à 9*48000/2048=210.9375.
    Mais l'indice 10 est aussi bien pourvu avec la fréquence 234.375
    Le La2 220Hz est compris entre les deux, donc je me suis dis que ça devait être une interpolation en fonction de l'amplitude de l'axe Y, mais ça ne me donne pas vraiment 220.
    J'ai essayé de faire des moyennes, des pondérations en fonctions de Y, etc ... et j'ai même essayé en prenant aussi l'amplitude de l'indice 8 de faire une interpolation quadratique avec la formule suivante :
    p=((A[imax-1] - A[imax+1]) / (A[imax-1] - 2A[imax] + A[imax+1])) / 2
    où en l'occurence imax est l'indice 9, les amplitudes sont :
    A[8]=34506.0156
    A[9]=454379.6250
    A[10]=188243.1406
    et j'ai un résultat pour p qui est de 0.112051649
    p est l'écart entre 9 et la position théorique de 220Hz, donc je fais (9+p)=9.112051649, ce qui me donne une fréquence calculée de 213.5637105 pour 220 attendu ...
    Il faudrait que je trouve p=0.38667, ce qui fait une belle différence.

    Est ce que j'ai merdé quelque part ? est ce que la valeur trop faible de A[8] pollue le calcul ?

    Je me suis dis qu'en prenant un échantillon double (8196 octets soit une série de 4096 entiers), j'aurai une meilleure précision, mais je me heurte alors, même avec des conditions d'enregistrement maitrisées au mieux avec une courbe complètement différente, plus proche de celles de mes messages précédents.
    Je m'étais dit que finalement il serait plus simple de traiter une courbe simple .. pas du tout du tout ;o)=

    Merci de vos avis éclairés

  19. #39
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par franckcl Voir le message
    Bonjour,

    - Mesure élémentaire: Ensuite un moyen le plus simple pour calculer la fréquence est de déterminer les points les plus haut en fixant un seuil mobile calculé sur une moyenne glissante.
    - Mesure complexe: il faut un mécanisme qui va extraire la fréquence fondamentale en la sélectionnant par son amplitude et c'est là qu'interviennent les FFT.
    Pour la mesure complexe, j'ai compris qu'il fallait le faire sur les tableaux issus de la fft
    Pour ce qui est de la mesure élémentaire, c'est sur quelles données qu'il faut travailler. Je n'ai toujours pas compris à quoi correspondaient les valeurs que je recueille sous forme de 2048 entiers signés, qui me servent à alimenter le tableau de complexes en entrée de la fft.
    Si je les utilise directement pour faire une courbe, ça me donne quelque chose comme ça pour le La2 220HzNom : courbe_entiers_La2_220.JPG
Affichages : 123
Taille : 61,7 Ko.
    Mais qu'en faire sinon une transformée de Fourier ?

    Si vous avez des infos là-dessus et que vous pouvez me préciser comment calculer le seuil mobile et la moyenne glissante, merci beaucoup par avance.

  20. #40
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Bon alors je me suis dit qu'il fallait que je comprenne.
    Apparemment les données issues du buffer donnent un signal qui évolue dans le temps, ce qui explique cette répétition de schéma.
    Sur la génération d'un si3, j'obtiens une sinusoïde quasiment parfaite et sans pics secondaires, très facile à utiliser.
    Et la durée entre deux pics représente la période. Et la fréquence est égale à 1/période divisée par le samplerate.
    Tiens tiens voilà donc une méthode pour déduire directement la fréquence sans faire une transformée de Fourier.
    Mais il faut faire du ménage, car même sur une courbe issue d'un générateur de fréquence avec une seule fréquence, il peut y avoir des pics secondaires qu'il faut éliminer.
    Et bien avec un peu de travail sur les données pour éliminer tout ce qui est "parasite", j'arrive à un résultat bien plus précis qu'avec la transformée.

    J'ai encore quelques scories à traiter, mais c'est prometteur et rapide.

    Il me reste aussi à voir si je peux faire ce type de traitement sur une courbe issue de l'écoute d'une corde de guitare pincée à vide.

    J'apprends beaucoup et j'avance.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Niveau du son enregistré par le micro
    Par Nayl.VBcoder dans le forum VB.NET
    Réponses: 5
    Dernier message: 09/09/2016, 10h18
  2. Ouvrir/afficher un fichier avec son logiciel par défaut
    Par Alain P. dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 20/06/2009, 18h47
  3. Réponses: 6
    Dernier message: 09/04/2007, 16h52
  4. Modifier un son appelé par Action Script
    Par Imperator34 dans le forum Flash
    Réponses: 3
    Dernier message: 26/10/2006, 05h46
  5. [Sécurité] connexion sur son compte par un lien
    Par Zen_Fou dans le forum Langage
    Réponses: 6
    Dernier message: 07/04/2006, 10h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo