I am writing code that takes windows of 1024 samples each of a sine wave, takes the FFT of each window, and returns the maximum frequency of each window. I know they will all be the same for a sine wave, but it's for testing. My code works mostly, except the resulting frequencies seem to be about 10 percent lower than they should be. For example, a sine of 440Hz results in a max amplitude at frequency 430 in my FFT. I can't for the life of me figure out what's causing this. Any suggestions?
import math
import numpy as np
import matplotlib.pyplot as plt
import pylab as py
from scipy import fftpack
from pylab import *
import scipy.io.wavfile
def PARTA(window):
sr = 44100
x = arange(0., 2*pi, 1./sr)
samples = sin(2*pi*440*x)
time_step = 1. / sr
end = len(samples)/window
print end
'''Make a 2-D array of samples'''
windowed = []
maxes = []
for i in range(0, end):
windowed.append(samples[i*window:(i+1)*window])
for j in range(0, end):
ps = np.abs(np.fft.fft(windowed[j]))**2
freqs = np.fft.fftfreq(windowed[j].size, time_step)
max_y = max(ps) # Find the maximum y value
max_x = freqs[ps.argmax()] # Find the x value corresponding to the maximum y value
maxes.append(max_x)
end2 = float(len(samples)/sr)
#print end2
interval = end2/end
#print interval
x = arange(0., end2, interval)
y = []
for i in range(0, len(maxes)):
y.append(abs(maxes[i]))
return (x, y)
x, y = PARTA(1024)
plt.plot(x, y, 'ro')
plt.show()