| 129 | } |
| 130 | |
| 131 | void EqualizerDetector::update(shared_ptr<Context> context) { |
| 132 | mSampleRate = context->getSampleRate(); |
| 133 | |
| 134 | span<const i16> pcm = context->getPCM(); |
| 135 | if (pcm.size() == 0) return; |
| 136 | |
| 137 | const float dt = computeAudioDt(pcm.size(), mSampleRate); |
| 138 | |
| 139 | // Use Context's cached fft::FFT (shared across detector) |
| 140 | mRetainedFFT = context->getFFT(kNumBins, mConfig.minFreq, mConfig.maxFreq); |
| 141 | if (!mRetainedFFT) return; |
| 142 | const fft::Bins& fftBins = *mRetainedFFT; |
| 143 | |
| 144 | const auto& raw = fftBins.raw(); |
| 145 | const int numBins = fl::min(static_cast<int>(raw.size()), kNumBins); |
| 146 | float scaledBins[kNumBins] = {}; |
| 147 | |
| 148 | // Fused loop: Steps 1-4 (Copy, mic correction, pink noise, gain, scaling) |
| 149 | // Combined for better cache locality and reduced memory bandwidth |
| 150 | const bool applyMicCorrection = mHasMicCorrection; |
| 151 | const bool applyScalingMode = (mConfig.scalingMode != FFTScalingMode::None && |
| 152 | mConfig.scalingMode != FFTScalingMode::Linear); |
| 153 | const bool applyGain = (mGain != 1.0f); |
| 154 | |
| 155 | for (int i = 0; i < numBins; ++i) { |
| 156 | // Step 1: Copy raw and apply fft::FFT downscale |
| 157 | float val = raw[i] * kFFTDownscale; |
| 158 | |
| 159 | // Step 2: Microphone correction |
| 160 | if (applyMicCorrection) { |
| 161 | val *= mMicGains[i]; |
| 162 | } |
| 163 | |
| 164 | // Step 2.5: Pink noise spectral tilt compensation |
| 165 | val *= mPinkNoiseGains[i]; |
| 166 | |
| 167 | // Step 3: Apply gain |
| 168 | if (applyGain) { |
| 169 | val *= mGain; |
| 170 | } |
| 171 | |
| 172 | // Step 4: Apply fft::FFT scaling mode |
| 173 | if (applyScalingMode) { |
| 174 | val = applyScaling(val, mConfig.scalingMode); |
| 175 | } |
| 176 | |
| 177 | scaledBins[i] = val; |
| 178 | } |
| 179 | |
| 180 | // Step 5: Apply spectral equalization curve (if not flat) |
| 181 | if (mConfig.curve != EqualizationCurve::Flat) { |
| 182 | span<const float> inSpan(scaledBins, numBins); |
| 183 | span<float> outSpan(mEqBuffer, numBins); |
| 184 | mSpectralEq.apply(inSpan, outSpan); |
| 185 | for (int i = 0; i < numBins; ++i) { |
| 186 | scaledBins[i] = mEqBuffer[i]; |
| 187 | } |
| 188 | } |
nothing calls this directly
no test coverage detected