This is a very basic version of a Discrete Fourier Transformation.
Not suitable for real-time analysis
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| namespace SimpleDFT | |
| { | |
| class SimpleDFT | |
| { | |
| static void Main(string[] args) | |
| { | |
| var s = new double[1024]; | |
| for(int i=0; i<s.Length; i++) | |
| s[i] = Math.Cos(2 * Math.PI * 1 / 1024 * i); | |
| var d = DFT(s); | |
| double normalizer = 1.0 / s.Length * 2; | |
| for (int i = 0; i < d.Item1.Length; i++) | |
| { | |
| d.Item1[i] = d.Item1[i] * normalizer; | |
| d.Item2[i] = d.Item2[i] * normalizer; | |
| } | |
| var output = IDFT(d.Item1, d.Item2); | |
| } | |
| /// <summary> | |
| /// Provides the Discrete Fourier Transform for a real-valued input signal | |
| /// </summary> | |
| /// <param name="input">the signal to transform</param> | |
| /// <param name="partials">the maximum number of partials to calculate. If not value is given it defaults to input/2</param> | |
| /// <returns>The Cos and Sin components of the signal, respectively</returns> | |
| public static Tuple<double[], double[]> DFT(double[] input, int partials = 0) | |
| { | |
| int len = input.Length; | |
| double[] cosDFT = new double[len / 2 + 1]; | |
| double[] sinDFT = new double[len / 2 + 1]; | |
| if (partials == 0) | |
| partials = len / 2; | |
| for (int n = 0; n <= partials ; n++) | |
| { | |
| double cos = 0.0; | |
| double sin = 0.0; | |
| for (int i = 0; i < len; i++) | |
| { | |
| cos += input[i] * Math.Cos(2 * Math.PI * n / len * i); | |
| sin += input[i] * Math.Sin(2 * Math.PI * n / len * i); | |
| } | |
| cosDFT[n] = cos; | |
| sinDFT[n] = sin; | |
| } | |
| return new Tuple<double[], double[]>(cosDFT, sinDFT); | |
| } | |
| /// <summary> | |
| /// Takes the real-valued Cos and Sin components of Fourier transformed signal and reconstructs the time-domain signal | |
| /// </summary> | |
| /// <param name="cos">Array of cos components, containing frequency components from 0 to pi. sin.Length must match cos.Length</param> | |
| /// <param name="sin">Array of sin components, containing frequency components from 0 to pi. sin.Length must match cos.Length</param> | |
| /// <param name="len"> | |
| /// The length of the output signal. | |
| /// If len < (partials-1)*2 then frequency data will be lost in the output signal. | |
| /// if no len parameter is given it defaults to (partials-1)*2 | |
| /// </param> | |
| /// <returns>the real-valued time-domain signal</returns> | |
| public static double[] IDFT(double[] cos, double[] sin, int len = 0) | |
| { | |
| if (cos.Length != sin.Length) throw new ArgumentException("cos.Length and sin.Length bust match!"); | |
| if (len == 0) | |
| len = (cos.Length - 1) * 2; | |
| double[] output = new double[len]; | |
| int partials = sin.Length; | |
| if (partials > len / 2) | |
| partials = len / 2; | |
| for (int n = 0; n <= partials; n++) | |
| { | |
| for (int i = 0; i < len; i++) | |
| { | |
| output[i] += Math.Cos(2 * Math.PI * n / len * i) * cos[n]; | |
| output[i] += Math.Sin(2 * Math.PI * n / len * i) * sin[n]; | |
| } | |
| } | |
| return output; | |
| } | |
| } | |
| } |