- const float *ptrs[] = { left.data(), right.data() };
- {
- lock_guard<mutex> lock(audio_measure_mutex);
- bus_r128[bus_index]->process(left.size(), const_cast<float **>(ptrs));
+ assert(left.size() == right.size());
+ const float peak_levels[2] = {
+ find_peak(left.data(), left.size()) * volume,
+ find_peak(right.data(), right.size()) * volume
+ };
+ for (unsigned channel = 0; channel < 2; ++channel) {
+ // Compute the current value, including hold and falloff.
+ // The constants are borrowed from zita-mu1 by Fons Adriaensen.
+ static constexpr float hold_sec = 0.5f;
+ static constexpr float falloff_db_sec = 15.0f; // dB/sec falloff after hold.
+ float current_peak;
+ PeakHistory &history = peak_history[bus_index][channel];
+ if (history.age_seconds < hold_sec) {
+ current_peak = history.last_peak;
+ } else {
+ current_peak = history.last_peak * from_db(-falloff_db_sec * (history.age_seconds - hold_sec));
+ }
+
+ // See if we have a new peak to replace the old (possibly falling) one.
+ if (peak_levels[channel] > current_peak) {
+ history.last_peak = peak_levels[channel];
+ history.age_seconds = 0.0f; // Not 100% correct, but more than good enough given our frame sizes.
+ current_peak = peak_levels[channel];
+ } else {
+ history.age_seconds += float(left.size()) / OUTPUT_FREQUENCY;
+ }
+ history.current_level = peak_levels[channel];
+ history.current_peak = current_peak;