137 lines
3.8 KiB
C#
137 lines
3.8 KiB
C#
using System;
|
||||
|
|
using UnityEngine;
|
|||
|
|
using System.Numerics;
|
|||
|
|
|
|||
|
|
public class FastFourierTransform : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// A fast Fourier transform (FFT) is an algorithm that computes the discrete Fourier transform (DFT) of a sequence.
|
|||
|
|
/// It converts a signal from its original domain (often time or space) to a representation in the frequency domain
|
|||
|
|
/// </summary>
|
|||
|
|
///
|
|||
|
|
|
|||
|
|
//the FFT returns a complex array of numbers given a input array of complex numbers.
|
|||
|
|
public static Complex[] FFT(Complex[] input, bool invert)
|
|||
|
|
{
|
|||
|
|
//in case there is only one element
|
|||
|
|
if (input.Length == 1)
|
|||
|
|
{
|
|||
|
|
return new Complex[] { input[0] };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//for more elements we need to otain the lenght of the input data stream
|
|||
|
|
int length = input.Length;
|
|||
|
|
|
|||
|
|
//half will be the half of the lenght
|
|||
|
|
int half = length / 2;
|
|||
|
|
|
|||
|
|
//this is the result of the FFT
|
|||
|
|
Complex[] result = new Complex[length];
|
|||
|
|
|
|||
|
|
// factor that goes in the
|
|||
|
|
double factorEXP = -2.0 * Math.PI / length;
|
|||
|
|
|
|||
|
|
//in case we want to invert the factor
|
|||
|
|
if (invert)
|
|||
|
|
{
|
|||
|
|
factorEXP = -factorEXP;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
//
|
|||
|
|
// Cooley–Tukey algorithm. This is a divide and conquer algorithm that recursively breaks down a DFT of any composite size N = N1N2 into many smaller DFTs of sizes N1 and N2,
|
|||
|
|
// it is divided into even and odd components
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
//even
|
|||
|
|
Complex[] evens = new Complex[half];
|
|||
|
|
for (int i = 0; i < half; i++)
|
|||
|
|
{
|
|||
|
|
evens[i] = input[2 * i];
|
|||
|
|
}
|
|||
|
|
//FFT recursive call
|
|||
|
|
Complex[] evenResult = FFT(evens, invert);
|
|||
|
|
|
|||
|
|
//odd
|
|||
|
|
Complex[] odds = evens;
|
|||
|
|
for (int i = 0; i < half; i++)
|
|||
|
|
{
|
|||
|
|
odds[i] = input[2 * i + 1];
|
|||
|
|
}
|
|||
|
|
// FFT recursive call
|
|||
|
|
Complex[] oddResult = FFT(odds, invert);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// final algorithm
|
|||
|
|
// N/2-1 N/2-1
|
|||
|
|
// FFT_k= SUM X_2n ·e^(-2*pi*(2n)*k)/(N/2) + SUM X_2n+1 ·e^(-2*pi*(2n+1)*k)/(N/2)
|
|||
|
|
// 0 0
|
|||
|
|
//
|
|||
|
|
// = Even_k + O_k·e^(-2*pi**k)/(N)
|
|||
|
|
|
|||
|
|
for (int k = 0; k < half; k++)
|
|||
|
|
{
|
|||
|
|
double factor_K = factorEXP * k;
|
|||
|
|
|
|||
|
|
// odd part & this is the second part that is added module 1 argument factor_k
|
|||
|
|
Complex oddComponent = oddResult[k] * new Complex(1*Math.Cos(factor_K), 1*Math.Sin(factor_K));
|
|||
|
|
|
|||
|
|
//first part of the chart
|
|||
|
|
result[k] = evenResult[k] + oddComponent;
|
|||
|
|
//second part of the chart
|
|||
|
|
result[k + half] = evenResult[k] - oddComponent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//reutrn the values (complex). To show FFT we need to display module or "abs" of the complex number
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static Complex[] doubleToComplex(double[] inp)
|
|||
|
|
{
|
|||
|
|
Complex[] outp = new Complex[inp.Length];
|
|||
|
|
|
|||
|
|
//convert to complex number
|
|||
|
|
for (int ii = 0; ii < inp.Length; ii++)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
outp[ii] = new Complex(inp[ii], 0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return outp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// maximum and minimum funtions for double arrays
|
|||
|
|
/// </summary>
|
|||
|
|
|
|||
|
|
public static double MaxD(double[] inp)
|
|||
|
|
{
|
|||
|
|
double outp = -1e10;
|
|||
|
|
|
|||
|
|
for (int ii = 0; ii < inp.Length; ii++)
|
|||
|
|
{
|
|||
|
|
if (inp[ii] > outp)
|
|||
|
|
{
|
|||
|
|
outp = inp[ii];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return outp;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static double MinD(double[] inp)
|
|||
|
|
{
|
|||
|
|
double outp = 1e10;
|
|||
|
|
|
|||
|
|
for (int ii = 0; ii < inp.Length; ii++)
|
|||
|
|
{
|
|||
|
|
if (inp[ii] < outp)
|
|||
|
|
{
|
|||
|
|
outp = inp[ii];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return outp;
|
|||
|
|
}
|
|||
|
|
}
|