#include #include #include #include namespace psemek::audio { volume_base::volume_base(float gain_left, float gain_right, float smoothness) : gain_{gain_left, gain_right} , smoothness_multiplier_{smoothness_to_multiplier(smoothness)} , real_gain_{gain_left, gain_right} , last_sample_src_{0.f, 0.f} , last_sample_tgt_{0.f, 0.f} {} float volume_base::smoothness() const { return multiplier_to_smoothness(smoothness_multiplier_.load()); } float volume_base::smoothness(float value) { auto old = smoothness_multiplier_.exchange(smoothness_to_multiplier(value)); return multiplier_to_smoothness(old); } void volume_base::apply(float * data, std::size_t sample_count) { float gain[2] = {gain_[0].load(), gain_[1].load()}; float smoothness_multiplier = smoothness_multiplier_.load(); auto apply_impl = [this](float & target, int i) { auto old = target; target = last_sample_tgt_[i] + (old - last_sample_src_[i]) * real_gain_[i]; last_sample_src_[i] = old; last_sample_tgt_[i] = target; }; auto end = data + sample_count; for (auto p = data; p < end;) { apply_impl(*p++, 0); apply_impl(*p++, 1); smooth_update(real_gain_[0], gain[0], smoothness_multiplier); smooth_update(real_gain_[1], gain[1], smoothness_multiplier); } } }