FastLED 3.9.15
Loading...
Searching...
No Matches

◆ runOctaveWise()

void fl::audio::fft::Context::runOctaveWise ( span< const i16 > buffer,
Bins * out )
inlineprivate

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

660 {
661 const int N = mInputSamples;
662 const int numOctaves = static_cast<int>(mOctaves.size());
663 const int numRawBins = N / 2 + 1;
664
665 out->setParams(mFmin, mFmax, mSampleRate);
666
667 // Copy input to working buffer
668 int workLen = N;
669 for (int i = 0; i < N; i++) {
670 mWorkBuf[i] =
671 (i < static_cast<int>(buffer.size())) ? buffer[i] : 0;
672 }
673
674 // FFT at full sample rate (for linear bins + top octave CQ)
676
677 // Deinterleave AoS → SoA and batch-compute magnitudes
678 FftScratch &s = scratch();
679 s.re.resize(numRawBins);
680 s.im.resize(numRawBins);
681 s.mag.resize(numRawBins);
682 deinterleave(mFftOut.data(), s.re.data(), s.im.data(), numRawBins);
683 batchMag(s.re.data(), s.im.data(), s.mag.data(), numRawBins);
684
685 computeLinearBins(s.mag.data(), N, out);
686
687 // Prepare CQ output bins
688 fl::vector<float> &rawBins = out->raw_mut();
689 rawBins.resize(mTotalBands);
690 for (int i = 0; i < mTotalBands; i++) {
691 rawBins[i] = 0.0f;
692 }
693
694 // Pre-allocate CQ accumulator once (avoids alloca in loop)
695 FASTLED_STACK_ARRAY(kiss_fft_cpx, cq, mMaxBinsPerOctave);
696
697 // Process octaves from top (highest freq) to bottom (lowest freq).
698 // Top octave uses the FFT already computed above.
699 // Each lower octave: decimate signal by 2x, then FFT + CQ.
700 for (int oct = numOctaves - 1; oct >= 0; oct--) {
701 const OctaveInfo &oi = mOctaves[oct];
702 if (oi.numBins <= 0 || !oi.kernels)
703 continue;
704
705 if (oct != numOctaves - 1) {
706 decimateBy2(mWorkBuf.data(), workLen);
707 workLen = workLen / 2;
708 // Zero-pad remainder so FFT sees clean input
709 for (int i = workLen; i < N; i++)
710 mWorkBuf[i] = 0;
712 }
713
714 // Zero the CQ accumulator and apply kernels
715 fl::memset(cq, 0, sizeof(kiss_fft_cpx) * oi.numBins);
716 apply_kernels(mFftOut.data(), cq, oi.kernels, oi.cfg);
717
718 for (int i = 0; i < oi.numBins; i++) {
719 int binIdx = oi.firstBin + i;
720 i32 real = cq[i].r;
721 i32 imag = cq[i].i;
722#ifdef FIXED_POINT
723 rawBins[binIdx] = static_cast<float>(fastMag(real, imag));
724#else
725 float r2 = float(real * real);
726 float i2 = float(imag * imag);
727 rawBins[binIdx] = sqrt(r2 + i2);
728#endif
729 }
730 }
731 }
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE)
Stack-allocated array with automatic zero-initialization.
Definition alloca.h:32
static void decimateBy2(kiss_fft_scalar *buf, int len)
static void deinterleave(const kiss_fft_cpx *cpx, kiss_fft_scalar *re, kiss_fft_scalar *im, int n)
fl::vector< kiss_fft_scalar > mWorkBuf
static void batchMag(const kiss_fft_scalar *re, const kiss_fft_scalar *im, u16 *mag, int n)
static FftScratch & scratch()
static u16 fastMag(i32 re, i32 im)
fl::vector< OctaveInfo > mOctaves
fl::vector< kiss_fft_cpx > mFftOut
void computeLinearBins(const u16 *mag, int, Bins *out)
void resize(fl::size n) FL_NOEXCEPT
Definition vector.h:593
void apply_kernels(kiss_fft_cpx fft[], kiss_fft_cpx cq[], struct sparse_arr kernels[], struct cq_kernel_cfg cfg) FL_NOEXCEPT
void fl_fft_real_forward(kiss_fftr_cfg cfg, int N, const kiss_fft_scalar *in, kiss_fft_cpx *out) FL_NOEXCEPT
Forward real-to-complex FFT.
constexpr enable_if< is_fixed_point< T >::value, T >::type sqrt(T x) FL_NOEXCEPT
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
const oct_t oct
Definition ios.cpp.hpp:8

References apply_kernels(), batchMag(), fl::audio::fft::Context::OctaveInfo::cfg, computeLinearBins(), fl::vector< T >::data(), decimateBy2(), deinterleave(), FASTLED_STACK_ARRAY, fastMag(), fl::audio::fft::Context::OctaveInfo::firstBin, fl::audio::fft::fl_fft_real_forward(), fl::audio::fft::Context::FftScratch::im, fl::audio::fft::Context::OctaveInfo::kernels, fl::audio::fft::Context::FftScratch::mag, fl::memset(), mFftOut, mFftrCfg, mFmax, mFmin, mInputSamples, mMaxBinsPerOctave, mOctaves, mSampleRate, mTotalBands, mWorkBuf, fl::audio::fft::Context::OctaveInfo::numBins, fl::oct, fl::audio::fft::Bins::raw_mut(), fl::audio::fft::Context::FftScratch::re, fl::vector< T >::resize(), scratch(), fl::audio::fft::Bins::setParams(), fl::span< T, Extent >::size(), and fl::sqrt().

Referenced by run().

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