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. #1
    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 mesurer la fréquence du son reçu par le micro d'un appareil android
    Bonjour,
    Je donne ma langue au chat ...
    Dans un but purement pédagogique pour moi (mais aussi pour me faire un acccordeur de guitare sans pub), j'essaye depuis plusieurs jours de mesurer la fréquence du son reçu par le micro d'un appareil android (mon téléphone en l'occurence).
    Après avoir essuyé de multiples refus pour la demande d'autorisation du micro faites en bonne et due forme, j'ai trouvé qu'il fallait d'abord cocher la case "Enregistrer du son" dans les permissions d'utilisation des options du projet. Il y a peut-être une autre astuce mais j'ai réussi de cette manière.
    Franchement ces autorisations android c'est pénible. Je ne dis pas que ce n'est pas sécurisant, mais ça serait plus simple si on pouvait simplement coder une instruction du genre : Form1.Android.Permission.RECORD_AUDIO:=true;
    Mais je dois être vieux jeu, il vaut mieux utiliser des instructions super-compliquées qui change selon les versions de delphi, donc en D11, j'ai fait un truc qui me permet relativement simplement (euphémisme) d'énumérer les autorisations dont j'ai besoin sans refaire tout à chaque fois, donc, ça ressemble à ça :
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
    const
    	// tableau des permissions et des messages associés
       perms: array[0..3, 0..2] of string=
          (('android.permission.RECORD_AUDIO',            'Micro',                'L''application doit pouvoir accéder au Micro'),
           ('android.permission.CAMERA',                  'Caméra',               'L''application doit pouvoir accéder à la Caméra'),
           ('android.permission.READ_EXTERNAL_STORAGE',   'Lire les Fichiers',    'L''application doit pouvoir Lire les fichiers'),
           ('android.permission.WRITE_EXTERNAL_STORAGE',  'Ecrire les Fichiers',  'L''application doit pouvoir Ecrire les fichiers')
          );
     
    implementation
     
    {$IFDEF ANDROID}
    // fonction pour retrouver le rang d'une autorisation dans le tableau perms
    function trouveRgPerm(s: string): integer;
    begin
    result:=-1;
    for var i:=0 to high(perms) do
       begin
       if s=perms[i, 0] then
          begin
          result:=i;
          exit;
          end;
       end;
    end;
     
    procedure TForm1.PermissionRequestResult (Sender: TObject;
                                              const APermissions: TClassicStringDynArray;
                                              const AGrantResults: TClassicPermissionStatusDynArray);
    var
       ps, resultmsg: string;
       resultat: boolean;
    const
       aps: array[0..2] of string = ('Accordée', 'Refusée', 'Refusée de manière permanente');
    begin
    // examen des résultats des demandes d'autorisation
    resultmsg:='';
    resultat:=true;
    for var i:=0 to length(AgrantResults)-1 do
       begin
       ps:=aps[ord(AgrantResults[i])];
       if ord(AgrantResults[i])>0 then
          begin
          // stockage des résultats dans un string
          resultmsg:=resultmsg+'La permission '+perms[trouveRgPerm(APermissions[i]), 1] +
                      ' a été '+ ps + SLineBreak + SLineBreak;
          resultat:=false;
          end;
       end;
    // s'il y a eu des refus alors afichage des résultats
    if not resultat then
       showmessage(resultmsg);
    end;
     
    procedure TForm1.DisplayRationale (Sender: TObject;
                                       const APermissions: TClassicStringDynArray;
                                       const APostRationaleProc: TProc);
    var
       RationaleMsg: string;
     
    begin
    // si des autorisations ne sont pas accordées rappel des besoins
    RationaleMsg:='';
    for var i:=0 to High(APermissions) do
       begin
       RationaleMsg:=RationaleMsg + perms[trouveRgPerm(APermissions[i]), 2] + SLineBreak + SLineBreak;
       end;
     
    TDialogService.ShowMessage(RationaleMsg,
          procedure(const AResult: TModalResult)
          begin
          APostRationaleProc;
          end)
    end;
    {$ENDIF}
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
    {$IFDEF ANDROID}
    // définition du nombre de permission à demander
    const nbPerms=3;
    // définir la taille du tableau des permissions demandées
    setlength(aPermsSel, nbperms);
    // on a besoin des permissions de rang 0, 2 et 3 dans le tableau aperms
    aPermsSel:=[0, 2, 3];
    // définir la taille du tableau des constantes des permissions à demander
    setlength(aperms, nbperms);
    // remplissage du tableau des constantes android des permissions demandées
    For var i:=0 to length(aperms)-1 do
       begin
       aperms[i]:=perms[aPermsSel[i],0];
       end;
    // demande des permissions
    PermissionsService.RequestPermissions(
       aperms,
       PermissionRequestResult,
       DisplayRationale);
    {$ENDIF}
     
    // autres instructions dans formcreate à la suite ...
    end;
    Donc pour cette partie c'est bon.
    Ensuite, j'ai trouvé qu'il fallait définir tout un tas de paramètres pour recueillir un tableau de byte dont il faut définir la taille en puissance de 2 (pour la suite) avec une taille minimum définie par TJAudioRecord.JavaClass.getMinBufferSize(SampleRate, ChannelConfig, AudioFormat), ce qui donne en gros le code suivant
    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
     
    // nbsr est un numberbox qui définit la fréquence d'échantillonage, en l'occurence 48000
    SampleRate:=round(nbsr.value);
    ChannelConfig:=TJAudioFormat.JavaClass.CHANNEL_IN_MONO;
    AudioFormat:=TJAudioFormat.JavaClass.ENCODING_PCM_16BIT;
    MinBufferSize:=TJAudioRecord.JavaClass.getMinBufferSize(SampleRate, ChannelConfig, AudioFormat);
    // affichage de la taille minimale du buffer
    lmbs.Text:=minbuffersize.ToString;
    // la taille du buffer est définie dans le numberbox nb1, en l'occurence 4096
    BufferSize:=round(nb1.value);
    if BufferSize<MinBufferSize then
       BufferSize:=MinBufferSize;
    Buffer:=TJavaArray<Byte>.Create(BufferSize);
    Recorder:=TJAudioRecord.JavaClass.init(TJMediaRecorder_AudioSource.JavaClass.MIC, SampleRate, ChannelConfig, AudioFormat, BufferSize);
    Recorder.startRecording;
    Recorder.read(Buffer, 0, BufferSize);
    Et c'est à partir de là que ça se gâte ... car pour débuguer sous android c'est coton !
    L'attente de réponse du téléphone est tellement longue qu'il est impossible de suivre l'exécution pas par pas.
    Donc il faut retracer les valeurs, notamment de ce buffer, dans des TMemo .
    Je vois donc que je recueille des valeurs, mais comment les traiter ?
    J'ai lu beaucoup de théorie sur les transformées de Fourier discrète qui permettrait de transformer ces valeurs en fréquence.
    J'ai cherché sur internet des exemples de code, mais aucun exemple ne va jusqu'à calculer la fréquence qui ressort de l'échantillon.
    J'ai même essayé de traduire en delphi deux fichiers de code java censés retourner la fréquence en fonction des valeurs du buffer, mais quelles que soient les valeurs obtenues dans le buffer j'obtiens toujours le même résultat donc j'ai dû louper quelque chose.

    Donc, je lance une bouteille à la mer.
    Est-ce que quelqu'un a une solution en delphi avec le mode d'emploi de(s) unités ?

    J'ai essayé de convertir en delphi les unités java FrequencyCalculator.java et RealDoubleFFT.java récupérées sur un projet en java sur GitHub https://github.com/BINETsimon/Accord...io/calculators mais je ne sais pas si ma traduction est correcte car je ne connais ni java, ni C et la lecture de ces unités m'a vraiment dégoûté de ces langages qui restent pour moi beaucoup trop obscurs.
    Les unités delphi résultantes ne donnent pas le résultat espéré.
    Je ne sais pas si je peux joindre ces unités car il y a pas mal de code.

    Merci de me dire si je dois mettre en ligne ces unités et merci d'avance pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour,

    pourquoi ne pas essayer la librairie Bass ?

    Elle est free (mais in english), sait parler en Delphi, et a un forum sympathique.

    Bon, son moteur de recherche n'est pas fantastique, mais en fouinant un peu, j'y ai trouvé ça, qui pourrait t'intéresser :
    https://www.un4seen.com/forum/?topic=4744.0
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  3. #3
    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
    Bonjour,
    Merci. Je ne connais pas du tout et mon anglais est très ... comment dire ... mauvais !
    Mais je vais aller voir ;o)

  4. #4
    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 ... Je n'y comprends rien du tout et je ne vois pas comment on peut utiliser ce qui ressemble à une usine à gaz ...
    Merci quand même ;o)

  5. #5
    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 Jipété Voir le message
    Bonjour,
    ...

    Bon, son moteur de recherche n'est pas fantastique, mais en fouinant un peu, j'y ai trouvé ça, qui pourrait t'intéresser :
    https://www.un4seen.com/forum/?topic=4744.0
    En revanche, les échanges du topic cité m'ont peut-être mis sur la voie !
    Je ne manquerai pas de vous dire la suite de mes recherches !

  6. #6
    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 pour l'instant je ne suis pas arrivé à grand chose, mais ce thème n'a pas l'air d'intéresser grand monde.
    Je continue quand même.
    Je crois avoir compris les choses suivantes :
    Le type de son (le codec ?) est PCM 16, donc des valeurs sur 16bits, soit 2 octets
    J'ai réglé la fréquence d'échantillonnage à 48000Hz.
    J'ai défini l'échantillon à 4096 (il faut une puissance de 2 pour le traitement ultérieur).
    Donc lorsque je lit les données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Recorder.read(Buffer, 0, BufferSize);
    j'obtiens un tableau de 4096 octets, ce qui, une fois traité donne un tableau de 2048 valeurs de 16bits.

    Mais déjà, quel type de valeur 16 bits ?
    Je me demande s'il faut faire un tableau d'entiers non signés (word) ou bien un tableau d'entiers courts signés (smallint).
    Dans les premiers tests que j'ai fait, avec un son a priori calibré, ou à tout le moins connu (un La2 doit être à 220Hz), que ce soit un tableau de word ou un tableau de smallint, les résultats ne correspondent pas du tout à ce que je devrai obtenir, mais le tableau initial contient essentiellement pour ce son avec une dominante très marquée que les valeurs 0, 1, 254, 255.
    Si j'utilise des smallint, il arrive que j'obtienne des valeurs négatives (par exemple 2 octets 255 donne 65535 dans un word et -1 dans un smallint).

    Mais, même si j'arrive à obtenir une réponse sur ce point, une fois que j'ai obtenu ce tableau, comment l'exploiter ?
    J'ai consulté pas mal de sites et d'informations, et il semblerait qu'il faille traiter ces données par une fonction mathématique dite transformée de Fourier discrète (souvent abrégée en FFT).

    On trouve quelques exemples de FFT en C ou en Java. J'ai même trouvé une unité FFTreal.pas, semble-t-il traduite du C, mais je ne dois pas savoir l'utiliser, car j'obtiens des résultats complètement incohérents.
    J'ai essayé de traduire les unités java en delphi mais je suis trop mauvais en C et en java pour faire la conversion.
    Les convertisseurs de programmes divers et variés que j'ai essayé (y compris chatgpt ;o) pour convertir ces unités C ou Java produisent du code qui ne fonctionne pas (erreurs diverses et variées qui empêchent la compilation sans que j'arrive à trouver la bonne formulation).

    Voilà où j'en suis pour l'instant.
    Je suis en train d'ingurgiter des cours de mathématiques pour essayer de programmer par moi-même une transformée de Fourier discrète, mais j'avoue que pour l'instant je ne comprends pas grand chose ... ça dépasse largement mes connaissances en mathématiques qui datent de mon BAC série D il y a bientôt 50 ans ...
    Encore merci d'avance à ceux qui pourraient me guider sur le sujet ... voire même un exemple de code, ce serait super !

  7. #7
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Bonjour,


    Citation Envoyé par navyg Voir le message
    Bon pour l'instant je ne suis pas arrivé à grand chose, mais ce thème n'a pas l'air d'intéresser grand monde.
    Oui, ce n'est pas un sujet qui motive les foules, qui sont plutôt intéressées par l'inverse, ie, configurer un outil qui joue la fréquence F, et bien content quand on l'entend !

    Citation Envoyé par navyg Voir le message
    Le type de son (le codec ?) est PCM 16, donc des valeurs sur 16bits, soit 2 octets
    Un codec est un dispositif matériel ou logiciel permettant de mettre en œuvre l'encodage ou le décodage d'un flux de données numérique, en vue d'une transmission ou d'un stockage. (wikipédia)

    Citation Envoyé par navyg Voir le message
    Voilà où j'en suis pour l'instant.
    Je suis en train d'ingurgiter des cours de mathématiques pour essayer de programmer par moi-même une transformée de Fourier discrète, mais j'avoue que pour l'instant je ne comprends pas grand chose ... ça dépasse largement mes connaissances en mathématiques qui datent de mon BAC série D il y a bientôt 50 ans ...
    Encore merci d'avance à ceux qui pourraient me guider sur le sujet ... voire même un exemple de code, ce serait super !
    Si je devais faire, je m'engrainerais avec le lien que j'ai donné mais avant, j'installerais la librairie BASS et je m'entrainerais un peu avec les exemples fournis, histoire de voir comment tout ça s'articule.
    Et après, ton truc ne devrait pas être insurmontable : l'aide est sympathique, il y a des micro-exemples, et ça cause en Delphi.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par navyg Voir le message
    Ce thème n'a pas l'air d'intéresser grand monde.
    Disons que les fêtes approchent, la fréquentation sur le forum s'en ressent. Quant à moi, je n'ai pas encore commencé mes grandes vacances (encore une semaine) que déjà ma liste des choses à faire s'est brusquement allongée de challenges intéressants (et plus dans mes cordes ).

    Je continue quand même.
    Ne pas lâcher le morceau

    mes connaissances en mathématiques qui datent de mon BAC série D il y a bientôt 50 ans ...
    en comptant sur mes doigts, j'arrive au même résultat et je ne pense pas que Fourier fusse au programme

    mon anglais est très ... comment dire ... mauvais !
    mon anglais parlé l'est aussi mais mon anglais lu reste affuté, de plus une extension d'un explorateur web comme ImTranslator ça aide beaucoup

    Je lis sur BASS que
    BASS Audio Recognition Library est une bibliothèque (.dll) à utiliser dans les logiciels Win32, Win64 (Windows XP/Vista/7/8/10) et OSX32 avec BASS.
    donc l'objectif Androïd me parait compromis (mais peut-être que le site n'est pas à jour)

    As-tu été voir du côté des composants Mitov ? https://www.mitov.com/products/visionlab#components; https://www.mitov.com/screenshots/audiolab
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  9. #9
    Membre actif
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Décembre 2003
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Distribution

    Informations forums :
    Inscription : Décembre 2003
    Messages : 167
    Points : 208
    Points
    208
    Par défaut
    Bonjour

    je ne vais pas faire avancer le schmilblick mais il existe un outils gratuits sans pub utilisant tous les capteurs de votre smartphone
    https://phyphox.org/

  10. #10
    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
    La librairie bass, j'ai regardé, je n'y comprends rien, ça me paraît vraiment très compliqué à mettre en oeuvre, mais je vais peut-être prendre plus de temps.
    Pour Mitov, je vais essayer aussi de me pencher dessus.

    Cette nuit, j'ai quand même un peu avancé.
    Il me semble que j'ai réussi à implémenter un tableau de complexes. Ce n'est pas évident dans delphi qui ne comporte pas vraiment de type TComplex ou alors avec un variant de type particulier, mais j'avais des erreurs opération sur variant incorrect en voulant utiliser Mathcmplx. La documentation sur le sujet dans delphi est vraiment très succinte et il n'y a aucun exemple d'utilisation de comment créer un type VarComplex et pouvoir en faire un tableau de valeurs de type complexe.

    Donc je me suis déjà attaqué à ce problème car pour utiliser une procédure récursive python, il me fallait un tableau de complexes, et pouvoir traiter quelques opérations sur les complexes (addition, multiplication, élévation à une puissance quelconque, produire un facteur de i .... c'est déjà pas mal);

    Ensuite j'ai mis un moment pour convertir cette procédure python qui traite une fft de façon récursive, et déjà ça ne plante pas !
    Mais si quelqu'un parle python et delphi couramment pour me vérifier la conversion, je suis preneur .

    Avec le premier jet produit en fin de nuit, quel que soit le son produit, les valeurs résultantes produisent toujours le même type de courbe avec un pic sur la valeur médiane, donc sans doute encore un problème de traitement ou d'interprétation des données.
    Je n'ai pas encore eu le temps d'analyser tout ça car à 5h30 du matin passé je ne voyais plus très clair
    Encore du travail en perspective, mais ça me plaît.

    Je ne manquerai pas tenir ce sujet à jour dès que je pourrai m'y remettre.

  11. #11
    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 fbalien Voir le message
    Bonjour

    je ne vais pas faire avancer le schmilblick mais il existe un outils gratuits sans pub utilisant tous les capteurs de votre smartphone
    https://phyphox.org/
    Merci pour le lien, ça semble très intéressant, mais pas tout à fait adapté à ce que je veux faire.
    Et puis au final je ne cherche pas une solution toute faite, je veux comprendre comment ça marche et faire un programme adapté à mes besoins.
    Si quelqu'un a produit ça, ce doit être possible d'en extraire uniquement ce dont j'ai besoin ?
    Je ne sais pas dans quel langage ce programme a été fait mais en fait ce dont j'ai besoin c'est uniquement la méthode en delphi pour faire l'analyse spectrale.
    Ca me paraît étonnant que personne n'ait déjà produit un exemple sur le sujet ...

  12. #12
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par navyg Voir le message
    Je vois donc que je recueille des valeurs, mais comment les traiter ?
    J'ai lu beaucoup de théorie sur les transformées de Fourier discrète qui permettrait de transformer ces valeurs en fréquence.
    J'ai cherché sur internet des exemples de code, mais aucun exemple ne va jusqu'à calculer la fréquence qui ressort de l'échantillon.
    Effectivement la transformée de Fourrier est la meilleure solution. Ceci dit à moins d'enregistrer une sinusoïde déterminer la fréquence peut être assez complexe en fonction de la nature du signal. Une première approche peut consister à déterminer le premier maximum de la courbe. En effet un son est généralement composé d'un fréquence fondamentale à laquelle on ajoute des harmoniques qui sont de fréquence plus élevées. La FFT impose un certain nombre de contraintes comme la taille de l'échantillon qui doit être une puissance de 2. Il faut aussi des connaissances mathématiques sur les nombres complexes.
    Pour ce qui est des algorithmes de transformée de fourrier rapide il y en a pléthore (exemple https://github.com/merlinND/pascal-f...pascal-fft.pas).
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  13. #13
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 730
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 730
    Points : 15 132
    Points
    15 132
    Par défaut
    Citation Envoyé par navyg Voir le message
    La librairie bass, j'ai regardé, je n'y comprends rien, ça me paraît vraiment très compliqué à mettre en oeuvre, mais je vais peut-être prendre plus de temps.
    Rhôôô, mais c'est simple comme bonjour !
    Un fichier .dll ou .so selon l'environnement, à copier au bon endroit.
    Puis ajouter Bass dans la section uses du .pas et roule ma poule !

    Tiens, je t'ai trouvé un autre exemple, qui détecte la valeur la plus élevée dans un bête fichier .wav ;
    https://www.un4seen.com/forum/?topic=20030.0

    c'est en C mais assez facile à traduire et d'ailleurs, l'OP a produit un code Delphi, à voir.

    Dans un coin j'ai un truc qui s'appelle "la base d'un prog Bass" et ça donne ça, au début d'un .pas :
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    uses
      {$IFDEF MSWINDOWS}
      Windows, Messages,
      {$ENDIF}
      {$IFDEF LINUX}
      LCLIntf, LCLType,
      {$ENDIF}
      Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
      bass;
     
    type
     
      { TForm1 }
     
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        procedure Error(msg: string);
      public
     
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.lfm}
     
    { TForm1 }
     
    const
      SAMPLERATE = 44100;
     
    procedure TForm1.Error(msg: string);
    begin
      MessageBox(Handle, PChar(msg + #13#10 + '(error code: ' + IntToStr(BASS_ErrorGetCode) + ')'), nil, 0);
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      if (HIWORD(BASS_GetVersion) <> BASSVERSION) then begin
        Error('Mauvaise version de la librairie BASS !');
        Halt;
      end;
     
      if not BASS_Init(-1, SAMPLERATE, 0, nil, nil) then begin
        Error('BASS ne peut pas s''initialiser !');
        Exit;
      end;
    end;
    Plus qu'à continuer avec les exemples, genre un générateur de waveform à partir d'un fichier son :

    Nom : visbuff_ok.png
Affichages : 208
Taille : 36,1 Ko

    (vient du dossier Delphi des exemples Bass).
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    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
    He be ce n'est pas si simple !
    Pour l'instant je n'ai trouvé que des exemples avec l'ouverture de fichiers de musique
    Il y a deux exemples pour du live mais c'est très compliqué à mettre en oeuvre et ça m'a même bloqué l'ordi !
    je continue mes investigations, mais les appels de fonctions sont très complexes et la documentation est en anglais, donc rédhibitoire pour moi ...
    Mais je continue à explorer

  15. #15
    Membre expérimenté
    Avatar de Gouyon
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 076
    Points : 1 521
    Points
    1 521
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par navyg Voir le message
    He be ce n'est pas si simple !
    Bienvenu dans le monde du traitement du signal

    Plus sérieusement dans un premier temps et pour faire simple:

    1/acquisition du signal dans un tableau de 2^N échantillons (16384 ou 32768 doivent amplement suffire)
    2/FFT qui va te donner 2 tableaux (partie réelle et imaginaire).
    3/Calcul du module à partir des deux tableaux M[n]=sqrt(R[n]²+I[n]²)
    3/Détection de la position du maximum du tableau M[n]= fréquence
    Il y a des jours où j'éprouve une haine profonde envers microsoft et Apple c'est pas mieux
    Mon modeste site et mes modestes oeuvres sont
    Rémi

  16. #16
    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 Jipété Voir le message
    Rhôôô, mais c'est simple comme bonjour !
    Un fichier .dll ou .so selon l'environnement, à copier au bon endroit.
    Puis ajouter Bass dans la section uses du .pas et roule ma poule !
    Et bien ce n'est pas simple du tout ...
    Je viens d'étudier tous les exemples et de faire un programme test.

    Un label, deux boutons, un radiogroup avec deux options et un stringgrid :
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    unit Unit1;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
      System.Math, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, bass, Vcl.StdCtrls, Vcl.Grids,
      Vcl.ExtCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        l1: TLabel;
        Button2: TButton;
        sg1: TStringGrid;
        rg1: TRadioGroup;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Déclarations privées }
        procedure Error(msg: string);
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      Channel	: HRECORD;	// recording channel
     
    implementation
     
    {$R *.dfm}
    var
      MasterFreq0,
      PeakFreq0: double;
      rec: boolean;
     
    const
      SAMPLERATE = 44100;
     
    //---------------------------------------------------------
    // Recording callback - not doing anything with the data
     
    function DuffRecording(handle : HRECORD; const Buffer : Pointer; Length : DWORD; user : Pointer) : Boolean; stdcall;
    begin
      Result := True;	// continue recording
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      PeakBin: Integer;
      Rate: single;
      PeakVal: single;
      FFT, temp: array [0..4095] of Single;
    var
      AStream: HSTREAM;
      i: Integer;
    begin
    rec:=true;
    rate:=48000;
    // start recording (48000hz mono 16-bit)
    PeakBin := 0;
    PeakVal := 0.0;
     
       case rg1.ItemIndex of
       0:
          begin
             repeat
             Channel := BASS_RecordStart(48000, 1, 0, @DuffRecording, NIL);
             if Channel = 0 then
                begin
                Error('Can''t start recording');
                Halt;
                end;
     
             if BASS_ChannelGetData(Channel, @temp, BASS_DATA_FFT4096 or BASS_DATA_FFT_REMOVEDC)=-1 then
                break; // get FFT data (4096 sample)
             for i:=0 to 2047 do
                fft[i]:=fft[i]+temp[i];
             application.processmessages
             until not rec;
     
          for i := 1 to 2046 do
             begin
             sg1.Cells[0,i]:=i.tostring;
             sg1.Cells[1,i]:=fft[i].ToString;
             if (Peakval < FFT[i]) then // found a new peak
                begin
                PeakVal := FFT[i];
                PeakBin := i;
                end;
             end;
          end;
     
       1:
          begin
             repeat
             Channel := BASS_RecordStart(48000, 1, 0, @DuffRecording, NIL);
             if Channel = 0 then
                begin
                Error('Can''t start recording');
                Halt;
                end;
     
             if BASS_ChannelGetData(Channel, @temp, BASS_DATA_FFT_complex or BASS_DATA_FFT_REMOVEDC)=-1 then // get FFT data (complexes)
                break;
             for i:=0 to 2047 do
                fft[i]:=fft[i]+temp[i];
             application.processmessages
             until not rec;
     
          i:=0;
          while i<4094 do
             begin
             sg1.Cells[0, i div 2]:=(i div 2).tostring;
             sg1.Cells[1, i div 2]:=fft[i].ToString;
             sg1.Cells[2, i div 2]:=fft[i+1].ToString;
             sg1.Cells[3, i div 2]:=hypot(FFT[i], FFT[i+1]).ToString;
             // calcul direct de l'amplitude du signal en faisant racine carrée (real*reel + imag*imag)
             if (Peakval < hypot(FFT[i], FFT[i+1])) then // found a new peak
                begin
                PeakVal := hypot(FFT[i], FFT[i+1]);
                PeakBin := i div 2;
                end;
             inc(i, 2);
             end;
          end;
       end;
     
    PeakFreq0 := PeakBin * (Rate / 2048); // get frequency of peak bin
    if (MasterFreq0 < PeakFreq0) then
       MasterFreq0 := PeakFreq0;
    l1.caption:='Rang: '+peakbin.ToString+ '    '+masterfreq0.ToString+'Hz';
     
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
    rec:=false;
    end;
     
    procedure TForm1.Error(msg: string);
    begin
      MessageBox(Handle, PChar(msg + #13#10 + '(error code: ' + IntToStr(BASS_ErrorGetCode) + ')'), nil, 0);
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      if (HIWORD(BASS_GetVersion) <> BASSVERSION) then begin
        Error('Mauvaise version de la librairie BASS !');
        Halt;
      end;
     
      // initialize BASS recording (default device)
      if not BASS_RecordInit(-1) then
      begin
        Error('Can''t initialize device');
        Halt;
      end;
     
    end;
     
    end.
    Alors les appels des fonctions, c'est vraiment très compliqué à comprendre, même avec l'aide (pourquoi faire compliqué quand ce serait si facile de faire simple ?)
    Après avoir pris beaucoup de temps à essayer de comprendre, je dois être complètement neuneu car selon mes tests, les résultats sont complètement aberrants.
    Ca retourne quasiment toujours la même fréquence en haut du spectre quel que soit le son produit en entrée.

    Je dois faire quelque chose de pas bien mais je ne vois pas quoi ?

    Donc bass, pas si bien que ça ... et grosse perte de temps.
    En plus ce que je veux c'est comprendre comment faire le calcul et le traitement des données, ce n'est pas d'utiliser une dll obscure qui met à disposition des fonctions dont on ne ne sait rien.

    Avis tout à fait personnel et qui ne préjuge pas de la qualité du produit.
    Mais ce n'est définitivement pas fait pour moi car je n'obtiens pas ce que je veux, c'est compliqué à comprendre ... et c'est en anglais !

  17. #17
    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 Gouyon Voir le message
    Bienvenu dans le monde du traitement du signal

    Plus sérieusement dans un premier temps et pour faire simple:

    1/acquisition du signal dans un tableau de 2^N échantillons (16384 ou 32768 doivent amplement suffire)
    2/FFT qui va te donner 2 tableaux (partie réelle et imaginaire).
    3/Calcul du module à partir des deux tableaux M[n]=sqrt(R[n]²+I[n]²)
    3/Détection de la position du maximum du tableau M[n]= fréquence
    Belle synthèse de ce que j'essaye de faire depuis plusieurs jours (semaines ?), enfin plusieurs nuits surtout.
    Pour le point 3 je crois avoir compris que la fréquence est égale au rang de la valeur maximum * le sample rate divisé par la taille de l'échantillon divisé par 2
    Si :
    Fréquence d'échantillonage=48000Hz
    Taille de l'échantillon : 4096
    les données sont recueuillies en PCM 16 bits, soit 2 octets par valeur
    donc, les tableaux de données et les tableaux FFT sont d'une taille de 2048 (4096 / 2)

    Mmax = rang de max(M[n])

    Donc :
    Fréquence = Mmax * 48000 / (4096 /2)

    Le module (ou l'amplitude ?) de la fréquence la plus grave sera M[1]
    Le module (ou l'amplitude ?) de la fréquence la plus aigüe sera M[2047]

    Est ce que mon raisonnement est bon ?

    Si c'est bon je dois faire une erreur de raisonnement dans le codage car j'ai des résultats assez baroques ...

    Je vais m'y remettre ...

  18. #18
    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 fait une vérification de ma fft
    J'ai récupéré les données du tampon de son sous excel et j'ai fait une fft avec l'utilitaire d'analyse intégré dans excel.
    Ca me donne un tableau de complexes à partir d'un tableau d'entier sur 16 bits transformé en complexes toujours dans excel avec partie réel égale à l'entier et imaginaire =0;

    ça me donne des résultats différents de ce que je récupère de mes calculs de fft.
    Donc si quelqu'un pouvait vérifier que ma traduction de cette fonction en python est correcte ça m'arrangerait.
    Au cas où, je joins le code python et ma conversion :
    Le code Python :
    Code python : 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
    def fft(u):
        # u : numpy.ndarray
        N = len(u)
        if N==1:
            return u
        pair = u[0::2]
        impair = u[1::2]
        tfd_pair = fft(pair)
        tfd_impair = fft(impair)
        tfd = numpy.zeros(N,dtype=numpy.complex64)
        W = numpy.exp(-1j*2*numpy.pi/N)
        N2 = N//2
        for n in range(N2):
            tfd[n] = tfd_pair[n]+tfd_impair[n]*W**n
        for n in range(N2,N):
            tfd[n] = tfd_pair[n-N2]+tfd_impair[n-N2]*W**n
        return tfd

    Et la conversion delphi, avec l'implémentation des nombres complexes
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
     
    type 
       TComplex=packed record
          re: double;
          im: double;
     
          class function Pui(const x: TComplex; n: Integer): TComplex; static;
          class operator Multiply(const x, y: TComplex): TComplex;
          class operator Add(const x, y: TComplex): TComplex;
       end;
     
     
    type
       taocx=array of TComplex;
       ptaocx=^taocx;
     
    function PuiCx(const x: TComplex; n: Integer): TComplex; overload;
     
    implementation
     
    {$R *.fmx}
    {$R *.LgXhdpiPh.fmx ANDROID}
    {$R *.iPhone4in.fmx IOS}
     
    // opérations sur nombres complexes
    class function TComplex.Pui(const x: TComplex; n: Integer): TComplex;
    var
      r, theta: Double;
    begin
    // Convertir x en coordonnées polaires
    r := Hypot(x.Re, x.Im);
    theta := ArcTan2(x.Im, x.Re);
     
    // Appliquer la formule de Moivre
    r := Power(r, n);
    theta := theta * n;
     
    // Convertir le résultat en coordonnées rectangulaires
    Result.Re := r * Cos(theta);
    Result.Im := r * Sin(theta);
    end;
     
    function PuiCx(const x: TComplex; n: Integer): TComplex;
    begin
    result:=TComplex.Pui(x, n);
    end;
     
    class operator TComplex.Add(const x, y: TComplex): TComplex;
    begin
    Result.Re := x.Re + y.Re;
    Result.Im := x.Im + y.Im;
    end;
     
    class operator TComplex.Multiply(const x, y: TComplex): TComplex;
    begin
    Result.Re := x.Re * y.Re - x.Im * y.Im;
    Result.Im := x.Re * y.Im + x.Im * y.Re;
    end;
     
    // en paramètres d'entrée : tableau des complexes issus de la conversion des entiers   
    // en résultat le tableau de la FFT
    function FFT(cxs: taocx): taocx;
       var
          Nb, N2, n: Integer;
          pair, impair, tfd_pair, tfd_impair, tfd: taocx;
          W: TComplex;
       begin
     
       Nb := Length(cxs);
       if Nb = 1 then
          Exit(cxs);
       SetLength(pair, Nb div 2);
       SetLength(impair, Nb div 2);
       for n := 0 to Nb div 2 - 1 do
          begin
          pair[n] := cxs[2*n];
          impair[n] :=cxs[(2*n)+1];
          end;
       tfd_pair := FFT(pair);
       tfd_impair := FFT(impair);
       SetLength(tfd, Nb);
       W.re:=0;
       W.im:=-(2*Pi/Nb);
       N2 := Nb div 2;
       for n := 0 to N2 - 1 do
          begin
          tfd[n] := tfd_pair[n] + (tfd_impair[n] * PuiCx(W, n));
          tfd[n+N2] := tfd_pair[n] + (tfd_impair[n] * PuiCx(W, n + N2));
          end;
       Result := tfd;
       end;

  19. #19
    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
    Je crois que j'ai compris ce qui se passe, mais j'ai du mal à trouver la solution.
    Tout d'abord, on travaille sur des tableaux dynamiques, donc j'ai changé les appels de paramètres en ne passant plus le tableau dynamique mais un pointeur sur le tableau dynamique.
    Mais du fait de la récursivité, lorsque les instructions de fft sur les rangs pairs s'exécutent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SetLength(pair, Length(pcxs^) div 2);
       for n := 0 to Length(pcxs^) div 2 - 1 do
          begin
          pair[n] := pcxs^[2*n];
          end;
       tfd_pair := FFT(@pair, 'pair'); // le string pair est ajouté pour faciliter le traçage dans mon fichier de débogage car sur android je n'arrive pas à faire du pas à pas.
    sont exécutées, elles s'appellent récursivement jusqu'à ce que la taille du tableau soit de 1.
    Et ensuite quand l'instruction de dimensionnement du tableau impair arrive
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       SetLength(impair, Length(pcxs^) div 2);
       for n := 0 to Length(pcxs^) div 2 - 1 do
          begin
          impair[n] :=pcxs^[(2*n)+1];
          end;
       tfd_impair := FFT(@impair, 'impair');
    la taille du tableau cxs d'origine est déjà réduite à 1 donc je débute impair avec un tableau de taille 1 !

    donc je cherche à résoudre ce problème, mais je n'y arrive pas ... je m'y remets

  20. #20
    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,

    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 5 12345 DernièreDernière

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