2

I am trying to find a solution for some weeks now and I really have read all threads related with this topic, so I really hope someone can help me out with this.

What I want to do is to use a wave-file as input, fourier-transform it and take these values to compare them to another file and get the difference.

The challenge I've been working on so long is to get that Fourier-transform to work.

Instead of giving me reasonable results I only get NaN-values.

I have the following code:

public FFTPerformer(float[] soundvalues)
    {
        buffer = new System.Numerics.Complex[4096];
        try {
            for (int i = 0; i < 4096; i++)
            {
                System.Numerics.Complex tmp = new System.Numerics.Complex(soundvalues[i], 0);
                buffer[i] = tmp;
            }
        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show("Es ist ein Fehler bei der Konvertierung des float arrays zum Complex-Array aufgetreten; " + ex.Message);
        }
    }

The 4096 is normally replaced by a higher number which is still a power of two, but it doesn't even work with that one.

public void performFFT()
    {
        try
        {
            MathNet.Numerics.IntegralTransforms.Fourier.Forward(buffer, MathNet.Numerics.IntegralTransforms.FourierOptions.Matlab);
        }
        catch(Exception ex)
        {
            System.Windows.MessageBox.Show("Fehler: " + ex.Message);
        }
    }

Little more detailed description: I set the length for 4096 values, because that is a factor of two and this length is only for test purposes, so that this is a little bit faster to check than using the original soundfile of some millions of values ;) so this is only like this, as long the algorithm isn't proved to work. This is also the reason for the weird for-loop. Even tough Math.Net uses Bluestein's algorithm to calculate, try it with factor of two arrays anyway, because they just should work even if they use any other algorithm atm.

tried to get an error-message with that try-catch because of Float-Decimal conversion, but it doesn't raise any.

My problem is now, that I send 4096 Complex numbers in that fft, all of them have Y=0, but X is depending on the audio-file (read in another thread that Y-values are not needed for audio-fft so you should set them to 0). All of the X-values are normal float-numbers, no NaNs. But still, the FFT just gives back an array full of NaNs.

I first tried to do the conversion to System.Numerics.Complex implicit, which didn't work out, so I that that construct with the tmp variable.

EDIT: I ended up reading even more articles on FFT algorithms. Now I still get my soundvalues als float and convert them to a Complex-Array. I checked all conversion-steps to consistency and it's fine in that area. So my question is if I really only do have to use this

MathNet.Numerics.IntegralTransforms.Fourier.Forward(buffer, MathNet.Numerics.IntegralTransforms.FourierOptions.Matlab);

or if I need somehting before that to do an clean FFT in Math.NET

webfreak1364
  • 21
  • 1
  • 3
  • Hey, Welcome to SO! German is OK for me, but you should still translate your error messages to English when posting here. – Marcus Müller Feb 21 '16 at 18:34
  • 1
    The result of an FFT being all NaN indicates that at least one input value was NaN. – Marcus Müller Feb 21 '16 at 18:38
  • If you mean [Math.net](https://stackoverflow.com/tags/mathnet/info) - you can add the tag for it - it may help. – ispiro Feb 21 '16 at 20:19
  • @MarcusMüller: thank you, did just forget to change it. will edit it now. I checked the input for NaN but there wasn't one but I'll check again tomorrow. – webfreak1364 Feb 23 '16 at 19:04

1 Answers1

0

Why are you allocating the buffer with 4096 elements first, and then allocate a Complex for every element? That looks wrong.

Just set buffer[i].real = soundvalues[i], .imag=0 (in the sense, not literallly. I don't "speak" C#).

EDIT:

https://msdn.microsoft.com/en-us/library/ee259559%28v=vs.110%29.aspx explains that there's an implicit conversion from Decimal to Complex, setting the resulting complex to (Decimal + 0i); which means that you should just

for (int i = 0; i < 4096; i++)
{
    buffer[i] = soundvalues[i];
}

My suspicion is that your soundvalues still contain NaNs; maybe you've got a problem with your input?

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • 1
    The constructor does this already. (`var z = new Complex(float real, float imag)`). But indeed, the problem here is that a static buffer of 4096 complex numbers is being allocated, and the length of the `float[] soundvalues` is not being taken into account at all. He probably meant to slice `soundvalues[]` into `n` sub-arrays of length 4096 and fourier-transform each of them? – Maximilian Gerhardt Feb 21 '16 at 18:47
  • 1
    exactly. And `new Type[4096]` allocates 4096 elements, so each element is already there; since there is an implicit conversion from Decimal to Complex, https://msdn.microsoft.com/en-us/library/ee259559%28v=vs.110%29.aspx , Op should just `buffer[i] = soundvalues[i]`. – Marcus Müller Feb 21 '16 at 18:50
  • @MarcusMüller I worte an longer answer in the post, which explains, why I'm doing it this way :) – webfreak1364 Feb 23 '16 at 20:17