tags:

views:

222

answers:

2

hi i used fft function in numpy which resulted in a complex array.how to get the exact frequency values?

+2  A: 

The frequency is just the index of the array. At index n, the frequency is 2πn / the array's length (radians per unit). Consider:

>>> 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])

the result has nonzero values at indices 0, 2 and 6. There are 8 elements. This means

       2πit/8 × 0       2πit/8 × 2       2πit/8 × 6
    8 e           - 4i e           + 4i e
y ~ ———————————————————————————————————————————————
                          8
KennyTM
thanks KennyTM.but how do u do it using python code ?
ria
@ria: Just associate each element with 0,1,2,3,4,....
KennyTM
@KennyTM: I'm sorry. But I couldn't get it clearly.Can you tell me what are 't' and 'e' above? why did you introduce 'i*t' in the equation 2πn/8,Is there a function in SciPy doing this calculation?
ria
@ria: e is 2.71828.... See http://en.wikipedia.org/wiki/Euler%27s_formula. t is the index of the original array, e.g. t=0 -> 1, t=1 -> 2, t=2 -> 1, etc. Basically, if you want to get the frequency, they are just 0/8, 1/8, 2/8, ..., 7/8.
KennyTM
@ KennyTM:I see,the exponent 'e'.I understood.
ria
+3  A: 

np.fft.fftfreq tells you the frequencies associated with the 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)

The OP asks how to find the frequency in Hertz. I believe the formula is frequency (Hz) = abs(fft_freq * frame_rate).

Here is some code that demonstrates that.

First, we make a wave file at 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()

This creates the file test.wav. Now we read in the data, FFT it, find the coefficient with maximum power, and find the corresponding fft frequency, and then convert to 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)**2)
    freq=freqs[idx]
    freq_in_hertz=abs(freq*frate)
    print(freq_in_hertz)
    # 439.8975
unutbu
@unutbu: thanks a lot. Let me try it:)
ria
@~unutbu:But can I get the frequency values in Hertz?I want to make wav files.
ria
@ria: `freq` as defined by `np.fft.fft` is unitless, and always in the interval [-1/2, 1/2]. I believe to convert to Hertz, you multiply by the frame rate and take the absolute value.
unutbu
No sir, my aim is to read a wav file , perform fft on it,and with each frequency value i have to create a new wav file.i have done till performing fft.this is the output i got:wavefile:Reading fmt chunkReading data chunk(8000, array([128, 128, 128, ..., 128, 128, 128], dtype=uint8))numpy array:[128 128 128 ..., 128 128 128]
ria
fft on numpy:[ 12535945.00000000 +0.j -30797.74496367 +6531.22295858j -26330.14948055-11865.08322966j ..., 34265.08792783+31937.15794965j -26330.14948055+11865.08322966j -30797.74496367 -6531.22295858j]now to write it on a wav file i guess i need the frequency values in hertz.or is there any other way?
ria
hi,please give me a reply.Because I need to do this ASAP.Is it possible to do this task at least?
ria