Fourier Transform not working correctly

Jun 28, 2010 at 10:01 PM

Hi,

I am using a fourier transform to get the signal frequencies from an array of doubles but I seem to be getting the wrong results.

I thought the results were weird so I created a test compound signal made up of 5 sine waves and the results still looked wrong so I used matlab and it outputted the expected results.

here is my code -


RealFourierTransformation rft = new RealFourierTransformation(TransformationConvention.Matlab);
 rft.TransformForward(tmp, out freqReal, out freqImag);

 //carry out mod
for (int w = 0; w < output.Length-1; w++){
     output[w] = Math.Sqrt(Math.Pow(freqReal[w], 2) +  Math.Pow(freqImag[w], 2));
}

 

I also used the default convention which didn't solve the issue.

am I missing some thing ?

Thanks, Alex

Coordinator
Jun 28, 2010 at 11:50 PM

Hi Alex,

This is about Math.NET Iridium, not Math.NET Numerics (see). Doesn't matter, just to clarify for the others, as Math.NET Numerics comes with a new FFT engine (which supports arbitrary non-power-of-2 lengths).

Your code looks ok (provided you do want the absolutes), yet your reported divergence from Matlab is unexpected. I've just written a small test with 3 sines and I do get the same result as in Matlab 6.5:

MATLAB:

t = [0:1:1023];
sines = sin(2*pi*(0.1*t)) + sin(2*pi*(0.4+0.03*t)) + sin(2*pi*(0.8+0.004*t));
freq = fft(sines);
freqr = real(freq);
freqi = imag(freq);

Math.NET Iridium:

var frequencies = new [] { 0.1, 0.03, 0.004 };
var phases = new[] { 0.0, 0.4, 0.8 };
var sines = new double[1024];
for(int i=0; i<sines.Length; i++)
   for(int k=0; k<frequencies.Length; k++)
      sines[i] += Math.Sin(2*Math.Pi*(phases[k] + i*frequencies[k]));
double[] real, imag;
var rft = new RealFourierTransformation(TransformationConvention.Matlab);
rft.TransformForward(sines, out real, out imag);

How did you generate your sines in MATLAB and Iridium?

What version or commit of Iridium are you using?

Thanks,
Chris

Jun 29, 2010 at 12:16 AM

Thanks for your reply!

I am using version - MathNet.Iridium-2008.8.16.470

I created the sines in excel and then created a compound which I then statically put into both programs here is the mat lab code

function fourier()

data = [0.00, 2.28, 2.09,1.19,1.71,2.05,0.63,-0.34,1.00,2.31,1.22,-0.39,-0.29,-0.08,-1.32,-1.89,0.00,1.89,1.32,0.08,0.29,0.39,-1.22,-2.31,-1.00,0.34,-0.63,-2.05,-1.71,-1.19,-2.09,-2.28,0.00,2.28,2.09,1.19,1.71,2.05,0.63,-0.34,1.00,2.31,1.22,-0.39,-0.29,-0.08,-1.32,-1.89,0.00,1.89,1.32,0.08,0.29,0.39,-1.22,-2.31,-1.00,0.34,-0.63,-2.05,-1.71,-1.19,-2.09,-2.28];
Fs = 212.5;
%Generate a time vector that corresponds with data 
t = linspace(0,length(data)/Fs,length(data)); 
%Plot time versus amplitude data 
plot(t,data) 
xlabel('Time (seconds)') 
ylabel('Normalized Amplitude (-1 to 1)') 
title('Time Domain Plot of Sound') 
%Analyze the frequency components. 
y=2*abs(fft(data))/length(data); 
disp(fft(data));
%Remove non-relevant data. 
y = y(1:end/2); 
%Calculate the maximum frequency that can be perceived. 
f_nyquist = Fs/2; 
%Generate the frequency vector that corresponds with y 
x=linspace(0,f_nyquist,length(y)); 
%Find strongest magnitude 
[y_max index] = max(y); 
%Look up the frequency that corresponds with the strongest magnitude 
f_principle = x(index); 
%Plot frequency versus frequency componant magnitude, circle f_max 
figure 
plot(x,y,f_principle,y_max,'o') 
xlabel('Frequency (Hz)') 
ylabel('Normalized Magnitude (0-1)') 
title('Frequency Domain Plot of Sound')
Thanks Alex

Coordinator
Jun 29, 2010 at 7:44 AM

Hi Alex,

The last functional code changes in the FFT classes date back to 2007, so we both seem to be using essentially the same Iridium code base.

Thanks for the code. I've just checked it, unfortunately I again got the same result in Math.NET Iridium as in Matlab's "fft(data)" as printed by the disp call in your Matlab code.

data is real-only and odd, hence its frequency space is expected to be imaginary-only and odd.
Indeed, both Matlab and Math.NET Iridium confirm and return the same imag-only odd frequency space with 4 peaks for both positive and (wrapped-around) negative frequencies.

Of course you'll have to apply the same processing you do in your Matlab script after calling fft in Iridium as well in order to get the same result if needed.

Can you confirm you get the same result in Iridium and Matlab with the two code snippets I've posted above?

Thanks,
Chris

Jun 29, 2010 at 10:28 AM

Hi Chris,

I get the same results, so it's my code or at least how I am plotting my data!

Just a few questions on fourier(as a developer I am trying to catch up a bit on the maths!)

Should there always be a peak at the start and finish if so why ?

How should I plot the real and imaginary numbers after they have be fouriered ?

Many Thanks

Alex