246 {
247
248
249
250
251
252
253
254 auto linearBins =
fft.linear();
255 if (linearBins.size() < 4) return 0.0f;
256
257 const int numBins = static_cast<int>(linearBins.size());
258 const float fmin =
fft.linearFmin();
259 const float fmax =
fft.linearFmax();
260 const float binWidth = (fmax - fmin) / static_cast<float>(numBins);
261
262
263 auto freqToLinBin = [&](float freq) -> int {
264 if (freq <= fmin) return 0;
265 if (freq >= fmax) return numBins - 1;
266 return fl::min(numBins - 1,
static_cast<int>((freq - fmin) / binWidth));
267 };
268
269 const int presMinBin = freqToLinBin(2000.0f);
270 const int presMaxBin = freqToLinBin(4000.0f);
271 const int bassMinBin = freqToLinBin(200.0f);
272 const int bassMaxBin = freqToLinBin(500.0f);
273
274 float presEnergy = 0.0f;
275 int presCount = 0;
276 for (int i = presMinBin; i <= presMaxBin && i < numBins; ++i) {
277 presEnergy += linearBins[i] * linearBins[i];
278 ++presCount;
279 }
280 if (presCount > 0) presEnergy /= static_cast<float>(presCount);
281
282 float bassEnergy = 0.0f;
283 int bassCount = 0;
284 for (int i = bassMinBin; i <= bassMaxBin && i < numBins; ++i) {
285 bassEnergy += linearBins[i] * linearBins[i];
286 ++bassCount;
287 }
288 if (bassCount > 0) bassEnergy /= static_cast<float>(bassCount);
289
290 if (bassEnergy < 1e-12f) return 0.0f;
291 return presEnergy / bassEnergy;
292}
FL_DISABLE_WARNING_PUSH U constexpr common_type_t< T, U > min(T a, U b) FL_NOEXCEPT