I recently wrote a little python program to compute a fourier transform of a signal from the basics for the sake of learning and checking my understanding of how this function works:
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
import math
def fourier_single_point(signal_y, signal_x, frequency):
exponent = signal_x * -2j * math.pi * frequency
fourier_internals = np.multiply(signal_y, np.exp(exponent))
return integrate.trapezoid(fourier_internals, dx=signal_x[1]-signal_x[0])
#Signal in Time-Domain
SAMPLES_PER_SEC = 48000
# Time values for 1.5s of a 48kHz sample
x_vals = np.linspace(start=0, stop=1.5, num=int(SAMPLES_PER_SEC*1.5))
# Single-Frequency signal at 314 Hz
sample = np.sin(314*(2*np.pi)*x_vals)
# Frequency Domain
min_val = 0
max_val = 400
step = 0.1
frequencies = np.linspace(start=min_val, stop=max_val, num=int((max_val-min_val)/step+1))
fourier_transform = [fourier_single_point(sample, x_vals, f) for f in frequencies]
plt.plot(frequencies, np.abs(fourier_transform), alpha=0.5)
plt.show()
After running it on a simple sine wave and graphing the results, I see the expected large spike at 314 Hz, but I also see smaller, periodic spikes surrounding that and tapering off. With some fiddling, I realized the frequency of the surrounding spikes is inversely correlated to the width of the window I'm integrating over (If I integrate over 1 second, I get these spikes every 1 Hz. Below I'm integrating over 1.5 sec. and getting them every 2/3 Hz.)
output spike at 314 Hz with surrounding periodic spikes
I would like to understand where these spikes come from, but as far as I can tell I have the math correct: Formula I referenced from Wikipedia
Maybe since the Fourier transform is on discrete values, some sort of adjustment must be made from the continous Fourier Transform function I was referencing?
Since it seems like the reason for these spikes is somehow related to the window over which I integrate, I did some searching about windowing functions and while I still didn't fully find an explanation, I did see some other examples like this one here that seem to have similar artifacts in the frequency domain, which makes me think maybe it isn't a bug or miscalculation, but simply my expectations that were wrong, in which case I'd want to know what the explanation for this occurance is.
Any insight is appreciated! Thanks!