X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=audio_mixer.cpp;h=a2f25f0a2d93fb5a8c29dae5548ed33cee723302;hb=737a04d0d56708e39805f33a6e948b5c1908ed39;hp=e28acfeb00154d2926e1f00c9fa26382c511aae8;hpb=1d75037f1e47e1e86adc444417922b402ba8272a;p=nageru diff --git a/audio_mixer.cpp b/audio_mixer.cpp index e28acfe..a2f25f0 100644 --- a/audio_mixer.cpp +++ b/audio_mixer.cpp @@ -12,6 +12,7 @@ #include "db.h" #include "flags.h" +#include "mixer.h" #include "timebase.h" using namespace bmusb; @@ -190,8 +191,7 @@ AudioMixer::AudioMixer(unsigned num_cards) new_input_mapping.buses.push_back(input); set_input_mapping(new_input_mapping); - // Look for ALSA cards. - available_alsa_cards = ALSAInput::enumerate_devices(); + alsa_pool.init(); r128.init(2, OUTPUT_FREQUENCY); r128.integr_start(); @@ -201,17 +201,6 @@ AudioMixer::AudioMixer(unsigned num_cards) peak_resampler.setup(OUTPUT_FREQUENCY, OUTPUT_FREQUENCY * 4, /*num_channels=*/2, /*hlen=*/16, /*frel=*/1.0); } -AudioMixer::~AudioMixer() -{ - for (unsigned card_index = 0; card_index < available_alsa_cards.size(); ++card_index) { - const AudioDevice &device = alsa_inputs[card_index]; - if (device.alsa_device != nullptr) { - device.alsa_device->stop_capture_thread(); - } - } -} - - void AudioMixer::reset_resampler(DeviceSpec device_spec) { lock_guard lock(audio_mutex); @@ -232,25 +221,6 @@ void AudioMixer::reset_resampler_mutex_held(DeviceSpec device_spec) device->next_local_pts = 0; } -void AudioMixer::reset_alsa_mutex_held(DeviceSpec device_spec) -{ - assert(device_spec.type == InputSourceType::ALSA_INPUT); - unsigned card_index = device_spec.index; - AudioDevice *device = find_audio_device(device_spec); - - if (device->alsa_device != nullptr) { - device->alsa_device->stop_capture_thread(); - } - if (device->interesting_channels.empty()) { - device->alsa_device.reset(); - } else { - const ALSAInput::Device &alsa_dev = available_alsa_cards[card_index]; - device->alsa_device.reset(new ALSAInput(alsa_dev.address.c_str(), OUTPUT_FREQUENCY, alsa_dev.num_channels, bind(&AudioMixer::add_audio, this, device_spec, _1, _2, _3, _4))); - device->capture_frequency = device->alsa_device->get_sample_rate(); - device->alsa_device->start_capture_thread(); - } -} - bool AudioMixer::add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, AudioFormat audio_format, int64_t frame_length) { AudioDevice *device = find_audio_device(device_spec); @@ -324,6 +294,22 @@ 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 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::AudioDevice *AudioMixer::find_audio_device(DeviceSpec device) { switch (device.type) { @@ -384,6 +370,24 @@ void AudioMixer::fill_audio_bus(const map> &samples_ca } } +vector AudioMixer::get_active_devices() const +{ + vector ret; + for (unsigned card_index = 0; card_index < MAX_VIDEO_CARDS; ++card_index) { + const DeviceSpec device_spec{InputSourceType::CAPTURE_CARD, card_index}; + if (!find_audio_device(device_spec)->interesting_channels.empty()) { + ret.push_back(device_spec); + } + } + for (unsigned card_index = 0; card_index < MAX_ALSA_CARDS; ++card_index) { + const DeviceSpec device_spec{InputSourceType::ALSA_INPUT, card_index}; + if (!find_audio_device(device_spec)->interesting_channels.empty()) { + ret.push_back(device_spec); + } + } + return ret; +} + vector AudioMixer::get_output(double pts, unsigned num_samples, ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy) { map> samples_card; @@ -392,14 +396,12 @@ vector AudioMixer::get_output(double pts, unsigned num_samples, Resamplin lock_guard lock(audio_mutex); // Pick out all the interesting channels from all the cards. - // TODO: If the card has been hotswapped, the number of channels - // might have changed; if so, we need to do some sort of remapping - // to silence. - for (const auto &spec_and_info : get_devices_mutex_held()) { - const DeviceSpec &device_spec = spec_and_info.first; + for (const DeviceSpec &device_spec : get_active_devices()) { AudioDevice *device = find_audio_device(device_spec); - if (!device->interesting_channels.empty()) { - samples_card[device_spec].resize(num_samples * device->interesting_channels.size()); + samples_card[device_spec].resize(num_samples * device->interesting_channels.size()); + 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], @@ -730,26 +732,23 @@ void AudioMixer::send_audio_level_callback() correlation.get_correlation()); } -map AudioMixer::get_devices() const +map AudioMixer::get_devices() { lock_guard lock(audio_mutex); - return get_devices_mutex_held(); -} -map AudioMixer::get_devices_mutex_held() const -{ map devices; for (unsigned card_index = 0; card_index < num_cards; ++card_index) { 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.num_channels = 8; devices.insert(make_pair(spec, info)); } - for (unsigned card_index = 0; card_index < available_alsa_cards.size(); ++card_index) { + vector available_alsa_devices = alsa_pool.get_devices(); + for (unsigned card_index = 0; card_index < available_alsa_devices.size(); ++card_index) { const DeviceSpec spec{ InputSourceType::ALSA_INPUT, card_index }; - const ALSAInput::Device &device = available_alsa_cards[card_index]; + const ALSAPool::Device &device = available_alsa_devices[card_index]; DeviceInfo info; info.name = device.name + " (" + device.info + ")"; info.num_channels = device.num_channels; @@ -783,14 +782,25 @@ void AudioMixer::set_input_mapping(const InputMapping &new_input_mapping) } // Reset resamplers for all cards that don't have the exact same state as before. - for (const auto &spec_and_info : get_devices_mutex_held()) { - const DeviceSpec &device_spec = spec_and_info.first; + for (unsigned card_index = 0; card_index < MAX_VIDEO_CARDS; ++card_index) { + const DeviceSpec device_spec{InputSourceType::CAPTURE_CARD, card_index}; AudioDevice *device = find_audio_device(device_spec); if (device->interesting_channels != interesting_channels[device_spec]) { device->interesting_channels = interesting_channels[device_spec]; - if (device_spec.type == InputSourceType::ALSA_INPUT) { - reset_alsa_mutex_held(device_spec); - } + reset_resampler_mutex_held(device_spec); + } + } + for (unsigned card_index = 0; card_index < MAX_ALSA_CARDS; ++card_index) { + const DeviceSpec device_spec{InputSourceType::ALSA_INPUT, card_index}; + AudioDevice *device = find_audio_device(device_spec); + if (interesting_channels[device_spec].empty()) { + alsa_pool.release_device(card_index); + } else { + alsa_pool.hold_device(card_index); + } + if (device->interesting_channels != interesting_channels[device_spec]) { + device->interesting_channels = interesting_channels[device_spec]; + alsa_pool.reset_device(device_spec.index); reset_resampler_mutex_held(device_spec); } }