Signal Processing

Numerics.NET provides a comprehensive set of classes for digital signal processing, including Fast Fourier Transforms (FFT), convolution, and correlation operations for real and complex signals.

This section covers the following topics:

Quick Start with the SignalMath Class

For quick, one-time signal processing operations, the SignalMath class provides static methods that perform FFT, convolution, and correlation operations in a single line of code. This is the recommended approach for most applications.

FFT Operations: To compute the Fourier transform of a real sequence, use FourierTransform. This method takes a signal as input and produces a complex spectrum. The inverse transform is computed using InverseFourierTransform.

Convolution Operations: To perform convolution, use Convolve. This method computes the linear convolution of two signals with various output modes (full length, same as signal, or no padding).

Correlation Operations: To compute cross-correlation, use Correlate. For autocorrelation, use AutoCorrelate.

The following example computes the Fourier transform of a short vector, and then computes the inverse transform. The result is a vector identical to the first one:

C#
var v = Vector.FromFunction(1024, i => Math.Sin(0.05 * i));
var w = Vector.FourierTransform(v);

For more details on using the SignalMath class, see The SignalMath Class. For detailed information on convolution and correlation operations, see Convolutions and Correlations.

Multiple FFT's of the same size

In many applications, many Fourier transforms of the same length need to be calculated. To make this process more efficient, you can use Fft<T> objects, that represent the implementation of an FFT of a given length. Fft<T> objects are created through an SignalOperations<T>.

Signal Processing Providers

Signal processing operations in Numerics.NET can use different implementation providers to optimize performance. Providers offer highly optimized implementations of FFT, convolution, and correlation operations.

Two providers are available: a managed provider that uses 100% managed code, and a native provider that uses hand-optimized native code and is typically an order of magnitude faster for longer transforms and larger kernels.

FFT Providers: The SignalOperations<T> is the base class for accessing a specific set of FFT algorithms. You can obtain FFT providers through the ManagedImplementation and NativeImplementation properties.

The following example demonstrates creating an FFT using a specific provider:

C#
// Get the managed FFT provider
var managedProvider = Numerics.NET.Providers.ImplementationManager<SignalOperations<double>>.ManagedImplementation;
int N = 1024;
Fft<double> managedFft = managedProvider.Create1DRealFft(N);

// Get the native FFT provider (if available)
var nativeProvider = Numerics.NET.Providers.ImplementationManager<SignalOperations<double>>.NativeImplementation;
if (nativeProvider != null)
{
    Fft<double> nativeFft = nativeProvider.Create1DRealFft(N);
}

Kernel Processor Creation: Kernel processors for convolution and correlation are created through the SignalOperations<T> class. The CreateRealKernelProcessor() and CreateComplexKernelProcessor() methods create processors that use the specific provider instance for all FFT operations:

C#
// Get the signal processing provider (uses managed or native based on availability)
var provider = CoreImplementations<double>.SignalProcessing;
double[] kernel = { 1, 2, 3, 2, 1 };

// Create a kernel processor using the default provider
var processor = provider.CreateRealKernelProcessor(
    kernel, mode: ConvolutionMode.FullLength);

In order to use the native provider, the assembly containing the native code for the current processor architecture must be present. This assembly is called Numerics.NET.Native.Mkl.dll. If this assembly cannot be found, the managed provider is used instead.

The managed provider has properties that specify thresholds for automatically switching to the native provider when available. The RealManagedThresholdLength property specifies the shortest length of a real FFT for which the native FFT provider will be used (default: 64). The ComplexManagedThresholdLength property specifies the shortest length of a complex FFT for which the native FFT provider will be used (default: 32).

The Fft<T> and Fft2D<T> classes implement System.IDisposable, so you should always use a using statement or call Dispose once you are done using the object.