From: Steinar H. Gunderson Date: Sun, 28 Aug 2016 21:18:58 +0000 (+0200) Subject: When the fader is moved, interpolate its volume over the next frame. X-Git-Tag: 1.4.0~70 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=2140fc18714d6e9ac2b0aca51d9b7ff986245c08 When the fader is moved, interpolate its volume over the next frame. Faders are among the things one should definitely be allowed to move around during an actual mix without hearing clicking; the gain and threshold is maybe somewhat less so, so I won't give it the same treatment, at least not right now. --- diff --git a/audio_mixer.cpp b/audio_mixer.cpp index 7810b43..18a669f 100644 --- a/audio_mixer.cpp +++ b/audio_mixer.cpp @@ -462,19 +462,9 @@ vector 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 AudioMixer::get_output(double pts, unsigned num_samples, Resamplin return samples_out; } -void AudioMixer::measure_bus_levels(unsigned bus_index, const vector &left, const vector &right, float volume) +void AudioMixer::add_bus_to_master(unsigned bus_index, const vector &samples_bus, vector *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(last_fader_volume_db[bus_index], -90.0f)); + float volume = from_db(max(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 &left, const vector &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 diff --git a/audio_mixer.h b/audio_mixer.h index 5d65582..29016eb 100644 --- a/audio_mixer.h +++ b/audio_mixer.h @@ -238,7 +238,8 @@ private: void reset_alsa_mutex_held(DeviceSpec device_spec); std::map get_devices_mutex_held() const; void update_meters(const std::vector &samples); - void measure_bus_levels(unsigned bus_index, const std::vector &left, const std::vector &right, float volume); + void add_bus_to_master(unsigned bus_index, const std::vector &samples_bus, std::vector *samples_out); + void measure_bus_levels(unsigned bus_index, const std::vector &left, const std::vector &right); void send_audio_level_callback(); unsigned num_cards; @@ -286,6 +287,7 @@ private: InputMapping input_mapping; // Under audio_mutex. std::atomic fader_volume_db[MAX_BUSES] {{ 0.0f }}; + float last_fader_volume_db[MAX_BUSES] { 0.0f }; // Under audio_mutex. audio_level_callback_t audio_level_callback = nullptr; mutable std::mutex audio_measure_mutex;