/// <summary> /// 一次元FFT /// </summary> /// <param name="src"></param> /// <param name="direction"></param> /// <returns></returns> public static Complex[] FFT(Complex[] src, FourierDirectionEnum direction) { p.MaxDegreeOfParallelism = System.Environment.ProcessorCount; Complex[] dest = fft(src, direction); //ComplexArray.Scale(dest, 1 / Math.Sqrt(src.Length)); for (int i = 0; i < dest.Length; i++) { dest[i] *= 1 / Math.Sqrt(src.Length); } return(dest); }
private static Complex[] fft(Complex[] src, FourierDirectionEnum direction) { sign = direction == FourierDirectionEnum.Forward ? -1 : 1; return(fft(src)); }
/// <summary> /// 2次元FFT /// </summary> /// <param name="src"></param> /// <param name="direction"></param> /// <returns></returns> public static Complex[][] FFT(Complex[][] src, double[][] filter, FourierDirectionEnum direction) { if (src == null || src.Length == 0 || src[0] == null || src[0].Length == 0) { return(null); } int centerX = src[0].Length / 2, centerY = src.Length / 2; //まずFilterを作用させる && 4分割して組みなおす Complex[][] src2 = new Complex[src.Length][]; for (int i = 0; i < src.Length; i++) { src2[i] = new Complex[src[i].Length]; } for (int i = 0; i < src.Length; i++) { for (int j = 0; j < src[i].Length; j++) { if (direction == FourierDirectionEnum.Inverse) { src2[i < centerY ? i + centerY : i - centerY][j < centerX ? j + centerX : j - centerX] = filter == null ? src[i][j] : (1 - filter[i][j]) * src[i][j]; } else { src2[i][j] = filter == null ? src[i][j] : (1 - filter[i][j]) * src[i][j]; } } } src = null; sign = direction == FourierDirectionEnum.Forward ? -1 : 1; FFTdelegate[] d = new FFTdelegate[ThreadTotal]; IAsyncResult[] ar = new IAsyncResult[ThreadTotal]; for (int i = 0; i < ThreadTotal; i++) { d[i] = new FFTdelegate(FFT); } //まず各行ごとにFFT Complex[][] dest1 = new Complex[src2.Length][]; for (int i = 0; i < dest1.Length; i++) { for (int j = 0; j < ThreadTotal && i + j < dest1.Length; j++) { ar[j] = d[j].BeginInvoke(src2[i + j], direction, ref dest1[i + j], null, null);//スレッド起動 } for (int j = 0; j < ThreadTotal && i + j < dest1.Length; j++) { d[j].EndInvoke(ref dest1[i + j], ar[j]);//スレッド終了待ち if (ProgressEvent != null) { ProgressEvent(); } } i += ThreadTotal - 1; } //次に各列ごとにFFT Complex[][] dest2 = new Complex[src2[0].Length][]; for (int i = 0; i < dest2.Length; i++) { dest2[i] = new Complex[src2.Length]; for (int j = 0; j < src2.Length; j++) { dest2[i][j] = dest1[j][i]; } } for (int i = 0; i < dest2.Length; i++) { for (int j = 0; j < ThreadTotal && i + j < dest2.Length; j++) { ar[j] = d[j].BeginInvoke(dest2[i + j], direction, ref dest2[i + j], null, null);//スレッド起動 } for (int j = 0; j < ThreadTotal && i + j < dest2.Length; j++) { d[j].EndInvoke(ref dest2[i + j], ar[j]);//スレッド終了待ち if (ProgressEvent != null) { ProgressEvent(); } } i += ThreadTotal - 1; } //dest2の行と列を入れ替えてdest1に格納し返す for (int i = 0; i < src2.Length; i++) { for (int j = 0; j < src2[0].Length; j++) { dest1[i][j] = dest2[j][i]; } } dest2 = null; if (direction == FourierDirectionEnum.Inverse) { return(dest1); } else //最後に入れ替える必要がある時は { Complex[][] dest3 = new Complex[src2.Length][]; for (int i = 0; i < dest3.Length; i++) { dest3[i] = new Complex[src2[i].Length]; } for (int i = 0; i < src2.Length; i++) { for (int j = 0; j < src2[i].Length; j++) { dest3[i < centerY ? i + centerY : i - centerY][j < centerX ? j + centerX : j - centerX] = dest1[i][j]; } } dest1 = null; return(dest3); } }
private static void FFT(Complex[] src, FourierDirectionEnum direction, ref Complex[] dest) { dest = FFT(src, direction); }
public static Complex[][] FFT(Complex[][] src, FourierDirectionEnum direction) { return(FFT(src, null, direction)); }