I am testing my knowledge about Discrete Fourier Transforms.
What I am testing now is how to calculate the central frequency of a wave using DFT.
For that purpose I create a sinusoidal data using this code:
// create a 100 Hz wave with a sampling rate of 512 samples per second
var data : [Double] = []
for i in 0...511 {
let t = Double(i) * 100/256
let f = 10 * sin(2 * Double.pi * t)
data.append(f)
}
Then I do a DWT on data
and get two vectors, one containing the real part and one containing the imaginary part.
I understand that the inside each vector I will have this:
- data has 512 samples
- therefore, items from 0 to 256 will be the positive frequencies
- and items from 257 to 511, the negative frequencies
- I can discard the negative frequencies and keep the positive frequencies, from bin 0 to 255.
- Bin 0 is DC. I can discard it.
- Bin 255 will be 256Hz, because it is half of the sample rate.
To see if I get it right, I check the 256 bins and look for the highest magnitude. The bin with the highest magnitude will be K
on the following formula and I can find the signal frequency:
freq = (K + 1) * fps / N
K+1
because my first index is 0
and I have discarded DC from my array, and where N
is the number of samples.
The big problem is: how do I calculate the energy per bin?
E[i] = sqrt(realPart[i] * realPart[i] + imaginaryPart[i] * imaginaryPart[i])
????
Your outline above looks on point ... to calculate the magnitude for a given bin
mag = 2.0 * math.Sqrt(real*real+imag*imag) / number_of_samples
where number_of_samples is the length of array fed into the fft call ... beautiful aspect of doing a fft is you can then apply the inverse Fourier Transform on that set of ( freq, magnitude, phase shift) to return back your source time domain signal ... doing this is a nice way to validate your process is correct
Magic of Fourier Transform and the Inverse Fourier Transform - an example :
you start with a floating point array which represents something which wobbles like audio, stock market index or any time-series ... this is the time domain representation since its a set of points on a curve where time is your left to right X axis and the up and down Y axis is the height of the curve ... then you feed this array into a fft api call which will return back to you the same information in its frequency domain representation ... its the same information just in a different representation ... in the freq domain you will have an array where element 0 is always frequency of 0 cycles per second (DC offset) then as you iterate across the array you increment freq using formula
incr_freq := sample_rate / number_of_samples
so in the complex array generated by the fft call each element is the data for a given frequency where each element is simply a complex number ... in simple terms this freq domain representation is just a set of frequencies, each freq embodied by a complex number (A + Bi) which can be used to calc that freq's magnitude and phase shift
now is the interesting part ... if you send this freq domain array into an inverse Fourier Transform you will get back your original data which is in time domain representation
myAudio_TD ( time domain ) --> send to fft --> myAudio_FD ( freq domain )
then later you are free to do the reverse as in
myAudio_FD ( freq domain ) --> send to inverse fft --> myAudio_TD ( time domain )
notice in that progression you started with an array myAudio_TD which got sent into an fft call then into an inverse fft call which magically returns back to you your original myAudio_TD
to see the full parsing of the complex array returned from fft call which includes notion of Nyquist Limit see Get frequency with highest amplitude from FFT
来源:https://stackoverflow.com/questions/55430065/how-to-calculate-the-energy-per-bin-in-a-dft