/// <summary> /// Thread method for fourier /// Takes destination Af, and set the result using original data, size of data /// starting and ending position of where the thread will do the job /// </summary> /// <param name="Af">Frequency bins</param> /// <param name="data">Data to be processed</param> /// <param name="N">Size of data</param> /// <param name="startPos">Starting position to be processed</param> /// <param name="endPos">Ending position to be processed</param> private static void fourierThread(AmplitudeF[] Af, double[] data, int N, int startPos, int endPos) { for (int f = startPos; f < endPos; f++) { double re = 0; double im = 0; for (int t = 0; t < N; t++) { re += data[t] * Math.Cos(2 * Math.PI * t * f / (double)N); im += data[t] * (-1) * Math.Sin(2 * Math.PI * t * f / (double)N); } Af[f] = new AmplitudeF(re / (double)data.Length, im / (double)data.Length); } }
/// <summary> /// Takes in original data, and a filter /// </summary> /// <param name="data">Input data</param> /// <param name="filter">filter</param> /// <returns>filtered data</returns> public static double[] filter(double[] data, int[] filter) { double[] filteredData = new double[data.Length]; AmplitudeF[] filterF = new AmplitudeF[filter.Length]; for (int i = 0; i < filterF.Length; i++) { filterF[i].re = filter[i]; filterF[i].im = filter[i]; } double[] filterT = FourierTransform.inverseFourier(filterF, filterF.Length); if (data.Length < ThreadSetting.THREAD_THRESHOLD && filter.Length < ThreadSetting.THREAD_THRESHOLD) { for (int i = 0; i < data.Length; i++) { for (int j = 0; j < filterT.Length && j + i < data.Length; j++) { filteredData[i] += data[i + j] * filterT[j]; } } } else { int segment = (int)Math.Ceiling((double)data.Length / (double)ThreadSetting.threadNum); Thread[] threads = new Thread[ThreadSetting.threadNum]; for (int i = 0; i < ThreadSetting.threadNum; i++) { int z = i; if (i < ThreadSetting.threadNum - 1) { threads[z] = new Thread(() => filterThread(filteredData, data, filterT, segment * z, segment * (z + 1))); } else { threads[z] = new Thread(() => filterThread(filteredData, data, filterT, segment * z, data.Length)); } } foreach (Thread t in threads) { t.Start(); } foreach (Thread t in threads) { t.Join(); } } return(filteredData); }
/// <summary> /// Full fourier formula that takes in a set of data point with N samples per second /// </summary> /// <param name="data">Input data</param> /// <param name="N">Size to apply fourier</param> /// <returns>an array of AmplitudeF Af</returns> public static AmplitudeF[] fourier(double[] data, int N) { AmplitudeF[] Af = new AmplitudeF[N]; if (N < ThreadSetting.THREAD_THRESHOLD) { for (int f = 0; f < data.Length; f++) { double re = 0; double im = 0; for (int t = 0; t < N; t++) { re += data[t] * Math.Cos(2 * Math.PI * t * f / (double)N); im += data[t] * (-1) * Math.Sin(2 * Math.PI * t * f / (double)N); } Af[f] = new AmplitudeF(re / (double)data.Length, im / (double)data.Length); } } else { int segment = (int)Math.Ceiling((double)N / (double)ThreadSetting.threadNum); Thread[] threads = new Thread[ThreadSetting.threadNum]; for (int i = 0; i < ThreadSetting.threadNum; i++) { int z = i; if (i < ThreadSetting.threadNum - 1) { threads[z] = new Thread(() => fourierThread(Af, data, N, segment * z, segment * (z + 1))); } else { threads[z] = new Thread(() => fourierThread(Af, data, N, segment * z, data.Length)); } } foreach (Thread t in threads) { t.Start(); } foreach (Thread t in threads) { t.Join(); } } return(Af); }