// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. // See LICENSE.md for license information. // SPDX-License-Identifier: MIT // // gateFft.h - numpy's spectral arithmetic for the gate tools: the discrete // Fourier transform of any length, and the pieces of numpy around it that // the graders lean on (its sum, its Hann window, its bin frequencies), each // computed in the order numpy computes it so a grade reads as it did. #ifndef GATE_FFT_H #define GATE_FFT_H #include #include #include // Prime factors a length can have (2^64 needs 64). #define GATE_FFT_FACTORS_MAX 64u // A transform of n points: mixed radix over its prime factors (the roots // of unity, and a butterfly's twiddled inputs, its spokes), or, when one of // them is too large for a direct butterfly, Bluestein's chirp through a // power-of-two transform (inner). typedef struct GateFftT { size_t n; size_t factorCount; size_t factors[GATE_FFT_FACTORS_MAX]; double *rootRe; double *rootIm; double *inRe; double *inIm; double *outRe; double *outIm; double *spokeRe; double *spokeIm; struct GateFftT *inner; double *chirpRe; double *chirpIm; double *filterRe; double *filterIm; } GateFftT; // numpy.abs(numpy.fft.rfft(in[0..inLen), fft->n)): the n / 2 + 1 bins' // magnitudes (hypot, as numpy takes them). void gateFftAbs(GateFftT *fft, const double *in, size_t inLen, double *magnitude); void gateFftFree(GateFftT *fft); // A plan for transforms of n (at least 1) points. Running out of memory is // fatal (toolFail). void gateFftInit(GateFftT *fft, size_t n); // numpy.fft.rfft(in[0..inLen), fft->n): the n / 2 + 1 bins, the input // zero-padded (or cut) to n points. void gateFftReal(GateFftT *fft, const double *in, size_t inLen, double *re, double *im); // numpy.hanning(n): the symmetric Hann window. void gateHanning(double *window, size_t n); // numpy.mean of n doubles: gateSum / n. double gateMean(const double *x, size_t n); // numpy.fft.rfftfreq(n, 1.0 / rate)[bin]. double gateRfftFreq(size_t bin, size_t n, uint32_t rate); // numpy.sum of n doubles: pairwise (eight running sums, halved past 128), // a buffer (8192) at a time, the buffers' sums added in turn. double gateSum(const double *x, size_t n); #endif