📄 fouriertransform.cs
字号:
// sum source elements
for (int k = 0; k < m; k++)
{
cos = System.Math.Cos(k * arg);
sin = System.Math.Sin(k * arg);
dst[j].Re += (data[i, k].Re * cos - data[i, k].Im * sin);
dst[j].Im += (data[i, k].Re * sin + data[i, k].Im * cos);
}
}
// copy elements
if (direction == Direction.Forward)
{
// devide also for forward transform
for (int j = 0; j < m; j++)
{
data[i, j].Re = dst[j].Re / m;
data[i, j].Im = dst[j].Im / m;
}
}
else
{
for (int j = 0; j < m; j++)
{
data[i, j].Re = dst[j].Re;
data[i, j].Im = dst[j].Im;
}
}
}
// process columns
for (int j = 0; j < m; j++)
{
for (int i = 0; i < n; i++)
{
dst[i] = Complex.Zero;
arg = -(int)direction * 2.0 * System.Math.PI * (double)i / (double)n;
// sum source elements
for (int k = 0; k < n; k++)
{
cos = System.Math.Cos(k * arg);
sin = System.Math.Sin(k * arg);
dst[i].Re += (data[k, j].Re * cos - data[k, j].Im * sin);
dst[i].Im += (data[k, j].Re * sin + data[k, j].Im * cos);
}
}
// copy elements
if (direction == Direction.Forward)
{
// devide also for forward transform
for (int i = 0; i < n; i++)
{
data[i, j].Re = dst[i].Re / n;
data[i, j].Im = dst[i].Im / n;
}
}
else
{
for (int i = 0; i < n; i++)
{
data[i, j].Re = dst[i].Re;
data[i, j].Im = dst[i].Im;
}
}
}
}
/// <summary>
/// One dimensional Fast Fourier Transform
/// </summary>
///
/// <param name="data">Data to transform</param>
/// <param name="direction">Transformation direction</param>
///
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
int m = Tools.Log2(n);
// reorder data first
ReorderData(data);
// compute FFT
int tn = 1, tm;
for (int k = 1; k <= m; k++)
{
Complex[] rotation = FourierTransform.GetComplexRotation(k, direction);
tm = tn;
tn <<= 1;
for (int i = 0; i < tm; i++)
{
Complex t = rotation[i];
for (int even = i; even < n; even += tn)
{
int odd = even + tm;
Complex ce = data[even];
Complex co = data[odd];
double tr = co.Re * t.Re - co.Im * t.Im;
double ti = co.Re * t.Im + co.Im * t.Re;
data[even].Re += tr;
data[even].Im += ti;
data[odd].Re = ce.Re - tr;
data[odd].Im = ce.Im - ti;
}
}
}
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
}
/// <summary>
/// Two dimensional Fast Fourier Transform
/// </summary>
///
/// <param name="data">Data to transform</param>
/// <param name="direction">Transformation direction</param>
///
public static void FFT2(Complex[,] data, Direction direction)
{
int k = data.GetLength(0);
int n = data.GetLength(1);
// check data size
if (
(!Tools.IsPowerOf2(k)) ||
(!Tools.IsPowerOf2(n)) ||
(k < minLength) || (k > maxLength) ||
(n < minLength) || (n > maxLength)
)
{
throw new ArgumentException();
}
// process rows
Complex[] row = new Complex[n];
for (int i = 0; i < k; i++)
{
// copy row
for (int j = 0; j < n; j++)
row[j] = data[i, j];
// transform it
FourierTransform.FFT(row, direction);
// copy back
for (int j = 0; j < n; j++)
data[i, j] = row[j];
}
// process columns
Complex[] col = new Complex[k];
for (int j = 0; j < n; j++)
{
// copy column
for (int i = 0; i < k; i++)
col[i] = data[i, j];
// transform it
FourierTransform.FFT(col, direction);
// copy back
for (int i = 0; i < k; i++)
data[i, j] = col[i];
}
}
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[,][] complexRotation = new Complex[maxBits, 2][];
// Get array, indicating which data members should be swapped before FFT
private static int[] GetReversedBits(int numberOfBits)
{
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
// check if the array is already calculated
if (reversedBits[numberOfBits - 1] == null)
{
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
// calculate the array
for (int i = 0; i < n; i++)
{
int oldBits = i;
int newBits = 0;
for (int j = 0; j < numberOfBits; j++)
{
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
}
rBits[i] = newBits;
}
reversedBits[numberOfBits - 1] = rBits;
}
return reversedBits[numberOfBits - 1];
}
// Get rotation of complex number
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
{
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
// check if the array is already calculated
if (complexRotation[numberOfBits - 1, directionIndex] == null)
{
int n = 1 << (numberOfBits - 1);
double uR = 1.0;
double uI = 0.0;
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
double t;
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
{
rotation[i] = new Complex(uR, uI);
t = uR * wI + uI * wR;
uR = uR * wR - uI * wI;
uI = t;
}
complexRotation[numberOfBits - 1, directionIndex] = rotation;
}
return complexRotation[numberOfBits - 1, directionIndex];
}
// Reorder data for FFT using
private static void ReorderData(Complex[] data)
{
int len = data.Length;
// check data length
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException();
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
{
int s = rBits[i];
if (s > i)
{
Complex t = data[i];
data[i] = data[s];
data[s] = t;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -