Majickal Majickal - 2 months ago 17
C# Question

Accessing processed values from FFT

I am attempting to use Lomont FFT in order to return complex numbers to build a spectrogram / spectral density chart using c#.

I am having trouble understanding how to return values from the class.
Here is the code I have put together thus far which appears to be working.

int read = 0;
Double[] data;
byte[] buffer = new byte[1024];

FileStream wave = new FileStream(args[0], FileMode.Open, FileAccess.Read);
read = wave.Read(buffer, 0, 44);
read = wave.Read(buffer, 0, 1024);
data = new Double[read];


for (int i = 0; i < read; i+=2)
{
data[i] = BitConverter.ToInt16(buffer, i) / 32768.0;
Console.WriteLine(data[i]);
}
LomontFFT LFFT = new LomontFFT();
LFFT.FFT(data, true);


What I am not clear on is, how to return/access the values from Lomont FFT implementation back into my application (console)?

Being pretty new to c# development, I'm thinking I am perhaps missing a fundamental aspect of understanding regarding how to retrieve processed values from the instance of the Lomont Class, or perhaps even calling it incorrectly.

Console.WriteLine(LFFT.A); // Returns 0
Console.WriteLine(LFFT.B); // Returns 1


I have been searching for a code snippet or explanation of how to do this, but so far have come up with nothing that I understand or explains this particular aspect of the issue I am facing. Any guidance would be greatly appreciated.

A subset of the results held in
data
array noted in the code above can be found below and based on my current understanding, appear to be valid:

0.00531005859375
0.0238037109375
0.041473388671875
0.0576171875
0.07183837890625
0.083465576171875
0.092193603515625
0.097625732421875
0.099639892578125
0.098114013671875
0.0931396484375
0.0848388671875
0.07354736328125
0.05963134765625
0.043609619140625
0.026031494140625
0.007476806640625
-0.011260986328125
-0.0296630859375
-0.047027587890625
-0.062713623046875
-0.076141357421875
-0.086883544921875
-0.09454345703125
-0.098785400390625
-0.0994873046875
-0.0966796875
-0.090362548828125
-0.080810546875
-0.06842041015625
-0.05352783203125
-0.036712646484375
-0.0185546875


What am I actually attempting to do? (perspective)

I am looking to load a wave file into a console application and return a spectrogram/spectral density chart/image as a jpg/png for further processing.

The wave files I am reading are mono in format




UPDATE 1

I Receive slightly different results depending on which FFT is used.

Using RealFFT

for (int i = 0; i < read; i+=2)
{
data[i] = BitConverter.ToInt16(buffer, i) / 32768.0;
//Console.WriteLine(data[i]);
}

LomontFFT LFFT = new LomontFFT();
LFFT.RealFFT(data, true);

for (int i = 0; i < buffer.Length / 2; i++)
{
System.Console.WriteLine("{0}",
Math.Sqrt(data[2 * i] * data[2 * i] + data[2 * i + 1] * data[2 * i + 1]));
}


Partial Result of RealFFT

0.314566983321381
0.625242818210924
0.30314888696868
0.118468857708093
0.0587697011760449
0.0369034115568654
0.0265842582236275
0.0207195964060356
0.0169601273233317
0.0143745438577886
0.012528799609089
0.0111831275153128
0.0102313284519146
0.00960198279358434
0.00920236001619566


Using FFT

for (int i = 0; i < read; i+=2)
{
data[i] = BitConverter.ToInt16(buffer, i) / 32768.0;
//Console.WriteLine(data[i]);
}

double[] bufferB = new double[2 * data.Length];

for (int i = 0; i < data.Length; i++)
{
bufferB[2 * i] = data[i];
bufferB[2 * i + 1] = 0;
}

LomontFFT LFFT = new LomontFFT();
LFFT.FFT(bufferB, true);

for (int i = 0; i < bufferB.Length / 2; i++)
{
System.Console.WriteLine("{0}",
Math.Sqrt(bufferB[2 * i] * bufferB[2 * i] + bufferB[2 * i + 1] * bufferB[2 * i + 1]));
}


Partial Result of FFT:

0.31456698332138
0.625242818210923
0.303148886968679
0.118468857708092
0.0587697011760447
0.0369034115568653
0.0265842582236274
0.0207195964060355
0.0169601273233317
0.0143745438577886
0.012528799609089
0.0111831275153127
0.0102313284519146
0.00960198279358439
0.00920236001619564

Answer

Looking at the LomontFFT.FFT documentation:

Compute the forward or inverse Fourier Transform of data, with data containing complex valued data as alternating real and imaginary parts. The length must be a power of 2. The data is modified in place.

This tells us a few things. First the function is expecting complex-valued data whereas your data is real. A quick fix for this is to create another buffer of twice the size and setting all the imaginary parts to 0:

double[] buffer = new double[2*data.Length];
for (int i=0; i<data.Length; i++)
{
  buffer[2*i] = data[i];
  buffer[2*i+1] = 0;
}

The documentation also tells us that the computation is done in place. That means that after the call to FFT returns, the input array is replaced with the computed result. You could thus print the spectrum with:

  LomontFFT LFFT = new LomontFFT();
  LFFT.FFT(buffer, true);

  for (int i = 0; i < buffer.Length/2; i++)
  {
    System.Console.WriteLine("{0}",
      Math.Sqrt(buffer[2*i]*buffer[2*i]+buffer[2*i+1]*buffer[2*i+1]));
  }

Note since your input data is real valued you could also use LomontFFT.RealFFT.

Comments