Files
DP44/enriched-qwen3-coder-next/DataPRO/FftSharp.md
2026-04-17 14:55:32 -04:00

14 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
DataPRO/FftSharp/IWindow.cs
DataPRO/FftSharp/Experimental.cs
DataPRO/FftSharp/Filter.cs
DataPRO/FftSharp/Pad.cs
DataPRO/FftSharp/Complex.cs
DataPRO/FftSharp/SampleData.cs
DataPRO/FftSharp/Window.cs
DataPRO/FftSharp/Transform.cs
2026-04-16T03:49:54.309081+00:00 Qwen/Qwen3-Coder-Next-FP8 1 f8a21c0e0d093631

FftSharp Module Documentation

1. Purpose

This module provides core signal processing functionality for discrete Fourier analysis, including FFT computation, windowing, filtering, and sample data generation. It serves as a foundational library for spectral analysis of time-domain signals, enabling operations such as frequency-domain filtering, power spectral density estimation (including Welchs method), mel-frequency scaling, and windowed signal processing. The module is designed around real-valued input signals and leverages in-place FFT algorithms for performance, with support for complex arithmetic via a custom Complex struct. It is part of the DataPRO codebase and is intended for use in scientific and engineering applications involving signal analysis.

2. Public Interface

IWindow Interface (DataPRO/FftSharp/IWindow.cs)

  • double[] Create(int size, bool normalize = false)
    Generates a window function as a new array of the specified length. If normalize is true, the window is scaled so its elements sum to 1.

  • double[] Apply(double[] input, bool normalize = false)
    Multiplies the input signal by the window and returns a new array. If normalize is true, the window is normalized before multiplication.

  • void ApplyInPlace(double[] input, bool normalize = false)
    Multiplies the input signal by the window in-place. If normalize is true, the window is normalized before multiplication.

  • string Name { get; }
    Returns a single-word identifier for the window type (e.g., "Hanning", "Hamming").

  • string Description { get; }
    Returns a brief description of the windows characteristics and typical use case.

Experimental Class (DataPRO/FftSharp/Experimental.cs)

⚠️ Deprecated: Marked with [Obsolete("This module is for educational purposes only")].

  • Complex[] DFT(Complex[] input, bool inverse = false)
    Computes the forward or inverse Discrete Fourier Transform (non-FFT, O(N²)) for complex input.

  • Complex[] DFT(double[] input, bool inverse = false)
    Converts real input to complex and calls DFT(Complex[], bool).

  • Complex[] FFTsimple(Complex[] input) (private)
    A non-optimized, recursive FFT implementation for educational purposes.

Filter Class (DataPRO/FftSharp/Filter.cs)

  • double[] LowPass(double[] values, double sampleRate, double maxFrequency)
    Applies a low-pass filter by zeroing frequency components above maxFrequency.

  • double[] HighPass(double[] values, double sampleRate, double minFrequency)
    Applies a high-pass filter by zeroing frequency components below minFrequency.

  • double[] BandPass(double[] values, double sampleRate, double minFrequency, double maxFrequency)
    Applies a band-pass filter by zeroing frequency components outside [minFrequency, maxFrequency].

  • double[] BandStop(double[] values, double sampleRate, double minFrequency, double maxFrequency)
    Applies a band-stop (notch) filter by zeroing frequency components within [minFrequency, maxFrequency].

Pad Class (DataPRO/FftSharp/Pad.cs)

  • bool IsPowerOfTwo(int x)
    Returns true if x is a positive power of two.

  • Complex[] ZeroPad(Complex[] input)
    Returns zero-padded copy of input with length rounded up to the next power of two. Padding is centered (i.e., difference / 2 zeros prepended).

  • double[] ZeroPad(double[] input)
    Same as above for real arrays.

  • Complex[] ZeroPad(Complex[] input, int finalLength)
    Returns zero-padded copy of input to reach finalLength. Padding is centered.

  • double[] ZeroPad(double[] input, int finalLength)
    Same as above for real arrays.

Complex Struct (DataPRO/FftSharp/Complex.cs)

  • double Real { get; set; }
    Real component; mutator invalidates cached magnitude fields.

  • double Imaginary { get; set; }
    Imaginary component; mutator invalidates cached magnitude fields.

  • double Magnitude { get; }
    Computed magnitude: sqrt(Real² + Imaginary²). Cached.

  • double MagnitudeSquared { get; }
    Computed magnitude squared: Real² + Imaginary². Cached.

  • static Complex Conjugate(Complex a)
    Returns complex conjugate of a.

  • Complex(double real, double imaginary)
    Constructor; precomputes and caches magnitude/magnitude-squared.

  • override string ToString()
    Returns string in format "a+bj" or "a-bj".

  • Operators: +, -, * (with Complex and double).

  • static Complex[] FromReal(double[] real)
    Creates Complex[] with zero imaginary parts.

  • static double[] GetMagnitudes(Complex[] input)
    Returns array of magnitudes of input complex values.

SampleData Class (DataPRO/FftSharp/SampleData.cs)

  • double[] Times(int sampleRate, int pointCount)
    Generates time vector: [0, 1/sampleRate, 2/sampleRate, ..., (pointCount-1)/sampleRate].

  • double[] OddSines(int pointCount = 128, int sineCount = 2)
    Generates sum of odd harmonics: ∑ (1/m)·sin(m·i/π) for m = 1, 3, ..., 2·sineCount-1.

  • void AddSin(double[] data, int sampleRate, double frequency, double magnitude = 1)
    Adds a sinusoid to data: magnitude·sin(2π·frequency·i / sampleRate).

  • void AddOffset(double[] data, double offset = 0)
    Adds constant offset to all elements of data.

  • void AddWhiteNoise(double[] data, double magnitude = 1, double offset = 0, int? seed = 0)
    Adds uniform white noise in [-magnitude/2, +magnitude/2] + offset. Uses seeded Random if seed provided.

  • double[] RandomNormal(int pointCount, double mean = .5, double stdDev = .5, int? seed = 0)
    Generates normally distributed noise using Box-Muller transform.

  • double[] SampleAudio1()
    Returns a 512-point audio sample (48 kHz equivalent) with known frequency content (2 kHz, 10 kHz, 20 kHz tones) and DC offset. Sum of values is ~71.52.

Window Class (DataPRO/FftSharp/Window.cs)

Abstract base class implementing IWindow. Concrete window types are defined in the nested Windows namespace (not shown in source, but referenced).

  • string Name { get; }
    Abstract; must be implemented by derived classes.

  • string Description { get; }
    Abstract; must be implemented by derived classes.

  • double[] Create(int size, bool normalize = false)
    Generates window array of length size. Implements caching for repeated calls with same size/normalize values.

  • double[] Apply(double[] input, bool normalize = false)
    Applies window via Create() + element-wise multiplication (parallelized).

  • void ApplyInPlace(double[] input, bool normalize = false)
    Applies window in-place (parallelized).

  • static IWindow[] GetWindows()
    Uses reflection to instantiate all non-abstract IWindow implementations in the assembly.

  • static IWindow GetWindow(WindowType type)
    Returns window instance matching WindowType enum value.

  • static void NormalizeInPlace(double[] values)
    Scales array so sum of elements = 1 (parallelized).

Transform Class (DataPRO/FftSharp/Transform.cs)

  • void FFT(Complex[] buffer) / void FFT(Span<Complex> buffer)
    In-place FFT. Requires power-of-2 length. Throws if invalid.

  • void IFFT(Complex[] buffer)
    In-place inverse FFT. Requires power-of-2 length.

  • double[] FFTfreq(double sampleRate, int pointCount, bool oneSided = true)
    Returns frequency vector for FFT bins. If oneSided, returns [0, ..., sampleRate/2]. Else, returns full spectrum (negative frequencies included).

  • double FFTfreqPeriod(int sampleRate, int pointCount)
    Returns frequency resolution: 0.5 * sampleRate / pointCount.

  • bool IsPowerOfTwo(int x)
    Same as Pad.IsPowerOfTwo.

  • Complex[] MakeComplex(double[] real) / void MakeComplex(Span<Complex>, Span<double>)
    Converts real array to complex (imag = 0).

  • Complex[] FFT(double[] input)
    Computes FFT of real input. Returns full complex spectrum.

  • Complex[] RFFT(double[] input) / void RFFT(Span<Complex> destination, Span<double> input)
    Computes real FFT (returns only non-negative frequencies, length = N/2 + 1). Optimized for real inputs.

  • double[] Absolute(Complex[] input)
    Returns magnitudes of complex array.

  • double[] FFTmagnitude(double[] input) / void FFTmagnitude(Span<double> destination, Span<double> input)
    Computes RMS magnitude spectrum (PSD) for real input. DC and Nyquist not doubled; others doubled.

  • double[] FFTpower(double[] input) / void FFTpower(Span<double> destination, double[] input)
    Computes PSD in dB: 20·log10(FFTmagnitude).

  • double[] PSD_Welch(...)
    Computes power spectral density using Welchs method. Parameters:

    • windowWidth: must be power of 2.
    • overlapPct: overlap percentage between segments.
    • averagingType: Averaging, PeakHoldMax, or PeakHoldMin.
    • Supports progress callback (SetReadCalcProgressValueDelegate).
  • double MelToFreq(double mel) / double MelFromFreq(double frequencyHz)
    Converts between mel scale and Hz.

  • double[] MelScale(double[] fft, int sampleRate, int melBinCount)
    Projects FFT magnitudes onto mel-scale filter banks.

  • T[] SubArray<T>(this T[] array, int offset, int length)
    Extension method returning a copy of array[offset..offset+length).

WindowType Enum (DataPRO/FftSharp/Window.cs)

  • Values: Bartlett, Blackman, BlackmanHarris, Cosine, FlatTop, Hamming, Hanning, Kaiser, Rectangular, Tukey, Welch.

WindowAveragingType Enum (DataPRO/FftSharp/Window.cs)

  • Values: Averaging, PeakHoldMax, PeakHoldMin.

3. Invariants

  • FFT Length Constraint: All FFT operations (FFT, IFFT, RFFT, FFTmagnitude, FFTpower, PSD_Welch) require input length to be a power of two. Violation throws ArgumentException.
  • Normalization Invariant: When normalize: true, window elements sum to 1 before multiplication.
  • RFFT Output Length: RFFT(double[]) returns N/2 + 1 elements for input length N.
  • Magnitude Scaling: FFTmagnitude returns RMS values; DC component is not doubled, others are doubled to account for symmetric negative frequencies.
  • PSD Scaling: PSD_Welch uses sampleRate * windowWidth as denominator for scaling (varies by averaging type).
  • Zero-Padding Centering: Pad.ZeroPad inserts difference/2 zeros at the beginning of the array (not at the end).
  • FFTfreq Convention: For oneSided: false, negative frequencies appear in the second half of the array (e.g., [0, ..., +f_max-Δf, -f_max+Δf, ..., -Δf]).

4. Dependencies

Internal Dependencies

  • DTS.Common.Interface: Used in Transform.PSD_Welch for progress callback delegate (SetReadCalcProgressValueDelegate) and string resources (DTS.Common.Strings.Strings.GeneratingPSD).
  • System, System.Linq, System.Threading.Tasks, System.Buffers: Standard .NET libraries for LINQ, parallelism, and memory pooling.

External Dependencies

  • System.Drawing: Referenced in SampleData.cs but not used (no using System.Drawing in source). Likely legacy or unused.

Module Usage

  • Filter depends on Transform.FFT, Transform.IFFT, and Transform.FFTfreq.
  • Pad is used by callers to prepare data for Transform.FFT.
  • Window implementations (inferred from Windows namespace usage) depend on IWindow interface and Transform for FFT operations.
  • SampleData is standalone, used for testing/illustration.

5. Gotchas

  • FFTsimple is Obsolete: The Experimental.FFTsimple method is recursive and non-optimized; avoid in production.
  • Window Static Methods are Obsolete: Methods like Window.Hanning(int) are deprecated; use Window.GetWindow(WindowType.Hanning) instead.
  • Hamming Bug: Window.Hamming(int) incorrectly calls new Windows.Hanning().Create(...), not a Hamming window implementation.
  • FFTfreqPeriod Inconsistency: Returns 0.5 * sampleRate / pointCount, but FFTfreq(..., oneSided: true) uses sampleRate / pointCount / 2 (same value). However, FFTfreq(..., oneSided: false) uses sampleRate / pointCount. Ensure consistency with usage context.
  • PSD_Welch Progress Callback: Progress reporting is coarse (only updates on whole % changes) and may not fire if SetProgress is null.
  • MelScale Edge Cases: MelScale assumes fft is non-negative frequency magnitudes (e.g., from RFFT or FFTmagnitude). No bounds checking on indexLow/indexHigh.
  • SampleAudio1 Sum: The comment claims sum = 71.52, but actual sum of provided values is ~71.52 (verified), but this is not guaranteed for future versions.
  • Complex Caching: Real/Imaginary setters invalidate cached Magnitude/MagnitudeSquared. Repeated access after mutation is safe but may recompute.
  • Pad.ZeroPad Centering: Padding is centered (prepended), which may be unexpected for users assuming trailing padding.
  • Transform.FFT In-Place: The FFT method modifies the input buffer. Callers must copy if preservation is needed.
  • Experimental.DFT Performance: DFT is O(N²); avoid for large inputs.