psemek/libs/audio/source/echo.cpp

73 lines
1.4 KiB
C++

#include <psemek/audio/echo.hpp>
#include <psemek/audio/engine.hpp>
#include <psemek/audio/utils.hpp>
#include <cmath>
#include <vector>
namespace psemek::audio
{
namespace
{
struct echo_impl
: audio::effect
{
echo_impl(float delay, float volume)
: delay_(delay)
, volume_(volume)
{}
void init(int frequency, int channels) override
{
int sample_count = std::round(delay_ * frequency) * channels;
samples_.reserve(sample_count);
}
std::string_view name() const override
{
return "echo";
}
void operator()(std::int16_t * data, std::size_t size) override
{
if (samples_.size() < samples_.capacity())
{
auto count = std::min(samples_.capacity() - samples_.size(), size);
std::copy(data, data + count, std::back_inserter(samples_));
pos_ += count;
data += count;
size -= count;
if (pos_ == samples_.capacity())
pos_ = 0;
}
for (; size > 0; ++data, --size)
{
float s = clamp((*data) + samples_[pos_] * volume_);
samples_[pos_] = *data;
*data = s;
++pos_;
if (pos_ == samples_.capacity())
pos_ = 0;
}
}
private:
std::vector<std::int16_t> samples_;
std::size_t pos_ = 0;
float delay_;
float volume_;
};
}
std::shared_ptr<effect> echo(float delay, float volume)
{
return std::make_shared<echo_impl>(delay, volume);
}
}