Module_SignalProcessing_Fourier - vorcyc/Vorcyc.Mathematics GitHub Wiki
Location: Home / Signal processing / Fourier transform
The Vorcyc.Mathematics.SignalProcessing.Fourier namespace provides CPU-side Fourier transforms.
0.10.1 reorganization: The Fourier family has been consolidated under the
Fourier/source folder and theVorcyc.Mathematics.SignalProcessing.Fouriernamespace.Fft,Fft64,RealFft,RealFft64, andStftwere all relocated here fromTransforms/;RealFft,RealFft64, andStftalso moved namespace fromVorcyc.Mathematics.SignalProcessing.Transformsto.Fourier(FftandFft64were already in the Fourier namespace). The legacyRealOnlyFFT_Fp32class has been removed; useRealFft(orFftfor full complex I/O) instead. A shared SoA radix-2 butterfly kernel —FftButterflyFp32/FftButterflyFp64— provides the SIMD and parallel execution paths used byFft,Fft64,RealFft, andRealFft64.
The static FastFourierTransform class remains the high-level entry point for pointer / ComplexFp32-based transforms.
0.10.12: All
FastFourierTransform.Forward/Inverseoverloads (span, array, pointer, in-place — and thereforeITimeDomainSignal.TransformToFrequencyDomain) use the same SoAFftButterflyFp32kernel asFft/RealFftwhen SIMD or parallel is beneficial. Below the SIMD crossover they keep the original scalarFastFourierTransformNormal. The AoSFastFourierTransformSIMD/FastFourierTransformParallelkernels, theFftVersionenum, andFastFourierTransform.Versionhave been removed. UseComputingContext/ComputingScope.0.10.13:
Stft.AveragePeriodogramaverages complete windows only (SciPy/MATLABwelch);Operation.WelchacceptsComputingContext?;RealFft.PowerSpectrumgains context-aware overloads. 0.10.14: SciPy onesided Welch scaling (DC/Nyquist not ×2);RealFft/Fftspectrum APIs gain context overloads; STFT frame-parallel usesNestedFrameFftContext;WindowBuilder.OfTypesupports periodic windows. 0.10.15:FrequencyDomain.IndexToFrequencymaps bins withTransformLength(FFT size), notActualLength(unpadded samples). Zero-pad / Welch no longer yield bogus negative Hz on the upper half of a onesided spectrum. 0.10.18:Fft<T>/RealFft<T>dispatchfloattoFft/RealFftanddoubletoFft64/RealFft64. Mode decomposition uses these facades so sample buffers stay inT.
0.9+: Use
ComputingContextto specify FFT execution strategy (Forward(..., context),Direct(..., context), orComputingScope).
GPU / CUDA: The main package does not include CUDA FFT (
CudaFFT/ ILGPU removed). See GPU policy. For native CPU FFT, see optionalExtensions.FFTW.
All types below are in namespace: Vorcyc.Mathematics.SignalProcessing.Fourier
📒 Contents
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.FastFourierTransform class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.Fft class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.Fft64 class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.Fft<T> class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.RealFft class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.RealFft64 class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.RealFft<T> class
- 🔖 Vorcyc.Mathematics.SignalProcessing.Fourier.Stft class
- 🔖 FftButterflyFp32 / FftButterflyFp64 (internal kernels)
Vorcyc.Mathematics.SignalProcessing.Fourier.FastFourierTransform is a static class for fast Fourier transform (FFT).
-
public static bool Forward(float* input, ComplexFp32* output, int N)- Performs forward FFT, converting real input to complex output.
- Parameters:
-
input: Input data, real sequence (time domain). -
output: Transform result, complex sequence. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(float[] input, int offset, out ComplexFp32[] output, int N)- Performs forward FFT, converting real input to complex output.
- Parameters:
-
input: Input data, real sequence (time domain). -
offset: Offset into the input data. -
output: Transform result, complex sequence. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ReadOnlySpan<float> input, Span<ComplexFp32> output)- Performs forward FFT, converting real input to complex output.
- Parameters:
-
input: Input data, real sequence (time domain). -
output: Transform result, complex sequence.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ComplexFp32* input, ComplexFp32* output, int N)- Performs forward FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (time domain). -
output: Transform result, complex sequence. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ReadOnlySpan<ComplexFp32> input, Span<ComplexFp32> output)- Performs forward FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (time domain). -
output: Transform result, complex sequence.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ComplexFp32[] input, int offset, ComplexFp32[] output, int N)- Performs forward FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (time domain). -
offset: Offset into the input data. -
output: Transform result, complex sequence. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ComplexFp32* data, int N)- Performs forward FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(ComplexFp32[] data, int offset, int N)- Performs forward FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence. -
offset: Offset into the data. -
N: FFT length.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(Span<ComplexFp32> data)- Performs forward FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence.
-
- Returns: Whether the operation succeeded.
-
public static bool Forward(float[] input, int offset, out ComplexFp32[] output, int N, ComputingContext? context)- Context-aware overload of
Forward(float[], int, out ComplexFp32[], int). From 0.10.12 this selects the SoAFftButterflyFp32SIMD / parallel kernel when beneficial, otherwise scalarFastFourierTransformNormal.
- Context-aware overload of
-
public static bool Forward(ReadOnlySpan<float> input, Span<ComplexFp32> output, ComputingContext? context)- Context-aware overload of
Forward(ReadOnlySpan<float>, Span<ComplexFp32>).
- Context-aware overload of
-
public static bool Forward(ReadOnlySpan<ComplexFp32> input, Span<ComplexFp32> output, ComputingContext? context)- Context-aware overload of
Forward(ReadOnlySpan<ComplexFp32>, Span<ComplexFp32>).
- Context-aware overload of
-
public static bool Inverse(ComplexFp32* input, ComplexFp32* output, int N, bool scale = true)- Performs inverse FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (frequency domain). -
output: Transform result, complex sequence (time domain). -
N: Input length. -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(ComplexFp32[] input, int inOffset, out ComplexFp32[] output, int outOffset, int N, bool scale = true)- Performs inverse FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (frequency domain). -
inOffset: Offset into the input data. -
output: Transform result, complex sequence (time domain). -
outOffset: Offset into the output data. -
N: Input length. -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(ReadOnlySpan<ComplexFp32> input, Span<ComplexFp32> output, bool scale = true)- Performs inverse FFT, converting complex input to complex output.
- Parameters:
-
input: Input data, complex sequence (frequency domain). -
output: Transform result, complex sequence (time domain). -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(ComplexFp32* data, int N, bool scale = true)- Performs inverse FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence (frequency domain). -
N: Input length. -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(ComplexFp32[] data, int offset, int N, bool scale = true)- Performs inverse FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence (frequency domain). -
offset: Offset into the data. -
N: Input length. -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(Span<ComplexFp32> data, bool scale = true)- Performs inverse FFT, in-place version.
- Parameters:
-
data: Input and output data, complex sequence (frequency domain). -
scale: Whether to scale; default is true.
-
- Returns: Whether the operation succeeded.
-
public static bool Inverse(ComplexFp32[] input, int inOffset, out ComplexFp32[] output, int outOffset, int N, bool scale, ComputingContext? context)- Context-aware overload of the array
Inverse(...). From 0.10.12 usesFftButterflyFp32when beneficial (same policy asForward).
- Context-aware overload of the array
-
public static bool Inverse(ReadOnlySpan<ComplexFp32> input, Span<ComplexFp32> output, bool scale, ComputingContext? context)- Context-aware overload of
Inverse(ReadOnlySpan<ComplexFp32>, Span<ComplexFp32>, bool).
- Context-aware overload of
-
public static bool Inverse(Span<ComplexFp32> data, bool scale, ComputingContext? context)- Context-aware in-place overload of
Inverse(Span<ComplexFp32>, bool).
- Context-aware in-place overload of
The following example uses several methods of FastFourierTransform, with comments:
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class FastFourierTransformExample
{
public static void Main()
{
// Define input signal
float[] inputSignal = { 0.5f, 0.6f, 0.55f, 0.7f, 0.65f };
// Perform forward FFT
FastFourierTransform.Forward(inputSignal, 0, out var forwardOutput, inputSignal.Length);
Console.WriteLine("Forward FFT Output:");
foreach (var sample in forwardOutput)
{
Console.WriteLine($"Real: {sample.Real}, Imaginary: {sample.Imaginary}");
}
// Perform inverse FFT
FastFourierTransform.Inverse(forwardOutput, 0, out var inverseOutput, 0, forwardOutput.Length);
Console.WriteLine("Inverse FFT Output:");
foreach (var sample in inverseOutput)
{
Console.WriteLine($"Real: {sample.Real}, Imaginary: {sample.Imaginary}");
}
}
}Vorcyc.Mathematics.SignalProcessing.Fourier.Fft is a complex in-place radix-2 FFT for float data. It implements IComplexTransform. The transform is computed in place on separate real / imaginary arrays (structure-of-arrays). ComputingContext-aware overloads dispatch to the shared SIMD / parallel butterfly kernel when the size is large enough to benefit; otherwise they run the scalar decimation-in-frequency butterfly.
-
public int Size { get; }- Gets the FFT size.
-
public Fft(int fftSize = 512)- Constructs an
Fftfor the givenfftSizeand precomputes the twiddle table. FFT size must be a power of two. - Parameters:
-
fftSize: FFT size.
-
- Constructs an
-
public void Direct(float[] re, float[] im) -
public void Direct(Span<float> re, Span<float> im)- Forward FFT in place on the real / imaginary arrays.
- Parameters:
-
re: Real parts (input and output). -
im: Imaginary parts (input and output).
-
-
public void Direct(float[] re, float[] im, ComputingContext? context)- Context-aware forward FFT; selects scalar / SIMD / parallel according to
context. - Parameters:
-
re: Real parts. -
im: Imaginary parts. -
context: Optional execution policy.
-
- Context-aware forward FFT; selects scalar / SIMD / parallel according to
public void Direct(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
public void Direct(ReadOnlySpan<float> inRe, ReadOnlySpan<float> inIm, Span<float> outRe, Span<float> outIm)- Forward FFT that copies the input to the output buffers before transforming in place.
- Parameters:
-
inRe/inIm: Input real / imaginary parts. -
outRe/outIm: Output real / imaginary parts.
-
public void DirectNorm(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
public void DirectNorm(ReadOnlySpan<float> inRe, ReadOnlySpan<float> inIm, Span<float> outRe, Span<float> outIm)- Normalized forward FFT (copy variant). Equivalent to
Direct(...)for this class.
- Normalized forward FFT (copy variant). Equivalent to
public void Inverse(float[] re, float[] im)-
public void Inverse(Span<float> re, Span<float> im)- Inverse FFT in place.
-
public void Inverse(float[] re, float[] im, ComputingContext? context)- Context-aware inverse FFT.
public void Inverse(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
public void Inverse(ReadOnlySpan<float> inRe, ReadOnlySpan<float> inIm, Span<float> outRe, Span<float> outIm)- Inverse FFT that copies the input to the output buffers before transforming in place.
public void InverseNorm(float[] re, float[] im)-
public void InverseNorm(Span<float> re, Span<float> im)- Normalized inverse FFT in place (divides by
Size).
- Normalized inverse FFT in place (divides by
-
public void InverseNorm(float[] re, float[] im, ComputingContext? context)- Context-aware normalized inverse FFT.
public void InverseNorm(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
public void InverseNorm(ReadOnlySpan<float> inRe, ReadOnlySpan<float> inIm, Span<float> outRe, Span<float> outIm)- Normalized inverse FFT (copy variant).
public void MagnitudeSpectrum(float[] samples, float[] spectrum, bool normalize = false)public void MagnitudeSpectrum(ReadOnlySpan<float> samples, float[] spectrum, bool normalize = false)-
public void MagnitudeSpectrum(ReadOnlySpan<float> samples, Span<float> spectrum, bool normalize = false)- Computes
spectrum = sqrt(re*re + im*im)from realsamples.spectrummust have length at leastSize/2 + 1.
- Computes
-
public Signal MagnitudeSpectrum(Signal signal, bool normalize = false)- Computes and returns the magnitude spectrum as a
Signal.
- Computes and returns the magnitude spectrum as a
public void PowerSpectrum(float[] samples, float[] spectrum, bool normalize = true)public void PowerSpectrum(ReadOnlySpan<float> samples, float[] spectrum, bool normalize = true)-
public void PowerSpectrum(ReadOnlySpan<float> samples, Span<float> spectrum, bool normalize = true)- Computes
spectrum = re*re + im*imfrom realsamples.
- Computes
-
public float[] PowerSpectrum(Signal signal, bool normalize = true)- Computes and returns the power spectrum as a
float[].
- Computes and returns the power spectrum as a
public static void Shift(float[] samples)-
public static void Shift(Span<float> samples)- In-place FFT shift (swaps the two halves). Throws
ArgumentExceptionif the length is odd.
- In-place FFT shift (swaps the two halves). Throws
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class FftExample
{
public static void Main()
{
int fftSize = 8;
var fft = new Fft(fftSize);
float[] re = { 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f };
float[] im = new float[fftSize];
// Forward FFT in place
fft.Direct(re, im);
Console.WriteLine("Forward FFT:");
for (int i = 0; i < fftSize; i++)
Console.WriteLine($"re={re[i]}, im={im[i]}");
// Inverse FFT in place (normalized)
fft.InverseNorm(re, im);
Console.WriteLine("Inverse (normalized):");
for (int i = 0; i < fftSize; i++)
Console.WriteLine($"re={re[i]}, im={im[i]}");
}
}Vorcyc.Mathematics.SignalProcessing.Fourier.Fft64 is the double-precision counterpart of Fft: a complex in-place radix-2 FFT. ComputingContext-aware overloads dispatch to the FftButterflyFp64 SIMD / parallel kernel when beneficial.
-
public int Size { get; }- Gets the FFT size.
-
public Fft64(int fftSize = 512)- Constructs an
Fft64for the givenfftSize. FFT size must be a power of two. - Parameters:
-
fftSize: FFT size.
-
- Constructs an
public void Direct(double[] re, double[] im)public void Direct(Span<double> re, Span<double> im)-
public void Direct(double[] re, double[] im, ComputingContext? context)- Forward FFT in place; the context-aware overload selects scalar / SIMD / parallel.
public void Direct(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
public void Direct(ReadOnlySpan<double> inRe, ReadOnlySpan<double> inIm, Span<double> outRe, Span<double> outIm)- Forward FFT that copies the input to the output buffers before transforming in place.
public void DirectNorm(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
public void DirectNorm(ReadOnlySpan<double> inRe, ReadOnlySpan<double> inIm, Span<double> outRe, Span<double> outIm)- Normalized forward FFT (copy variant).
public void Inverse(double[] re, double[] im)public void Inverse(Span<double> re, Span<double> im)-
public void Inverse(double[] re, double[] im, ComputingContext? context)- Inverse FFT in place; the context-aware overload selects scalar / SIMD / parallel.
public void Inverse(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
public void Inverse(ReadOnlySpan<double> inRe, ReadOnlySpan<double> inIm, Span<double> outRe, Span<double> outIm)- Inverse FFT that copies the input to the output buffers before transforming in place.
public void InverseNorm(double[] re, double[] im)public void InverseNorm(Span<double> re, Span<double> im)public void InverseNorm(double[] re, double[] im, ComputingContext? context)public void InverseNorm(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
public void InverseNorm(ReadOnlySpan<double> inRe, ReadOnlySpan<double> inIm, Span<double> outRe, Span<double> outIm)- Normalized inverse FFT (in-place, context-aware, and copy variants).
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class Fft64Example
{
public static void Main()
{
int fftSize = 8;
var fft = new Fft64(fftSize);
double[] re = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
double[] im = new double[fftSize];
fft.Direct(re, im);
Console.WriteLine("Forward FFT64:");
for (int i = 0; i < fftSize; i++)
Console.WriteLine($"re={re[i]}, im={im[i]}");
fft.InverseNorm(re, im);
Console.WriteLine("Inverse (normalized):");
for (int i = 0; i < fftSize; i++)
Console.WriteLine($"re={re[i]}, im={im[i]}");
}
}Fft<T> (0.10.18) is a generic complex-FFT facade: float dispatches to Fft, double to Fft64. Other T types throw NotSupportedException.
public Fft(int fftSize = 512)public void Direct(T[] re, T[] im, ComputingContext? context = null)public void Inverse(T[] re, T[] im, ComputingContext? context = null)public void InverseNorm(T[] re, T[] im, ComputingContext? context = null)
var fft = new Fft<float>(256);
fft.Direct(re, im, ComputingContext.Simd);RealFft<T> (0.10.18) is the matching real-input facade: float → RealFft, double → RealFft64.
public RealFft(int size)public void Direct(T[] input, T[] re, T[] im, ComputingContext? context = null)public void Inverse(T[] re, T[] im, T[] output, ComputingContext? context = null)public void InverseNorm(T[] re, T[] im, T[] output, ComputingContext? context = null)
Vorcyc.Mathematics.SignalProcessing.Fourier.RealFft is a complex FFT optimized for real-valued input (float). It implements IComplexTransform. It computes a half-size complex FFT internally and exposes direct / inverse / normalized-inverse transforms, magnitude and power spectra, and an FFT-shift utility. ComputingContext-aware overloads dispatch to the shared FftButterflyFp32 SIMD / parallel kernel for the inner half-size transform when beneficial. This replaces the removed RealOnlyFFT_Fp32.
-
public int Size { get; }- Gets the FFT size (the configured real-input length).
-
public RealFft(int size)- Constructs a
RealFftfor the givensize. FFT size must be a power of two. - Parameters:
-
size: FFT size.
-
- Constructs a
public void Direct(float[] input, float[] re, float[] im)public void Direct(float[] input, float[] re, float[] im, ComputingContext? context)-
public void Direct(ReadOnlySpan<float> input, Span<float> re, Span<float> im, ComputingContext? context = null)- Forward FFT: real
input-> complex (re,im). The context-aware overloads select scalar / SIMD / parallel for the inner half-size FFT.
- Forward FFT: real
-
public void Direct(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
IComplexTransformsignature;inImis ignored.
-
-
public void DirectNorm(float[] inRe, float[] inIm, float[] outRe, float[] outIm)- Normalized forward FFT (
IComplexTransformsignature;inImis ignored). Equivalent toDirect(...)for this class.
- Normalized forward FFT (
public void Inverse(float[] re, float[] im, float[] output)public void Inverse(float[] re, float[] im, float[] output, ComputingContext? context)-
public void Inverse(ReadOnlySpan<float> re, ReadOnlySpan<float> im, Span<float> output, ComputingContext? context = null)- Inverse FFT: complex (
re,im) -> realoutput.
- Inverse FFT: complex (
-
public void Inverse(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
IComplexTransformsignature;outImis ignored.
-
public void InverseNorm(float[] re, float[] im, float[] output)public void InverseNorm(float[] re, float[] im, float[] output, ComputingContext? context)-
public void InverseNorm(ReadOnlySpan<float> re, ReadOnlySpan<float> im, Span<float> output, ComputingContext? context = null)- Normalized inverse FFT: complex (
re,im) -> realoutput(divided by the half-size).
- Normalized inverse FFT: complex (
-
public void InverseNorm(float[] inRe, float[] inIm, float[] outRe, float[] outIm)-
IComplexTransformsignature;outImis ignored.
-
public void MagnitudeSpectrum(float[] samples, float[] spectrum, bool normalize = false)public void MagnitudeSpectrum(ReadOnlySpan<float> samples, float[] spectrum, bool normalize = false)-
public void MagnitudeSpectrum(ReadOnlySpan<float> samples, Span<float> spectrum, bool normalize = false)- Computes
spectrum = sqrt(re*re + im*im).spectrummust have length at leastSize/2 + 1.
- Computes
-
public Signal MagnitudeSpectrum(Signal signal, bool normalize = false)- Returns the magnitude spectrum as a
Signal.
- Returns the magnitude spectrum as a
public void PowerSpectrum(float[] samples, float[] spectrum, bool normalize = true)public void PowerSpectrum(ReadOnlySpan<float> samples, float[] spectrum, bool normalize = true)-
public void PowerSpectrum(ReadOnlySpan<float> samples, Span<float> spectrum, bool normalize = true)- Computes
spectrum = re*re + im*im.
- Computes
-
public Signal PowerSpectrum(Signal signal, bool normalize = true)- Returns the power spectrum as a
Signal.
- Returns the power spectrum as a
-
public float[] PowerSpectrumArray(Signal signal, bool normalize = true)- Returns the power spectrum as a
float[].
- Returns the power spectrum as a
public static void Shift(float[] samples)-
public static void Shift(Span<float> samples)- In-place FFT shift (swaps the two halves). Throws
ArgumentExceptionif the length is odd.
- In-place FFT shift (swaps the two halves). Throws
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class RealFftExample
{
public static void Main()
{
int fftSize = 8;
var fft = new RealFft(fftSize);
float[] input = { 0.5f, 0.6f, 0.55f, 0.7f, 0.65f, 0.8f, 0.75f, 0.9f };
var re = new float[fftSize / 2 + 1];
var im = new float[fftSize / 2 + 1];
// Forward FFT: real input -> complex spectrum
fft.Direct(input, re, im);
Console.WriteLine("Forward FFT:");
for (int i = 0; i < re.Length; i++)
Console.WriteLine($"re={re[i]}, im={im[i]}");
// Magnitude / power spectra
var mag = new float[re.Length];
var pow = new float[re.Length];
fft.MagnitudeSpectrum(input, mag);
fft.PowerSpectrum(input, pow);
// Inverse FFT: complex spectrum -> real output
var output = new float[fftSize];
fft.InverseNorm(re, im, output);
Console.WriteLine("Inverse (normalized):");
foreach (var v in output) Console.WriteLine(v);
}
}Vorcyc.Mathematics.SignalProcessing.Fourier.RealFft64 is the double-precision counterpart of RealFft: a complex FFT optimized for real-valued input. ComputingContext-aware overloads dispatch to the FftButterflyFp64 SIMD / parallel kernel for the inner half-size transform when beneficial.
-
public int Size { get; }- Gets the FFT size (the configured real-input length).
-
public RealFft64(int size)- Constructs a
RealFft64for the givensize. FFT size must be a power of two. - Parameters:
-
size: FFT size.
-
- Constructs a
public void Direct(double[] input, double[] re, double[] im)public void Direct(double[] input, double[] re, double[] im, ComputingContext? context)-
public void Direct(ReadOnlySpan<double> input, Span<double> re, Span<double> im, ComputingContext? context = null)- Forward FFT: real
input-> complex (re,im).
- Forward FFT: real
-
public void Direct(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
IComplexTransform-style signature;inImis ignored.
-
-
public void DirectNorm(double[] inRe, double[] inIm, double[] outRe, double[] outIm)- Normalized forward FFT (
inImis ignored). Equivalent toDirect(...)for this class.
- Normalized forward FFT (
public void Inverse(double[] re, double[] im, double[] output)public void Inverse(double[] re, double[] im, double[] output, ComputingContext? context)-
public void Inverse(ReadOnlySpan<double> re, ReadOnlySpan<double> im, Span<double> output, ComputingContext? context = null)- Inverse FFT: complex (
re,im) -> realoutput.
- Inverse FFT: complex (
-
public void Inverse(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
IComplexTransform-style signature;outImis ignored.
-
public void InverseNorm(double[] re, double[] im, double[] output)public void InverseNorm(double[] re, double[] im, double[] output, ComputingContext? context)-
public void InverseNorm(ReadOnlySpan<double> re, ReadOnlySpan<double> im, Span<double> output, ComputingContext? context = null)- Normalized inverse FFT: complex (
re,im) -> realoutput.
- Normalized inverse FFT: complex (
-
public void InverseNorm(double[] inRe, double[] inIm, double[] outRe, double[] outIm)-
IComplexTransform-style signature;outImis ignored.
-
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class RealFft64Example
{
public static void Main()
{
int fftSize = 8;
var fft = new RealFft64(fftSize);
double[] input = { 0.5, 0.6, 0.55, 0.7, 0.65, 0.8, 0.75, 0.9 };
var re = new double[fftSize / 2 + 1];
var im = new double[fftSize / 2 + 1];
fft.Direct(input, re, im);
var output = new double[fftSize];
fft.InverseNorm(re, im, output);
foreach (var v in output) Console.WriteLine(v);
}
}Vorcyc.Mathematics.SignalProcessing.Fourier.Stft implements the Short-Time Fourier Transform and its inverse, plus spectrogram and magnitude-phase spectrogram helpers. It wraps a RealFft and a window function (WindowBuilder). All processing methods accept an optional ComputingContext that drives frame-level parallel dispatch when the workload is large enough; otherwise a serial path is used. Stft was moved here from Vorcyc.Mathematics.SignalProcessing.Transforms in 0.10.1.
-
public int Size { get; }- Gets the FFT size used by the transformer.
-
public Stft(int windowSize = 1024, int hopSize = 256, WindowType window = WindowType.Hann, int fftSize = 0)- Constructs an
Stfttransformer. WhenfftSize < windowSize, the FFT size is rounded up to the next power of two ofwindowSize. - Parameters:
-
windowSize: Size of the analysis window. -
hopSize: Hop (overlap) size. -
window: Type of the window function. -
fftSize: Size of FFT;0auto-selects fromwindowSize.
-
- Constructs an
public List<(float[], float[])> Direct(float[] input, ComputingContext? context = null)public List<(float[], float[])> Direct(ReadOnlySpan<float> input, ComputingContext? context = null)-
public List<(float[], float[])> Direct(Signal signal, ComputingContext? context = null)- Computes STFT and returns the list of per-frame spectra
(re[], im[]).
- Computes STFT and returns the list of per-frame spectra
-
public float[] Inverse(List<(float[], float[])> stft, bool perfectReconstruction = true, ComputingContext? context = null)- Inverse STFT via overlap-add. When
perfectReconstructionis true,hopSizemust not exceedwindowSize.
- Inverse STFT via overlap-add. When
public List<float[]> Spectrogram(float[] input, bool normalize = true, ComputingContext? context = null)public List<float[]> Spectrogram(ReadOnlySpan<float> input, bool normalize = true, ComputingContext? context = null)-
public List<float[]> Spectrogram(Signal signal, bool normalize = true, ComputingContext? context = null)- Computes the spectrogram as a list of per-frame power spectra.
public float[] AveragePeriodogram(float[] input, ComputingContext? context = null)public float[] AveragePeriodogram(ReadOnlySpan<float> input, ComputingContext? context = null)-
public float[] AveragePeriodogram(Signal signal, ComputingContext? context = null)- Computes a Welch-style averaged periodogram: mean of per-frame power spectra over complete windows only (trailing samples that do not fill a window are discarded — SciPy / MATLAB
welchconvention). HonorsComputingContextfor frame-level parallel dispatch; when frames are parallelized, each frame FFT uses SIMD (not nested Parallel).
- Computes a Welch-style averaged periodogram: mean of per-frame power spectra over complete windows only (trailing samples that do not fill a window are discarded — SciPy / MATLAB
0.10.13: Dropped the previous trailing incomplete frame (and
/ (N+1)average). Breaking change for short signals / few frames.
public MagnitudePhaseList MagnitudePhaseSpectrogram(float[] input, ComputingContext? context = null)public MagnitudePhaseList MagnitudePhaseSpectrogram(ReadOnlySpan<float> input, ComputingContext? context = null)-
public MagnitudePhaseList MagnitudePhaseSpectrogram(Signal signal, ComputingContext? context = null)- Computes the spectrogram as separate lists of magnitudes and phases.
-
public float[] ReconstructMagnitudePhase(MagnitudePhaseList spectrogram, bool perfectReconstruction = true, ComputingContext? context = null)- Reconstructs samples from a magnitude/phase spectrogram via inverse STFT.
-
public struct MagnitudePhaseList-
public List<float[]> Magnitudes { get; set; }— list of per-frame magnitudes. -
public List<float[]> Phases { get; set; }— list of per-frame phases.
-
using System;
using Vorcyc.Mathematics.SignalProcessing.Fourier;
public class StftExample
{
public static void Main()
{
var stft = new Stft(windowSize: 1024, hopSize: 256);
float[] signal = new float[16000];
for (int i = 0; i < signal.Length; i++)
signal[i] = MathF.Sin(2f * MathF.PI * 440f * i / 16000f);
// Forward STFT
var frames = stft.Direct(signal);
Console.WriteLine($"Frames: {frames.Count}");
// Spectrogram (list of power spectra)
var spectrogram = stft.Spectrogram(signal);
// Inverse STFT
var reconstructed = stft.Inverse(frames);
Console.WriteLine($"Reconstructed length: {reconstructed.Length}");
}
}FftButterflyFp32 and FftButterflyFp64 are internal static structure-of-arrays radix-2 butterfly kernels shared by Fft / RealFft, Fft64 / RealFft64, and FastFourierTransform.Forward / Inverse. They are not part of the public API, but are documented here because they implement the SIMD and parallel execution paths selected by ComputingContext.
Each kernel exposes:
-
public static bool WillAccelerate(CpuExecutionMode mode, int size)- Returns
truewhen the given mode and size would take an accelerated (SIMD or parallel) path. Below the SIMD crossover (~8K) the scalar caller-side butterfly is faster, so the kernels returnfalseand the calling class falls back to its own scalar butterfly.
- Returns
-
public static void Transform(float[]/double[] re, float[]/double[] im, int size, bool inverse, CpuExecutionMode mode, ComputingContext? context = null)- In-place radix-2 butterfly stages followed by the bit-reversal permutation.
inverseselects the twiddle sign.
- In-place radix-2 butterfly stages followed by the bit-reversal permutation.
Three execution paths are selected via CpuExecutionMode: scalar (Normal), Vector<T> SIMD, and parallel. All paths produce results identical (up to floating-point rounding) to the original scalar decimation-in-frequency FFT.