using CommonLib.math; using System; using System.Collections.Generic; using System.Text; namespace CommonLib.math { /// /// 快速傅里叶变换 /// public class FFT { /// /// 获取FFT数列 /// /// 数字信号数组 /// 获取结果的长度,数字信号的数组长度需要不小于该值的两倍,否则将无法正常计算 /// public double[] GetFftValueFromChData(short[] chdata, int result_lenth) { double[] result = new double[0]; double[] allvalue = new double[0];//快速计算结果为双倍长度 int n = result_lenth * 2;// 470;// this.allChanData.Length; short[] x = chdata;//被计算的数组 complex[] y = new complex[n];//接收复数结果的数组 if (chdata.Length >= n) { result = new Double[n];//接收幅值结果的数组 y = airthm.dft(x, n);//重点耗时项 allvalue = airthm.amplitude(y, n); result = new double[allvalue.Length / 2]; for (int i = 0; i < result.Length; i++) { result[i] = allvalue[i]; } } else { } return result; } //double [,]X_sn; double pi = System.Math.PI; public double[,] Wcreat(int N, int FFT_IFFT_elect) { double[,] Wp = new double[2, N / 2]; if (FFT_IFFT_elect == 0) { for (int i = 0; i < N / 2; i++) { Wp[0, i] = System.Math.Cos(2 * pi / N * i); Wp[1, i] = System.Math.Sin(-2 * pi / N * i); } } else { for (int i = 0; i < N / 2; i++) { Wp[0, i] = System.Math.Cos(2 * pi / N * i); Wp[1, i] = System.Math.Sin(2 * pi / N * i); } } return Wp; } /// /// 进行傅里叶变换 /// /// 数列/原始信号 /// 数列的长度 /// /// public double[,] FFT_T(double[,] X_sn, int N, int FFT_IFFT_elect) { double[,] Wp = new double[2, N / 2]; FFT Xn = new FFT(); Wp = Xn.Wcreat(N, FFT_IFFT_elect); //测试 // double tem = System.Math.Log(N, 2); int M = (int)tem; for (int L = 1; L <= M; L++) { double M_Ld = System.Math.Pow(2, M - L);//计算2的M-L次方 int M_L = (int)M_Ld; double L_1d = System.Math.Pow(2, L - 1); int L_1 = (int)L_1d; for (int j = 0; j < M_L; j++) { int J = j * (int)System.Math.Pow(2, L); for (int k = 0; k < L_1; k++) { double[] T = new double[2]; double p_k = k * (int)System.Math.Pow(2, (M - L)); int P = (int)p_k; T = Xn.C_multi(X_sn[0, J + L_1 + k], X_sn[1, J + L_1 + k], Wp[0, P], Wp[1, P]); X_sn[0, J + L_1 + k] = X_sn[0, J + k] - T[0]; X_sn[1, J + L_1 + k] = X_sn[1, J + k] - T[1]; X_sn[0, J + k] = X_sn[0, J + k] + T[0]; X_sn[1, J + k] = X_sn[1, J + k] + T[1]; } } } return X_sn; } public double[] C_multi(double a, double b, double c, double d) { double[] R_value = new double[2]; R_value[0] = a * c - b * d; R_value[1] = a * d + b * c; return R_value; } public int R_value(int num, int M)//将一个数取反 { double R_num = 0; for (int i = M; i > 0; i--) { double tem = System.Math.Pow(2, i); int t = (int)tem; int j = (num % t) / (t / 2); R_num = R_num + j * System.Math.Pow(2, M - i); } return (int)R_num; } public double[,] R_Xn(double[,] xn, int N) { double tem = System.Math.Log(N, 2);//求得序列点数对2为底的对数 例:N=4则tem=2,N=8则tem=3; int M = (int)tem;//将该对数取整 FFT R_fft = new FFT(); for (int i = 0; i < N / 2; i++) { int tem1 = R_fft.R_value(i, M);//把索引各种倒换,得出一个换位置的索引,还没看懂 double[] tem2 = new double[2]; if (tem1 != i)//防止计算出的索引值与i重合造成计算的浪费 { tem2[0] = xn[0, i];//将索引位置的值互换 tem2[1] = xn[1, i]; xn[0, i] = xn[0, tem1]; xn[1, i] = xn[1, tem1]; xn[0, tem1] = tem2[0]; xn[1, tem1] = tem2[1]; } } return xn; } } }