J'ai utilisé fft
dans numpy, ce qui a donné lieu à un tableau complexe. Comment obtenir les valeurs exactes de la fréquence ?
Réponses
Trop de publicités?np.fft.fftfreq
vous indique les fréquences associées aux coefficients :
import numpy as np
x = np.array([1,2,1,0,1,2,1,0])
w = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x))
for coef,freq in zip(w,freqs):
if coef:
print('{c:>6} * exp(2 pi i t * {f})'.format(c=coef,f=freq))
# (8+0j) * exp(2 pi i t * 0.0)
# -4j * exp(2 pi i t * 0.25)
# 4j * exp(2 pi i t * -0.25)
L'OP demande comment trouver la fréquence en Hertz. Je crois que la formule est frequency (Hz) = abs(fft_freq * frame_rate)
.
Voici un code qui le démontre.
Tout d'abord, nous créons un fichier d'ondes à 440 Hz :
import math
import wave
import struct
if __name__ == '__main__':
# http://stackoverflow.com/questions/3637350/how-to-write-stereo-wav-files-in-python
# http://www.sonicspot.com/guide/wavefiles.html
freq = 440.0
data_size = 40000
fname = "test.wav"
frate = 11025.0
amp = 64000.0
nchannels = 1
sampwidth = 2
framerate = int(frate)
nframes = data_size
comptype = "NONE"
compname = "not compressed"
data = [math.sin(2 * math.pi * freq * (x / frate))
for x in range(data_size)]
wav_file = wave.open(fname, 'w')
wav_file.setparams(
(nchannels, sampwidth, framerate, nframes, comptype, compname))
for v in data:
wav_file.writeframes(struct.pack('h', int(v * amp / 2)))
wav_file.close()
Cela crée le fichier test.wav
. Maintenant nous lisons les données, nous les transformons en FFT, nous trouvons le coefficient avec la puissance maximale, et on trouve la fréquence fft correspondante, puis on convertit en Hertz :
import wave
import struct
import numpy as np
if __name__ == '__main__':
data_size = 40000
fname = "test.wav"
frate = 11025.0
wav_file = wave.open(fname, 'r')
data = wav_file.readframes(data_size)
wav_file.close()
data = struct.unpack('{n}h'.format(n=data_size), data)
data = np.array(data)
w = np.fft.fft(data)
freqs = np.fft.fftfreq(len(w))
print(freqs.min(), freqs.max())
# (-0.5, 0.499975)
# Find the peak in the coefficients
idx = np.argmax(np.abs(w))
freq = freqs[idx]
freq_in_hertz = abs(freq * frate)
print(freq_in_hertz)
# 439.8975
Fréquences associées aux valeurs DFT (en python)
Par fft Avec la transformée de Fourier rapide, nous comprenons un membre d'une grande famille d'algorithmes qui permettent le rapide calcul de la TFD, Transformée de Fourier Discrète, d'un signal équi-échantillonné.
A DFT convertit une liste de N des nombres complexes à une liste de N les nombres complexes, étant entendu que les deux listes sont périodiques avec la période N .
Nous traitons ici de la numpy
mise en œuvre de la fft .
Dans de nombreux cas, vous pensez à
- un signal x défini dans le domaine temporel de longueur N échantillonné à un intervalle constant dt ,
- son DFT X (ici spécifiquement
X = np.fft.fft(x)
), dont les éléments sont échantillonnés sur l'axe des fréquences avec une fréquence d'échantillonnage dw .
Quelques définitions
-
la période (c'est-à-dire la durée) du signal
x
, échantillonné àdt
conN
échantillons est estT = dt*N
-
les fréquences fondamentales (en Hz et en rad/s) de
X
vos DFT sontdf = 1/T dw = 2*pi/T # =df*2*pi
-
la fréquence supérieure est la Nyquist fréquence
ny = dw*N/2
(et ce n'est pas
dw*N
)
Les fréquences associées à un élément particulier dans la TFD
Les fréquences correspondant aux éléments dans X = np.fft.fft(x)
pour un indice donné 0<=n<N
peut être calculée comme suit :
def rad_on_s(n, N, dw):
return dw*n if n<N/2 else dw*(n-N)
ou en un seul coup de balai
w = np.array([dw*n if n<N/2 else dw*(n-N) for n in range(N)])
si vous préférez considérer les fréquences en Hz, s/w/f/
f = np.array([df*n if n<N/2 else df*(n-N) for n in range(N)])
En utilisant ces fréquences
Si vous voulez modifier le signal original x
-> y
Si l'on applique un opérateur dans le domaine fréquentiel sous la forme d'une fonction de la fréquence uniquement, la méthode consiste à calculer la fonction de la fréquence. w
et
Y = X*f(w)
y = ifft(Y)
Présentation de np.fft.fftfreq
Bien sûr. numpy
a une fonction de commodité np.fft.fftfreq
qui renvoie fréquences sans dimension plutôt que dimensionnels mais c'est aussi simple que
f = np.fft.fftfreq(N)*N*df
w = np.fft.fftfreq(N)*N*dw
Parce que df = 1/T
y T = N/sps
( sps
étant le nombre d'échantillons par seconde), on peut également écrire
f = np.fft.fftfreq(N)*sps
La fréquence est simplement l'index du tableau. A l'indice n la fréquence est de 2 n / la longueur du tableau (radians par unité). Considérez :
>>> numpy.fft.fft([1,2,1,0,1,2,1,0])
array([ 8.+0.j, 0.+0.j, 0.-4.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+4.j,
0.+0.j])
le résultat a des valeurs non nulles aux indices 0, 2 et 6. Il y a 8 éléments. Cela signifie que
2it/8 × 0 2it/8 × 2 2it/8 × 6
8 e - 4i e + 4i e
y ~ ———————————————————————————————————————————————
8