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

Python Discussion :

Retrouver fréquence fichier wav


Sujet :

Python

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Retrouver fréquence fichier wav
    Salutations

    Voilà, dans le cadre d'un projet scolaire, je dois, à partir d'un fichier wav contenant un son pur (c'est à dire une seule note avec une fréquence bien définie), retrouver cette sus-dite fréquence.

    (En vrai, mon fichier wav contient plusieurs notes, mais je me charge de découper mon wav en n=nombre de notes fichiers, et je les anaylse un par un)

    Voici donc mon code, j'utilise la transformée de Fourier :
    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
     
    frequences = []
    #Ouverture du fichier wav à décrypter
    wav_original = wave.open("sons/elpkzgyldd.wav",'rb')
    (nchannels, sampwidth, framerate, nframes, comptype, compname) = wav_original.getparams()
     
    #Ensuite, il va découper le fichier wav en n=nombre de notes fichiers
    nbr_notes = nframes/2500
     
    for i in range(0, nbr_notes):
        debut = int(i*2500)
        fin = int((i*2500)+2500)
     
        wav_original.setpos(debut)
        print wav_original.tell()
        donnee_partie = wav_original.readframes(int((fin-debut)*framerate))
     
        partie_fichier_son = wave.open('dcrpt_fichier.wav','wb')
        partie_fichier_son.setnchannels(nchannels)
        partie_fichier_son.setsampwidth(sampwidth)
        partie_fichier_son.setframerate(framerate)
        partie_fichier_son.writeframes(donnee_partie)
        partie_fichier_son.close()
     
        #Maintenant, on applique la transformée de Fourier
        wav = wave.open("dcrpt_fichier.wav",'rb')
        (nchannels, sampwidth, framerate, nframes, comptype, compname) = wav.getparams()
        frames = wav.readframes(nframes)
     
        data = struct.unpack('%sh' % (nframes * nchannels), frames)
     
        w = np.fft.fft(data)
        freqs = np.fft.fftfreq(len(w))
        idx=np.argmax(np.abs(w)**2)
        freq=freqs[idx]
        frequence=abs(freq*framerate)
     
        #On arrondit la fréquence, car elle est non-entière
        partie_decimale = frequence-int(frequence)
        if(partie_decimale >= 0.5):
            frequence=int(frequence+0.5)
        else:
            frequence=int(frequence-0.5)
     
        frequences.append(frequence)
        wav.close()
        os.remove("dcrpt_fichier.wav")
    print frequences
    Voici ce que me retourne cet algorithme :
    [247, 182, 247, 182, 248, 182, 248]

    Or il est censé me retourner :
    [247, 182, 248, 182, 249, 182, 250]

    D'accord on est pas très loin, mais il me faut les fréquences exactes

    Et parfois, les écarts sont éléphantesques ! Par exemple je dois obtenir ceci :
    [266, 264, 255, 265, 266, 247, 260, 262, 255, 249, 267, 266]

    Et mon algorithme retourne :
    [267, 265, 265, 267, 267, 266, 266, 266, 266, 266, 267, 267]

    Ventre-saint-gris ! me direz-vous, que fait donc cette transformée de Fourier ?
    Existe-t-il un moyen d'obtenir les fréquences exactes ? Je ne tiens point forcément à utiliser la transformée de Fourier, car comme dans le cochon, tout est bon pour que je parvienne à mes fins !

    En vous remerciant d'avance de l'intérêt que vous porterez à mon problème !

  2. #2
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Points : 692
    Points
    692
    Par défaut
    Bonjour.
    Quelles sont les valeurs sans l'arrondi ?
    Peut-on avoir le fichier "elpkzgyldd.wav".

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Sans l'arrondi, voici les valeurs :

    [248.21999999999997, 181.91250000000002, 248.28300000000002, 181.91250000000002, 249.16500000000002, 181.91250000000002, 249.16500000000002]

    Et voici le fichier :
    elpkzgyldd.zip

    Merci d'avance

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Points : 692
    Points
    692
    Par défaut
    Par exemple, pour la troisième fréquence, tu obtiens 247 et tu t'attends à 248.
    J'ai tracé le carré de l'amplitude de la FFT (Figure jointe). Je n'ai pas fait la correction sur les abscisses (l'arrondi).

    On ne peut pas directement prendre la valeur maximale des points calculés. Il faut ajuster la courbe auparavant (avec une gaussienne par exemple).
    D'où le petit décalage.
    Images attachées Images attachées  

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Je te remercie de ton aide, mais comment dans mon cas pourrais-je implémenter ta solution ? Je dois avouer que je ne maîtrise pas très bien les FFT...

  6. #6
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Points : 692
    Points
    692
    Par défaut
    Salut.
    Comme tu as fait du bon travail, je te donne un petit coup de pouce pour terminer.

    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
    import wave, struct
    from time import sleep
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
     
    def func(x,a,b,c):
        return c * np.exp( -np.power( (x-a)/b, 2) )
     
    plt.ion()   # utilise pyplot en interactif
     
    # Ouverture du fichier wav a decrypter
    wav_original = wave.open("son/elpkzgyldd.wav",'rb')
     
    nchannels = wav_original.getnchannels()     # Returns number of audio channels (1 for mono, 2 for stereo)
    framerate = wav_original.getframerate()     # Returns sampling frequency
    nframes   = wav_original.getnframes()       # Returns number of audio frames
     
    # Decouper le fichier en plusieurs parties (une note par partie)
    frequences, freq_gauss = [], []
    larg_frame = 2500
    for posi in range(0,nframes,larg_frame):
     
        # Sequence contenant une note
        wav_original.setpos(posi)
        donnee = wav_original.readframes(larg_frame)
        data = struct.unpack('%sh' % (larg_frame * nchannels), donnee)
     
        # Transformee de Fourier
        w     = np.fft.fft(data)
        sig   = np.real(w * w.conjugate())
        freqs = np.fft.fftfreq(len(w)) * framerate
     
        # Estimation de la frequence
        idx = np.argmax(sig)
        f0, maxi = np.abs(freqs[idx]), sig[idx]
        frequences.append( f0 )
     
        # Ajustement par une gaussienne
        ind = np.where( np.abs(freqs - f0) < 20 )
        popt, pcov = curve_fit( func, freqs[ind], sig[ind]/maxi, p0=[f0,1,1] )
        a, b, c = popt
        freq_gauss.append(a)
     
        # Affichage
        plt.plot( freqs[ind], sig[ind], 'o')
        fnew = np.linspace( freqs[ind][0], freqs[ind][-1], 512)
        plt.plot( fnew, maxi * func(fnew,a,b,c), 'r')
        plt.draw() ; sleep(2) ; plt.clf()
     
    wav_original.close()
     
    for res in (frequences,freq_gauss):
        print np.round(res, 0)
    print "Resultats attendus :\n[247, 182, 248, 182, 249, 182, 250]"

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Un très, très grand merci, cela marche exactement comme je le voulais !

    Vraiment, ça fait chaud au cœur de voir que la magie d'internet est toujours présente

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

Discussions similaires

  1. Réponses: 31
    Dernier message: 06/02/2010, 10h50
  2. Fichier Wav avec une fréquence donnée
    Par azimut2 dans le forum Windows
    Réponses: 0
    Dernier message: 23/11/2009, 05h19
  3. Jouer des fichiers .wav à une fréquence précise
    Par germinho dans le forum LabVIEW
    Réponses: 0
    Dernier message: 22/05/2008, 10h16
  4. Lecture de fichiers ".WAV"...
    Par 0x4e84 dans le forum Langage
    Réponses: 2
    Dernier message: 03/09/2002, 09h43
  5. [Kylix] jouer un fichier wav avec kilyx
    Par JlouisI dans le forum EDI
    Réponses: 1
    Dernier message: 14/06/2002, 02h05

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