68 lines
1.4 KiB
C++
68 lines
1.4 KiB
C++
#include <psemek/audio/effect/all_pass.hpp>
|
||
|
||
#include <vector>
|
||
|
||
namespace psemek::audio
|
||
{
|
||
|
||
namespace
|
||
{
|
||
|
||
struct all_pass_impl
|
||
: stream
|
||
{
|
||
all_pass_impl(stream_ptr stream, duration delay, float gain)
|
||
: stream_(std::move(stream))
|
||
, buffer_(std::max<std::size_t>(2, delay.samples()), 0.f)
|
||
, gain_(gain)
|
||
{}
|
||
|
||
std::optional<std::size_t> length() const override
|
||
{
|
||
return std::nullopt;
|
||
}
|
||
|
||
// y[n] = (−g·x[n]) + x[n−M] + (g·y[n−M])
|
||
std::size_t read(util::span<float> samples) override
|
||
{
|
||
auto count = stream_->read(samples);
|
||
|
||
for (std::size_t i = 0; i < count; ++i)
|
||
{
|
||
float input = samples[i];
|
||
samples[i] = - gain_ * input + buffer_[buffer_pos_];
|
||
buffer_[buffer_pos_] = input + gain_ * samples[i];
|
||
++buffer_pos_;
|
||
buffer_pos_ %= buffer_.size();
|
||
}
|
||
|
||
for (std::size_t i = count; i < samples.size(); ++i)
|
||
{
|
||
samples[i] = buffer_[buffer_pos_];
|
||
buffer_[buffer_pos_] = gain_ * buffer_[buffer_pos_];
|
||
++buffer_pos_;
|
||
buffer_pos_ %= buffer_.size();
|
||
}
|
||
|
||
return samples.size();
|
||
}
|
||
|
||
std::size_t played() const override
|
||
{
|
||
return stream_->played();
|
||
}
|
||
|
||
private:
|
||
stream_ptr stream_;
|
||
std::vector<float> buffer_;
|
||
std::size_t buffer_pos_ = 0;
|
||
float gain_;
|
||
};
|
||
|
||
}
|
||
|
||
stream_ptr all_pass(stream_ptr stream, duration delay, float gain)
|
||
{
|
||
return std::make_shared<all_pass_impl>(std::move(stream), delay, gain);
|
||
}
|
||
}
|