J'ai utilisé la fonction fft
dans numpy, ce qui a entraîné un tableau complexe. Comment obtenir les valeurs de fréquence exactes?
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 du code qui le démontre.
Tout d'abord, nous faisons un fichier wave à 440 Hz:
import math
import wave
import struct
if __== '__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, les FFT, trouvons le coefficient avec la puissance maximale et trouvons la fréquence fft correspondante, puis convertissons en Hertz:
import wave
import struct
import numpy as np
if __== '__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
Par fft , Fast Fourier Transform, nous comprenons un membre d'une grande famille d'algorithmes qui permettent le fast calcul de la DFT, Discrete Fourier Transform, d'un signal équisamplé.
A DFT convertit une liste de [~ # ~] n [~ # ~] des nombres complexes à une liste de [~ # ~] n [~ # ~] nombres complexes, étant entendu que les deux listes sont périodiques avec période [~ # ~] n [~ # ~] .
Ici, nous traitons de l'implémentation numpy
de la fft .
Dans de nombreux cas, vous pensez
X = np.fft.fft(x)
), dont les éléments sont échantillonnés sur la fréquence axe avec un taux d'échantillonnage dw .la période (ou durée) du signal x
, échantillonnée à dt
avec N
échantillons est est
T = dt*N
les fréquences fondamentales (en Hz et en rad/s) de X
, vos DFT sont
df = 1/T
dw = 2*pi/T # =df*2*pi
la fréquence supérieure est la fréquence de Nyquist
ny = dw*N/2
(et ce n'est pas dw*N
)
Les fréquences correspondant aux éléments de X = np.fft.fft(x)
pour un indice donné 0<=n<N
Peuvent être calculées comme suit:
def rad_on_s(n, N, dw):
return dw*n if n<N/2 else dw*(n-N)
ou d'un seul coup
w = np.array([dw*nif 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)])
Si vous souhaitez modifier le signal d'origine x
-> y
en appliquant un opérateur dans le domaine fréquentiel sous la forme d'une fonction de fréquence uniquement, le chemin à parcourir est de calculer le w
'le sable
Y = X*f(w)
y = ifft(Y)
np.fft.fftfreq
Bien sûr, numpy
a une fonction pratique np.fft.fftfreq
Qui renvoie des fréquences sans dimension plutôt que ceux dimensionnels mais c'est aussi simple que
f = np.fft.fftfreq(N)*N*df
w = np.fft.fftfreq(N)*N*dw
La fréquence n'est que l'indice du tableau. À l'indice n, la fréquence est 2πn / la longueur du tableau (radians par unité). Considérer:
>>> 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. Ça signifie
2πit/8 × 0 2πit/8 × 2 2πit/8 × 6
8 e - 4i e + 4i e
y ~ ———————————————————————————————————————————————
8