From c19abd24ee5929934a88adf1dd86107fc0cd5f61 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 10 Sep 2016 14:06:54 +0200 Subject: [PATCH] When an ALSA input goes away, replace it by silence. Silences the warning spew from the resampler that no data is coming. --- alsa_input.cpp | 17 +++++++++++++++-- audio_mixer.cpp | 30 +++++++++++++++++++++++++----- audio_mixer.h | 8 ++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/alsa_input.cpp b/alsa_input.cpp index a6487a4..0a39d3f 100644 --- a/alsa_input.cpp +++ b/alsa_input.cpp @@ -166,6 +166,8 @@ void ALSAInput::stop_capture_thread() void ALSAInput::capture_thread_func() { + parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING); + // If the device hasn't been opened already, we need to do so // before we can capture. while (!should_quit && pcm_handle == nullptr) { @@ -549,8 +551,15 @@ ALSAPool::Device::State ALSAPool::get_card_state(unsigned index) void ALSAPool::set_card_state(unsigned index, ALSAPool::Device::State state) { - lock_guard lock(mu); - devices[index].state = state; + { + lock_guard lock(mu); + devices[index].state = state; + } + + DeviceSpec spec{InputSourceType::ALSA_INPUT, index}; + bool silence = (state != ALSAPool::Device::State::RUNNING); + while (!global_audio_mixer->silence_card(spec, silence)) + ; } unsigned ALSAPool::find_free_device_index() @@ -570,6 +579,10 @@ unsigned ALSAPool::find_free_device_index() void ALSAPool::free_card(unsigned index) { + DeviceSpec spec{InputSourceType::ALSA_INPUT, index}; + while (!global_audio_mixer->silence_card(spec, true)) + ; + lock_guard lock(mu); if (devices[index].held) { devices[index].state = Device::State::DEAD; diff --git a/audio_mixer.cpp b/audio_mixer.cpp index 8485d0a..87a99bd 100644 --- a/audio_mixer.cpp +++ b/audio_mixer.cpp @@ -294,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) { @@ -383,11 +399,15 @@ vector 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 samples_out, left, right; diff --git a/audio_mixer.h b/audio_mixer.h index c845a26..855295d 100644 --- a/audio_mixer.h +++ b/audio_mixer.h @@ -93,6 +93,13 @@ public: bool add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, int64_t frame_length); bool add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length); + // If a given device is offline for whatever reason and cannot deliver audio + // (by means of add_audio() or add_silence()), you can call put it in silence mode, + // where it will be taken to only output silence. Note that when taking it _out_ + // of silence mode, the resampler will be reset, so that old audio will not + // affect it. Same true/false behavior as add_audio(). + bool silence_card(DeviceSpec device_spec, bool silence); + std::vector get_output(double pts, unsigned num_samples, ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy); void set_fader_volume(unsigned bus_index, float level_db) { fader_volume_db[bus_index] = level_db; } @@ -263,6 +270,7 @@ private: unsigned capture_frequency = OUTPUT_FREQUENCY; // Which channels we consider interesting (ie., are part of some input_mapping). std::set interesting_channels; + bool silenced = false; }; const AudioDevice *find_audio_device(DeviceSpec device_spec) const -- 2.39.2