Dependencies:   DMSupport DMemWin

Revision:
0:08606a13a816
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/embedded/fft.cpp	Thu Jun 02 05:04:57 2016 +0000
@@ -0,0 +1,172 @@
+//   Include declaration file
+#include "fft.h"
+
+//   FORWARD FOURIER TRANSFORM
+//     Input  - input data
+//     Output - transform result
+//     N      - length of both input data and result
+bool CFFT::Forward(const complex *const Input, complex *const Output, const unsigned int N)
+{
+	//   Check input parameters
+	if (!Input || !Output || N < 1 || N & (N - 1))
+		return false;
+	//   Initialize data
+	Rearrange(Input, Output, N);
+	//   Call FFT implementation
+	Perform(Output, N);
+	//   Succeeded
+	return true;
+}
+
+//   FORWARD FOURIER TRANSFORM, INPLACE VERSION
+//     Data - both input data and output
+//     N    - length of input data
+bool CFFT::Forward(complex *const Data, const unsigned int N)
+{
+	//   Check input parameters
+	if (!Data || N < 1 || N & (N - 1))
+		return false;
+	//   Rearrange
+	Rearrange(Data, N);
+	//   Call FFT implementation
+	Perform(Data, N);
+	//   Succeeded
+	return true;
+}
+
+//   INVERSE FOURIER TRANSFORM
+//     Input  - input data
+//     Output - transform result
+//     N      - length of both input data and result
+//     Scale  - if to scale result
+bool CFFT::Inverse(const complex *const Input, complex *const Output, const unsigned int N, const bool Scale /* = true */)
+{
+	//   Check input parameters
+	if (!Input || !Output || N < 1 || N & (N - 1))
+		return false;
+	//   Initialize data
+	Rearrange(Input, Output, N);
+	//   Call FFT implementation
+	Perform(Output, N, true);
+	//   Scale if necessary
+	if (Scale)
+		CFFT::Scale(Output, N);
+	//   Succeeded
+	return true;
+}
+
+//   INVERSE FOURIER TRANSFORM, INPLACE VERSION
+//     Data  - both input data and output
+//     N     - length of both input data and result
+//     Scale - if to scale result
+bool CFFT::Inverse(complex *const Data, const unsigned int N, const bool Scale /* = true */)
+{
+	//   Check input parameters
+	if (!Data || N < 1 || N & (N - 1))
+		return false;
+	//   Rearrange
+	Rearrange(Data, N);
+	//   Call FFT implementation
+	Perform(Data, N, true);
+	//   Scale if necessary
+	if (Scale)
+		CFFT::Scale(Data, N);
+	//   Succeeded
+	return true;
+}
+
+//   Rearrange function
+void CFFT::Rearrange(const complex *const Input, complex *const Output, const unsigned int N)
+{
+	//   Data entry position
+	unsigned int Target = 0;
+	//   Process all positions of input signal
+	for (unsigned int Position = 0; Position < N; ++Position)
+	{
+		//  Set data entry
+		Output[Target] = Input[Position];
+		//   Bit mask
+		unsigned int Mask = N;
+		//   While bit is set
+		while (Target & (Mask >>= 1))
+			//   Drop bit
+			Target &= ~Mask;
+		//   The current bit is 0 - set it
+		Target |= Mask;
+	}
+}
+
+//   Inplace version of rearrange function
+void CFFT::Rearrange(complex *const Data, const unsigned int N)
+{
+	//   Swap position
+	unsigned int Target = 0;
+	//   Process all positions of input signal
+	for (unsigned int Position = 0; Position < N; ++Position)
+	{
+		//   Only for not yet swapped entries
+		if (Target > Position)
+		{
+			//   Swap entries
+			const complex Temp(Data[Target]);
+			Data[Target] = Data[Position];
+			Data[Position] = Temp;
+		}
+		//   Bit mask
+		unsigned int Mask = N;
+		//   While bit is set
+		while (Target & (Mask >>= 1))
+			//   Drop bit
+			Target &= ~Mask;
+		//   The current bit is 0 - set it
+		Target |= Mask;
+	}
+}
+
+//   FFT implementation
+void CFFT::Perform(complex *const Data, const unsigned int N, const bool Inverse /* = false */)
+{
+	const double pi = Inverse ? 3.14159265358979323846 : -3.14159265358979323846;
+	//   Iteration through dyads, quadruples, octads and so on...
+	for (unsigned int Step = 1; Step < N; Step <<= 1)
+	{
+		//   Jump to the next entry of the same transform factor
+		const unsigned int Jump = Step << 1;
+		//   Angle increment
+		const double delta = pi / double(Step);
+		//   Auxiliary sin(delta / 2)
+		const double Sine = sin(delta * .5);
+		//   Multiplier for trigonometric recurrence
+		const complex Multiplier(-2. * Sine * Sine, sin(delta));
+		//   Start value for transform factor, fi = 0
+		complex Factor(1.);
+		//   Iteration through groups of different transform factor
+		for (unsigned int Group = 0; Group < Step; ++Group)
+		{
+			//   Iteration within group
+			for (unsigned int Pair = Group; Pair < N; Pair += Jump)
+			{
+				//   Match position
+				const unsigned int Match = Pair + Step;
+				//   Second term of two-point transform
+				const complex Product(Factor * Data[Match]);
+				//   Transform for fi + pi
+				Data[Match] = Data[Pair] - Product;
+				//   Transform for fi
+				Data[Pair] += Product;
+			}
+			//   Successive transform factor via trigonometric recurrence
+			Factor = Multiplier * Factor + Factor;
+		}
+	}
+}
+
+//   Scaling of inverse FFT result
+void CFFT::Scale(complex *const Data, const unsigned int N)
+{
+	const double Factor = 1. / double(N);
+	//   Scale all data entries
+	for (unsigned int Position = 0; Position < N; ++Position)
+		Data[Position] *= Factor;
+}
+