LOG_REBIN helper: group FFT bins into CQ output bins [binStart, binEnd) Uses pre-computed LUT for O(1) bin mapping per FFT bin.
| 1008 | // LOG_REBIN helper: group FFT bins into CQ output bins [binStart, binEnd) |
| 1009 | // Uses pre-computed LUT for O(1) bin mapping per FFT bin. |
| 1010 | void logRebinRange(const u16 *mag, int fftN, float fs, |
| 1011 | int binStart, int binEnd, |
| 1012 | u32 *rawBinsI, const fl::vector<u8>& lut) { |
| 1013 | const int numRawBins = fftN / 2 + 1; |
| 1014 | // Compute loop bounds to skip out-of-range FFT bins |
| 1015 | const u16x16 rawBinHz(fs / static_cast<float>(fftN)); |
| 1016 | const u16x16 halfBin = rawBinHz >> 1; |
| 1017 | const u16x16 loEdge(mLogBinEdges[binStart]); |
| 1018 | const u16x16 hiEdge(mLogBinEdges[binEnd]); |
| 1019 | |
| 1020 | int kStart = 0; |
| 1021 | if (loEdge > halfBin) { |
| 1022 | kStart = static_cast<int>( |
| 1023 | u16x16::ceil((loEdge - halfBin) / rawBinHz).to_int()); |
| 1024 | } |
| 1025 | int kEnd = static_cast<int>( |
| 1026 | u16x16::ceil((hiEdge + halfBin) / rawBinHz).to_int()); |
| 1027 | if (kEnd > numRawBins) kEnd = numRawBins; |
| 1028 | |
| 1029 | for (int k = kStart; k < kEnd; ++k) { |
| 1030 | rawBinsI[lut[k]] += static_cast<u32>(mag[k]); |
| 1031 | } |
| 1032 | } |
| 1033 | |
| 1034 | void computeLinearBins(const u16 *mag, int /*nfft*/, Bins *out) { |
| 1035 | const int numLinearBins = mTotalBands; |