FastLED 3.10.8
Loading...
Searching...
No Matches

◆ initHybrid()

void fl::audio::fft::Context::initHybrid ( int samples,
int bands,
float fmin,
float fmax,
int sr )
inlineprivate

Definition at line 837 of file fft_impl.cpp.hpp.

837 {
838 float logRatio = logf(fmax / fmin);
839
840 // Log-spaced center frequencies for all bins
841 FASTLED_STACK_ARRAY(float, centerFreqs, bands);
842 for (int i = 0; i < bands; i++) {
843 centerFreqs[i] =
844 fmin * expf(logRatio * static_cast<float>(i) /
845 static_cast<float>(bands - 1));
846 }
847
848 // 3-tier split at octave boundaries:
849 // bass/mid at fmin*4 (~698 Hz, 2 octaves above fmin)
850 // mid/upper at fmin*8 (~1397 Hz, 3 octaves above fmin)
851 float bassMidFreq = fmin * 4.0f;
852 float midUpperFreq = fmin * 8.0f;
853
854 // Clamp splits to valid range
855 if (midUpperFreq >= fmax) midUpperFreq = fmax * 0.5f;
856 if (bassMidFreq >= midUpperFreq) bassMidFreq = midUpperFreq * 0.5f;
857
858 // Find split bin indices
859 mHybridSplitBin = 0;
860 for (int i = 0; i < bands; i++) {
861 if (centerFreqs[i] < bassMidFreq)
862 mHybridSplitBin = i + 1;
863 }
865 for (int i = mHybridSplitBin; i < bands; i++) {
866 if (centerFreqs[i] < midUpperFreq)
867 mHybridMidSplitBin = i + 1;
868 }
869
870 // Ensure each tier has at least 1 bin
871 if (mHybridSplitBin < 1) mHybridSplitBin = 1;
874 if (mHybridMidSplitBin >= bands)
875 mHybridMidSplitBin = bands - 1;
876
877 // LOG_REBIN bin edges (shared by all three tiers)
878 mLogBinEdges.resize(bands + 1);
879 if (bands <= 1) {
880 mLogBinEdges[0] = fmin;
881 mLogBinEdges[1] = fmax;
882 } else {
883 float denom = 2.0f * static_cast<float>(bands - 1);
884 mLogBinEdges[0] = fmin * expf(-logRatio / denom);
885 for (int i = 1; i < bands; i++) {
886 mLogBinEdges[i] =
887 fmin * expf(logRatio *
888 (2.0f * static_cast<float>(i) - 1.0f) / denom);
889 }
890 mLogBinEdges[bands] = fmax * expf(logRatio / denom);
891 }
892
893 // Clamp top bin edge to Nyquist
894 float nyquist = static_cast<float>(sr) / 2.0f;
895 if (mLogBinEdges[bands] > nyquist) {
896 mLogBinEdges[bands] = nyquist;
897 }
898
900
901 // Window for the full-rate 512pt FFT (upper tier)
902 initWindow();
903
904 // Mid-tier: 2 decimation steps → samples/4 at sr/4
905 // Zero-pad 2x: 128 real samples → 256pt FFT → 43 Hz bins
906 mHybridMidN = samples / 4;
907 mHybridMidFs = static_cast<float>(sr) / 4.0f;
908 mHybridMidFft = kiss_fftr_alloc(mHybridMidN * 2, 0, nullptr, nullptr);
909 mHybridMidFftOut.resize(mHybridMidN * 2);
911
912 // Bass-tier: 3 decimation steps → samples/8 at sr/8
913 mHybridSmallN = samples / 8;
914 mHybridSmallFs = static_cast<float>(sr) / 8.0f;
916 kiss_fftr_alloc(mHybridSmallN, 0, nullptr, nullptr);
919
920 // Work buffer for decimation (reused across phases)
921 mWorkBuf.resize(samples);
922 mFftOut.resize(samples);
923
924 // Pre-computed bin mapping LUTs for each tier
925 buildLogBinLut(mLogBinLut, samples,
926 static_cast<float>(sr),
927 mHybridMidSplitBin, bands);
933 0, mHybridSplitBin);
935
936 // Pre-compute normalization factors for each hybrid tier
938 samples, static_cast<float>(sr),
939 mHybridMidSplitBin, bands);
945 0, mHybridSplitBin);
946
947 // Pre-compute merged norm factors (avoids per-frame allocation)
948 mHybridMergedNorm.resize(bands);
949 for (int i = 0; i < bands; ++i) {
950 if (i >= mHybridMidSplitBin && i < static_cast<int>(mHybridNormUpper.size())) {
952 } else if (i >= mHybridSplitBin && i < static_cast<int>(mHybridNormMid.size())) {
954 } else if (i < static_cast<int>(mHybridNormBass.size())) {
956 } else {
957 mHybridMergedNorm[i] = 1.0f;
958 }
959 }
960 }
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE)
Stack-allocated array with automatic zero-initialization.
Definition alloca.h:32
fl::vector< alpha16 > mHybridBassWindow
fl::vector< kiss_fft_scalar > mWorkBuf
void buildLinearBinLut(fl::vector< u8 > &lut, int fftN) FL_NO_EXCEPT
void buildLogBinLut(fl::vector< u8 > &lut, int fftN, float fs, int binStart, int binEnd) FL_NO_EXCEPT
fl::vector< u8 > mLinearBinLut
void initWindow() FL_NO_EXCEPT
fl::vector< alpha16 > mHybridMidWindow
fl::vector< kiss_fft_cpx > mHybridMidFftOut
fl::vector< float > mLogBinEdges
fl::vector< u8 > mLogBinLutMid
fl::vector< kiss_fft_cpx > mHybridSmallFftOut
fl::vector< float > mHybridNormUpper
fl::vector< u8 > mLogBinLutBass
fl::vector< u8 > mLogBinLut
fl::vector< kiss_fft_cpx > mFftOut
static void computeWindow(fl::vector< alpha16 > &win, int N, Window type) FL_NO_EXCEPT
void computeBinEdgesQ16() FL_NO_EXCEPT
fl::vector< float > mHybridNormBass
fl::vector< float > mHybridMergedNorm
void computeLogRebinNormFactors(fl::vector< float > &normFactors, const fl::vector< u8 > &lut, int fftN, float fs, int binStart, int binEnd) FL_NO_EXCEPT
fl::vector< float > mHybridNormMid
kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem)
float logf(float value) FL_NO_EXCEPT
Definition math.h:426
float expf(float value) FL_NO_EXCEPT
Definition math.h:406

References buildLinearBinLut(), buildLogBinLut(), computeBinEdgesQ16(), computeLogRebinNormFactors(), computeWindow(), fl::expf(), FASTLED_STACK_ARRAY, fl::FL_NO_EXCEPT, initWindow(), kiss_fftr_alloc(), fl::logf(), mFftOut, mHybridBassWindow, mHybridMergedNorm, mHybridMidFft, mHybridMidFftOut, mHybridMidFs, mHybridMidN, mHybridMidSplitBin, mHybridMidWindow, mHybridNormBass, mHybridNormMid, mHybridNormUpper, mHybridSmallFft, mHybridSmallFftOut, mHybridSmallFs, mHybridSmallN, mHybridSplitBin, mLinearBinLut, mLogBinEdges, mLogBinLut, mLogBinLutBass, mLogBinLutMid, mWindow, and mWorkBuf.

Referenced by Context().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: