From 26e1ec466d4730b6abc0e20201d704cfdf41a6eb Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 21 Sep 2016 19:00:21 +0200 Subject: [PATCH] Let settings follow buses when editing the mapping. If a user wants to add a new bus (or delete one), we shouldn't delete all their settings. Track them as a nicely bound-together hidden state when editing. (This also lays the ground for serialization of the entire mixer state in the future, should we want to do that.) --- audio_mixer.cpp | 53 +++++++++++++++++++++++++++++++++++----- audio_mixer.h | 16 ++++++++++++ input_mapping_dialog.cpp | 15 ++++++++++++ input_mapping_dialog.h | 5 ++++ 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/audio_mixer.cpp b/audio_mixer.cpp index c7676b5..197b4f3 100644 --- a/audio_mixer.cpp +++ b/audio_mixer.cpp @@ -167,17 +167,13 @@ AudioMixer::AudioMixer(unsigned num_cards) for (unsigned bus_index = 0; bus_index < MAX_BUSES; ++bus_index) { locut[bus_index].init(FILTER_HPF, 2); - locut_enabled[bus_index] = global_flags.locut_enabled; eq[bus_index][EQ_BAND_BASS].init(FILTER_LOW_SHELF, 1); // Note: EQ_BAND_MID isn't used (see comments in apply_eq()). eq[bus_index][EQ_BAND_TREBLE].init(FILTER_HIGH_SHELF, 1); - - gain_staging_db[bus_index] = global_flags.initial_gain_staging_db; compressor[bus_index].reset(new StereoCompressor(OUTPUT_FREQUENCY)); - compressor_threshold_dbfs[bus_index] = ref_level_dbfs - 12.0f; // -12 dB. - compressor_enabled[bus_index] = global_flags.compressor_enabled; level_compressor[bus_index].reset(new StereoCompressor(OUTPUT_FREQUENCY)); - level_compressor_enabled[bus_index] = global_flags.gain_staging_auto; + + set_bus_settings(bus_index, get_default_bus_settings()); } set_limiter_enabled(global_flags.limiter_enabled); set_final_makeup_gain_auto(global_flags.final_makeup_gain_auto); @@ -322,6 +318,51 @@ bool AudioMixer::silence_card(DeviceSpec device_spec, bool silence) return true; } +AudioMixer::BusSettings AudioMixer::get_default_bus_settings() +{ + BusSettings settings; + settings.fader_volume_db = 0.0f; + settings.locut_enabled = global_flags.locut_enabled; + for (unsigned band_index = 0; band_index < NUM_EQ_BANDS; ++band_index) { + settings.eq_level_db[band_index] = 0.0f; + } + settings.gain_staging_db = global_flags.initial_gain_staging_db; + settings.level_compressor_enabled = global_flags.gain_staging_auto; + settings.compressor_threshold_dbfs = ref_level_dbfs - 12.0f; // -12 dB. + settings.compressor_enabled = global_flags.compressor_enabled; + return settings; +} + +AudioMixer::BusSettings AudioMixer::get_bus_settings(unsigned bus_index) const +{ + lock_guard lock(audio_mutex); + BusSettings settings; + settings.fader_volume_db = fader_volume_db[bus_index]; + settings.locut_enabled = locut_enabled[bus_index]; + for (unsigned band_index = 0; band_index < NUM_EQ_BANDS; ++band_index) { + settings.eq_level_db[band_index] = eq_level_db[bus_index][band_index]; + } + settings.gain_staging_db = gain_staging_db[bus_index]; + settings.level_compressor_enabled = level_compressor_enabled[bus_index]; + settings.compressor_threshold_dbfs = compressor_threshold_dbfs[bus_index]; + settings.compressor_enabled = compressor_enabled[bus_index]; + return settings; +} + +void AudioMixer::set_bus_settings(unsigned bus_index, const AudioMixer::BusSettings &settings) +{ + lock_guard lock(audio_mutex); + fader_volume_db[bus_index] = settings.fader_volume_db; + locut_enabled[bus_index] = settings.locut_enabled; + for (unsigned band_index = 0; band_index < NUM_EQ_BANDS; ++band_index) { + eq_level_db[bus_index][band_index] = settings.eq_level_db[band_index]; + } + gain_staging_db[bus_index] = settings.gain_staging_db; + level_compressor_enabled[bus_index] = settings.level_compressor_enabled; + compressor_threshold_dbfs[bus_index] = settings.compressor_threshold_dbfs; + compressor_enabled[bus_index] = settings.compressor_enabled; +} + AudioMixer::AudioDevice *AudioMixer::find_audio_device(DeviceSpec device) { switch (device.type) { diff --git a/audio_mixer.h b/audio_mixer.h index faa0cc5..502a442 100644 --- a/audio_mixer.h +++ b/audio_mixer.h @@ -252,6 +252,22 @@ public: } } + // A combination of all settings for a bus. Useful if you want to get + // or store them as a whole without bothering to call all of the get_* + // or set_* functions for that bus. + struct BusSettings { + float fader_volume_db; + bool locut_enabled; + float eq_level_db[NUM_EQ_BANDS]; + float gain_staging_db; + bool level_compressor_enabled; + float compressor_threshold_dbfs; + bool compressor_enabled; + }; + static BusSettings get_default_bus_settings(); + BusSettings get_bus_settings(unsigned bus_index) const; + void set_bus_settings(unsigned bus_index, const BusSettings &settings); + private: struct AudioDevice { std::unique_ptr resampling_queue; diff --git a/input_mapping_dialog.cpp b/input_mapping_dialog.cpp index 232a88d..c81e292 100644 --- a/input_mapping_dialog.cpp +++ b/input_mapping_dialog.cpp @@ -16,6 +16,10 @@ InputMappingDialog::InputMappingDialog() old_mapping(mapping), devices(global_audio_mixer->get_devices()) { + for (unsigned bus_index = 0; bus_index < mapping.buses.size(); ++bus_index) { + bus_settings.push_back(global_audio_mixer->get_bus_settings(bus_index)); + } + ui->setupUi(this); ui->table->setSelectionBehavior(QAbstractItemView::SelectRows); ui->table->setSelectionMode(QAbstractItemView::SingleSelection); // Makes implementing moving easier for now. @@ -149,6 +153,10 @@ void InputMappingDialog::ok_clicked() { global_audio_mixer->set_state_changed_callback(saved_callback); global_audio_mixer->set_input_mapping(mapping); + for (unsigned bus_index = 0; bus_index < mapping.buses.size(); ++bus_index) { + global_audio_mixer->set_bus_settings(bus_index, bus_settings[bus_index]); + global_audio_mixer->reset_peak(bus_index); + } accept(); } @@ -189,6 +197,7 @@ void InputMappingDialog::add_clicked() new_bus.name = "New input"; new_bus.device.type = InputSourceType::SILENCE; mapping.buses.push_back(new_bus); + bus_settings.push_back(AudioMixer::get_default_bus_settings()); ui->table->setRowCount(mapping.buses.size()); unsigned row = mapping.buses.size() - 1; @@ -214,6 +223,7 @@ void InputMappingDialog::remove_clicked() for (int row : rows_to_delete) { ui->table->removeRow(row); mapping.buses.erase(mapping.buses.begin() + row); + bus_settings.erase(bus_settings.begin() + row); } update_button_state(); } @@ -226,6 +236,7 @@ void InputMappingDialog::updown_clicked(int direction) int b_row = range.bottomRow() + direction; swap(mapping.buses[a_row], mapping.buses[b_row]); + swap(bus_settings[a_row], bus_settings[b_row]); fill_row_from_bus(a_row, mapping.buses[a_row]); fill_row_from_bus(b_row, mapping.buses[b_row]); @@ -262,6 +273,10 @@ void InputMappingDialog::load_clicked() } mapping = new_mapping; + bus_settings.clear(); + for (unsigned bus_index = 0; bus_index < mapping.buses.size(); ++bus_index) { + bus_settings.push_back(global_audio_mixer->get_bus_settings(bus_index)); + } devices = global_audio_mixer->get_devices(); // New dead cards may have been made. fill_ui_from_mapping(mapping); } diff --git a/input_mapping_dialog.h b/input_mapping_dialog.h index e24a801..3fa11e3 100644 --- a/input_mapping_dialog.h +++ b/input_mapping_dialog.h @@ -47,6 +47,11 @@ private: // held forever). InputMapping old_mapping; + // One for each bus in the mapping. Edited along with the mapping, + // so that old volumes etc. are being kept in place for buses that + // existed before. + std::vector bus_settings; + std::map devices; // Needs no lock, accessed only on the UI thread. AudioMixer::state_changed_callback_t saved_callback; }; -- 2.39.2