]> git.sesse.net Git - nageru/blobdiff - audio_mixer.cpp
Let settings follow buses when editing the mapping.
[nageru] / audio_mixer.cpp
index 8485d0a6343fec00a97fe2417dd46d7aac0bb248..197b4f34605a1b27818c4fb45a40fd715387a83b 100644 (file)
@@ -13,6 +13,7 @@
 #include "db.h"
 #include "flags.h"
 #include "mixer.h"
+#include "state.pb.h"
 #include "timebase.h"
 
 using namespace bmusb;
@@ -162,36 +163,43 @@ AudioMixer::AudioMixer(unsigned num_cards)
          limiter(OUTPUT_FREQUENCY),
          correlation(OUTPUT_FREQUENCY)
 {
+       global_audio_mixer = this;
+
        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);
-
-       // Generate a very simple, default input mapping.
-       InputMapping::Bus input;
-       input.name = "Main";
-       input.device.type = InputSourceType::CAPTURE_CARD;
-       input.device.index = 0;
-       input.source_channel[0] = 0;
-       input.source_channel[1] = 1;
+       alsa_pool.init();
 
        InputMapping new_input_mapping;
-       new_input_mapping.buses.push_back(input);
-       set_input_mapping(new_input_mapping);
+       if (!global_flags.input_mapping_filename.empty()) {
+               if (!load_input_mapping_from_file(get_devices(),
+                                                 global_flags.input_mapping_filename,
+                                                 &new_input_mapping)) {
+                       fprintf(stderr, "Failed to load input mapping from '%s', exiting.\n",
+                               global_flags.input_mapping_filename.c_str());
+                       exit(1);
+               }
+       } else {
+               // Generate a very simple, default input mapping.
+               InputMapping::Bus input;
+               input.name = "Main";
+               input.device.type = InputSourceType::CAPTURE_CARD;
+               input.device.index = 0;
+               input.source_channel[0] = 0;
+               input.source_channel[1] = 1;
 
-       alsa_pool.init();
+               new_input_mapping.buses.push_back(input);
+       }
+       set_input_mapping(new_input_mapping);
 
        r128.init(2, OUTPUT_FREQUENCY);
        r128.integr_start();
@@ -294,6 +302,67 @@ bool AudioMixer::add_silence(DeviceSpec device_spec, unsigned samples_per_frame,
        return true;
 }
 
+bool AudioMixer::silence_card(DeviceSpec device_spec, bool silence)
+{
+       AudioDevice *device = find_audio_device(device_spec);
+
+       unique_lock<timed_mutex> lock(audio_mutex, defer_lock);
+       if (!lock.try_lock_for(chrono::milliseconds(10))) {
+               return false;
+       }
+
+       if (device->silenced && !silence) {
+               reset_resampler_mutex_held(device_spec);
+       }
+       device->silenced = 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<timed_mutex> 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<timed_mutex> 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) {
@@ -383,11 +452,15 @@ vector<float> AudioMixer::get_output(double pts, unsigned num_samples, Resamplin
        for (const DeviceSpec &device_spec : get_active_devices()) {
                AudioDevice *device = find_audio_device(device_spec);
                samples_card[device_spec].resize(num_samples * device->interesting_channels.size());
-               device->resampling_queue->get_output_samples(
-                       pts,
-                       &samples_card[device_spec][0],
-                       num_samples,
-                       rate_adjustment_policy);
+               if (device->silenced) {
+                       memset(&samples_card[device_spec][0], 0, samples_card[device_spec].size() * sizeof(float));
+               } else {
+                       device->resampling_queue->get_output_samples(
+                               pts,
+                               &samples_card[device_spec][0],
+                               num_samples,
+                               rate_adjustment_policy);
+               }
        }
 
        vector<float> samples_out, left, right;
@@ -721,8 +794,8 @@ map<DeviceSpec, DeviceInfo> AudioMixer::get_devices()
                const DeviceSpec spec{ InputSourceType::CAPTURE_CARD, card_index };
                const AudioDevice *device = &video_cards[card_index];
                DeviceInfo info;
-               info.name = device->name;
-               info.num_channels = 8;  // FIXME: This is wrong for fake cards.
+               info.display_name = device->display_name;
+               info.num_channels = 8;
                devices.insert(make_pair(spec, info));
        }
        vector<ALSAPool::Device> available_alsa_devices = alsa_pool.get_devices();
@@ -730,19 +803,40 @@ map<DeviceSpec, DeviceInfo> AudioMixer::get_devices()
                const DeviceSpec spec{ InputSourceType::ALSA_INPUT, card_index };
                const ALSAPool::Device &device = available_alsa_devices[card_index];
                DeviceInfo info;
-               info.name = device.name + " (" + device.info + ")";
+               info.display_name = device.display_name();
                info.num_channels = device.num_channels;
+               info.alsa_name = device.name;
+               info.alsa_info = device.info;
+               info.alsa_address = device.address;
                devices.insert(make_pair(spec, info));
        }
        return devices;
 }
 
-void AudioMixer::set_name(DeviceSpec device_spec, const string &name)
+void AudioMixer::set_display_name(DeviceSpec device_spec, const string &name)
 {
        AudioDevice *device = find_audio_device(device_spec);
 
        lock_guard<timed_mutex> lock(audio_mutex);
-       device->name = name;
+       device->display_name = name;
+}
+
+void AudioMixer::serialize_device(DeviceSpec device_spec, DeviceSpecProto *device_spec_proto)
+{
+       lock_guard<timed_mutex> lock(audio_mutex);
+       switch (device_spec.type) {
+               case InputSourceType::SILENCE:
+                       device_spec_proto->set_type(DeviceSpecProto::SILENCE);
+                       break;
+               case InputSourceType::CAPTURE_CARD:
+                       device_spec_proto->set_type(DeviceSpecProto::CAPTURE_CARD);
+                       device_spec_proto->set_index(device_spec.index);
+                       device_spec_proto->set_display_name(video_cards[device_spec.index].display_name);
+                       break;
+               case InputSourceType::ALSA_INPUT:
+                       alsa_pool.serialize_device(device_spec.index, device_spec_proto);
+                       break;
+       }
 }
 
 void AudioMixer::set_input_mapping(const InputMapping &new_input_mapping)