#include #include #include #include namespace psemek::audio { volume_base::volume_base(float gain, float attack) : gain_{gain} , attack_multiplier_{attack_to_multiplier(attack)} , real_gain_{gain} , last_sample_src_{0.f, 0.f} , last_sample_tgt_{0.f, 0.f} {} float volume_base::attack() const { return multiplier_to_attack(attack_multiplier_.load()); } float volume_base::attack(float value) { auto old = attack_multiplier_.exchange(attack_to_multiplier(value)); return multiplier_to_attack(old); } void volume_base::apply(float * data, std::size_t sample_count) { float gain = gain_.load(); float attack_multiplier = attack_multiplier_.load(); auto apply_impl = [this](float & target, float & last_src, float & last_tgt) { auto old = target; target = last_tgt + (old - last_src) * real_gain_; last_src = old; last_tgt = target; }; auto end = data + sample_count; for (auto p = data; p < end;) { apply_impl(*p++, last_sample_src_[0], last_sample_tgt_[0]); apply_impl(*p++, last_sample_src_[1], last_sample_tgt_[1]); attack_update(real_gain_, gain, attack_multiplier); } } }