psemek/libs/audio/source/3d.cpp

83 lines
2.2 KiB
C++

#include <psemek/audio/3d.hpp>
#include <psemek/util/not_implemented.hpp>
#include <optional>
#include <mutex>
namespace psemek::audio
{
namespace
{
struct mono_effect_impl
: listener_3d_mono::mono_effect
{
mono_effect_impl(geom::point<float, 3> const & source_position, geom::point<float, 3> & 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<float, 3> const & position) override
{
std::lock_guard lock{source_position_mutex_};
source_position_ = position;
}
private:
std::mutex source_position_mutex_;
geom::point<float, 3> source_position_;
geom::point<float, 3> cached_source_position_;
geom::point<float, 3> & target_position_;
geom::point<float, 3> cached_target_position_;
std::mutex & target_position_mutex_;
float distance_factor_;
};
}
void listener_3d_mono::set_position(geom::point<float, 3> const & position)
{
std::lock_guard lock{position_mutex_};
position_ = position;
}
std::shared_ptr<listener_3d_mono::mono_effect> listener_3d_mono::make_effect(const geom::point<float, 3> &position, float distance_factor)
{
return std::make_shared<mono_effect_impl>(position, position_, position_mutex_, distance_factor);
}
}