#include #include #include #include namespace psemek::audio { namespace { struct mono_effect_impl : listener_3d_mono::mono_effect { mono_effect_impl(geom::point const & source_position, geom::point & target_position, std::mutex & target_position_mutex, float distance_factor) : source_position_(source_position) , target_position_(target_position) , cached_target_position_(target_position) , target_position_mutex_(target_position_mutex) , distance_factor_(distance_factor) {} std::string_view name() const override { return "mono_3d"; } void init(int, int) override { } void operator()(sample * data, std::size_t count) override { { std::unique_lock lock{target_position_mutex_, std::try_to_lock}; if (lock.owns_lock()) cached_target_position_ = target_position_; } { std::unique_lock lock{source_position_mutex_, std::try_to_lock}; if (lock.owns_lock()) cached_source_position_ = source_position_; } float distance = geom::distance(cached_target_position_, cached_source_position_) / distance_factor_; float factor = std::min(1.f, 1.f / (1.f + distance * distance)); for (std::size_t i = 0; i < count; ++i) data[i] = pack(unpack(data[i]) * factor); } void set_position(geom::point const & position) override { std::lock_guard lock{source_position_mutex_}; source_position_ = position; } private: std::mutex source_position_mutex_; geom::point source_position_; geom::point cached_source_position_; geom::point & target_position_; geom::point cached_target_position_; std::mutex & target_position_mutex_; float distance_factor_; }; } void listener_3d_mono::set_position(geom::point const & position) { std::lock_guard lock{position_mutex_}; position_ = position; } std::shared_ptr listener_3d_mono::make_effect(const geom::point &position, float distance_factor) { return std::make_shared(position, position_, position_mutex_, distance_factor); } }