]> git.sesse.net Git - nageru/blobdiff - audio_mixer.cpp
Add support for EQ filters to the Filter class.
[nageru] / audio_mixer.cpp
index 6b7ffeb0d6d28fb1ffdbfa8308ab341970893b20..193d221627cfce48738795d5200476bf972d3c76 100644 (file)
@@ -462,19 +462,9 @@ vector<float> AudioMixer::get_output(double pts, unsigned num_samples, Resamplin
                        }
                }
 
-               float volume = from_db(fader_volume_db[bus_index]);
-               if (bus_index == 0) {
-                       for (unsigned i = 0; i < num_samples * 2; ++i) {
-                               samples_out[i] = samples_bus[i] * volume;
-                       }
-               } else {
-                       for (unsigned i = 0; i < num_samples * 2; ++i) {
-                               samples_out[i] += samples_bus[i] * volume;
-                       }
-               }
-
+               add_bus_to_master(bus_index, samples_bus, &samples_out);
                deinterleave_samples(samples_bus, &left, &right);
-               measure_bus_levels(bus_index, left, right, volume);
+               measure_bus_levels(bus_index, left, right);
        }
 
        {
@@ -541,9 +531,56 @@ vector<float> AudioMixer::get_output(double pts, unsigned num_samples, Resamplin
        return samples_out;
 }
 
-void AudioMixer::measure_bus_levels(unsigned bus_index, const vector<float> &left, const vector<float> &right, float volume)
+void AudioMixer::add_bus_to_master(unsigned bus_index, const vector<float> &samples_bus, vector<float> *samples_out)
+{
+       assert(samples_bus.size() == samples_out->size());
+       assert(samples_bus.size() % 2 == 0);
+       unsigned num_samples = samples_bus.size() / 2;
+       if (fabs(fader_volume_db[bus_index] - last_fader_volume_db[bus_index]) > 1e-3) {
+               // The volume has changed; do a fade over the course of this frame.
+               // (We might have some numerical issues here, but it seems to sound OK.)
+               // For the purpose of fading here, the silence floor is set to -90 dB
+               // (the fader only goes to -84).
+               float old_volume = from_db(max<float>(last_fader_volume_db[bus_index], -90.0f));
+               float volume = from_db(max<float>(fader_volume_db[bus_index], -90.0f));
+
+               float volume_inc = pow(volume / old_volume, 1.0 / num_samples);
+               volume = old_volume;
+               if (bus_index == 0) {
+                       for (unsigned i = 0; i < num_samples; ++i) {
+                               (*samples_out)[i * 2 + 0] = samples_bus[i * 2 + 0] * volume;
+                               (*samples_out)[i * 2 + 1] = samples_bus[i * 2 + 1] * volume;
+                               volume *= volume_inc;
+                       }
+               } else {
+                       for (unsigned i = 0; i < num_samples; ++i) {
+                               (*samples_out)[i * 2 + 0] += samples_bus[i * 2 + 0] * volume;
+                               (*samples_out)[i * 2 + 1] += samples_bus[i * 2 + 1] * volume;
+                               volume *= volume_inc;
+                       }
+               }
+       } else {
+               float volume = from_db(fader_volume_db[bus_index]);
+               if (bus_index == 0) {
+                       for (unsigned i = 0; i < num_samples; ++i) {
+                               (*samples_out)[i * 2 + 0] = samples_bus[i * 2 + 0] * volume;
+                               (*samples_out)[i * 2 + 1] = samples_bus[i * 2 + 1] * volume;
+                       }
+               } else {
+                       for (unsigned i = 0; i < num_samples; ++i) {
+                               (*samples_out)[i * 2 + 0] += samples_bus[i * 2 + 0] * volume;
+                               (*samples_out)[i * 2 + 1] += samples_bus[i * 2 + 1] * volume;
+                       }
+               }
+       }
+
+       last_fader_volume_db[bus_index] = fader_volume_db[bus_index];
+}
+
+void AudioMixer::measure_bus_levels(unsigned bus_index, const vector<float> &left, const vector<float> &right)
 {
        assert(left.size() == right.size());
+       const float volume = from_db(fader_volume_db[bus_index]);
        const float peak_levels[2] = {
                find_peak(left.data(), left.size()) * volume,
                find_peak(right.data(), right.size()) * volume
@@ -555,6 +592,7 @@ void AudioMixer::measure_bus_levels(unsigned bus_index, const vector<float> &lef
                static constexpr float falloff_db_sec = 15.0f;  // dB/sec falloff after hold.
                float current_peak;
                PeakHistory &history = peak_history[bus_index][channel];
+               history.historic_peak = max(history.historic_peak, peak_levels[channel]);
                if (history.age_seconds < hold_sec) {
                        current_peak = history.last_peak;
                } else {
@@ -639,6 +677,9 @@ void AudioMixer::send_audio_level_callback()
                        bus_levels[bus_index].current_level_dbfs[1] = to_db(peak_history[bus_index][1].current_level);
                        bus_levels[bus_index].peak_level_dbfs[0] = to_db(peak_history[bus_index][0].current_peak);
                        bus_levels[bus_index].peak_level_dbfs[1] = to_db(peak_history[bus_index][1].current_peak);
+                       bus_levels[bus_index].historic_peak_dbfs = to_db(
+                               max(peak_history[bus_index][0].historic_peak,
+                                   peak_history[bus_index][1].historic_peak));
                        bus_levels[bus_index].gain_staging_db = gain_staging_db[bus_index];
                        if (compressor_enabled[bus_index]) {
                                bus_levels[bus_index].compressor_attenuation_db = -to_db(compressor[bus_index]->get_attenuation());
@@ -727,3 +768,16 @@ InputMapping AudioMixer::get_input_mapping() const
        lock_guard<timed_mutex> lock(audio_mutex);
        return input_mapping;
 }
+
+void AudioMixer::reset_peak(unsigned bus_index)
+{
+       lock_guard<timed_mutex> lock(audio_mutex);
+       for (unsigned channel = 0; channel < 2; ++channel) {
+               PeakHistory &history = peak_history[bus_index][channel];
+               history.current_level = 0.0f;
+               history.historic_peak = 0.0f;
+               history.current_peak = 0.0f;
+               history.last_peak = 0.0f;
+               history.age_seconds = 0.0f;
+       }
+}