693 {
695 const int numOctaves =
static_cast<int>(
mOctaves.size());
696 const int numRawBins = N / 2 + 1;
697
699
700
701 int workLen = N;
702 for (int i = 0; i < N; i++) {
704 (i < static_cast<int>(buffer.size())) ? buffer[i] : 0;
705 }
706
707
709
710
712 s.re.resize(numRawBins);
713 s.im.resize(numRawBins);
714 s.mag.resize(numRawBins);
716 batchMag(s.re.data(), s.im.data(), s.mag.data(), numRawBins);
717
719
720
721 fl::vector<float> &rawBins = out->raw_mut();
724 rawBins[i] = 0.0f;
725 }
726
727
729
730
731
732
733 for (
int oct = numOctaves - 1;
oct >= 0;
oct--) {
735 if (oi.numBins <= 0 || !oi.kernels)
736 continue;
737
738 if (
oct != numOctaves - 1) {
740 workLen = workLen / 2;
741
742 for (int i = workLen; i < N; i++)
745 }
746
747 fl::memset(cq, 0,
sizeof(kiss_fft_cpx) * oi.numBins);
749
750 for (int i = 0; i < oi.numBins; i++) {
751 int binIdx = oi.firstBin + i;
752 i32 real = cq[i].r;
753 i32 imag = cq[i].i;
754#ifdef FIXED_POINT
755 rawBins[binIdx] =
static_cast<float>(
fastMag(real, imag));
756#else
757 float r2 = float(real * real);
758 float i2 = float(imag * imag);
759 rawBins[binIdx] =
sqrt(r2 + i2);
760#endif
761 }
762 }
763
764
765
766
767
768 s.windowed.resize(N);
769 s.fftOut.resize(N);
773 deinterleave(s.fftOut.data(), s.re.data(), s.im.data(), numRawBins);
774 batchMag(s.re.data(), s.im.data(), s.mag.data(), numRawBins);
778
779
780
781 static constexpr float kCoverageGain = 0.02f;
785#ifdef FIXED_POINT
786
787 s.cqSnapshot[i] = static_cast<u32>(rawBins[i]);
788#else
789 s.cqSnapshot[i] = rawBins[i];
790#endif
791 }
792 int head = 0;
793 int tail = 0;
794 int next = 0;
797 while (tail > head &&
798 s.cqSnapshot[s.coverageMaxQueue[tail - 1]] <=
799 s.cqSnapshot[next]) {
800 --tail;
801 }
802 s.coverageMaxQueue[tail++] = static_cast<u16>(next++);
803 }
804 while (head < tail &&
806 ++head;
807 }
808#ifdef FIXED_POINT
809
810
812 s.rawBinsI[i], s.cqSnapshot[i],
813 s.cqSnapshot[s.coverageMaxQueue[head]])) {
814 rawBins[i] = static_cast<float>(s.rawBinsI[i]) * kCoverageGain;
815 }
816#else
817 const float localCq = s.cqSnapshot[s.coverageMaxQueue[head]];
818 static constexpr float kDetectedCqMagnitude = 20.0f;
819 float coverage = static_cast<float>(s.rawBinsI[i]) * kCoverageGain;
820 if (localCq < kDetectedCqMagnitude && coverage > rawBins[i]) {
821 rawBins[i] = coverage;
822 }
823#endif
824 }
825 }
#define FASTLED_STACK_ARRAY(TYPE, NAME, SIZE)
Stack-allocated array with automatic zero-initialization.
static void batchMag(const kiss_fft_scalar *re, const kiss_fft_scalar *im, u16 *mag, int n) FL_NO_EXCEPT
void computeLinearBins(const u16 *mag, int, Bins *out) FL_NO_EXCEPT
void logRebinRange(const u16 *mag, int fftN, float fs, int binStart, int binEnd, u32 *rawBinsI, const fl::vector< u8 > &lut) FL_NO_EXCEPT
fl::vector< kiss_fft_scalar > mWorkBuf
fl::vector< alpha16 > mWindowBuf
fl::vector< u16 > mCoverageLast
static u16 fastMag(i32 re, i32 im) FL_NO_EXCEPT
static FftScratch & scratch() FL_NO_EXCEPT
static void deinterleave(const kiss_fft_cpx *cpx, kiss_fft_scalar *re, kiss_fft_scalar *im, int n) FL_NO_EXCEPT
fl::vector< u16 > mCoverageFirst
fl::vector< OctaveInfo > mOctaves
static void applyWindow(const kiss_fft_scalar *samples, const alpha16 *win, kiss_fft_scalar *out, int N) FL_NO_EXCEPT
fl::vector< u8 > mLogBinLut
fl::vector< kiss_fft_cpx > mFftOut
static void decimateBy2(kiss_fft_scalar *buf, int len) FL_NO_EXCEPT
void resize(fl::size n) FL_NO_EXCEPT
void apply_kernels(kiss_fft_cpx fft[], kiss_fft_cpx cq[], struct sparse_arr kernels[], struct cq_kernel_cfg cfg)
void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata, kiss_fft_cpx *freqdata)
bool coverageFloorApplies(u32 fftMag, u32 cqMag, u32 localCqMax) FL_NO_EXCEPT
CQ_OCTAVE coverage supplement decision (FastLED#4301/#4540), integer form used in FIXED16: the full-r...
FASTLED_FORCE_INLINE void * memset(void *s, int c, size_t n) FL_NO_EXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type sqrt(T x) FL_NO_EXCEPT