75 lines
1.5 KiB
C++
75 lines
1.5 KiB
C++
#include <psemek/audio/effect/fade_out.hpp>
|
|
#include <psemek/audio/constants.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
namespace psemek::audio
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
struct fade_out_impl
|
|
: stream
|
|
{
|
|
fade_out_impl(stream_ptr stream, duration length, duration start)
|
|
: stream_(std::move(stream))
|
|
, length_(length)
|
|
, start_(start)
|
|
, total_length_(stream_->played() + start_.samples() + length_.samples())
|
|
{}
|
|
|
|
std::optional<std::size_t> length() const override
|
|
{
|
|
return total_length_;
|
|
}
|
|
|
|
std::size_t played() const override
|
|
{
|
|
return stream_->played();
|
|
}
|
|
|
|
std::size_t read(util::span<float> samples) override
|
|
{
|
|
if (current_ >= length_.samples())
|
|
return 0;
|
|
|
|
auto result = stream_->read(samples);
|
|
|
|
if (result <= start_.samples())
|
|
{
|
|
start_ -= duration::from_samples(result);
|
|
}
|
|
else
|
|
{
|
|
for (std::size_t i = start_.samples(); i < result; i += 2)
|
|
{
|
|
float m = static_cast<float>(length_.samples() - std::min<std::size_t>(current_, length_.samples())) / length_.samples();
|
|
|
|
samples[i + 0] *= m;
|
|
samples[i + 1] *= m;
|
|
|
|
current_ += 2;
|
|
}
|
|
start_ = {};
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private:
|
|
stream_ptr stream_;
|
|
duration length_;
|
|
duration start_;
|
|
std::size_t current_ = 0;
|
|
std::size_t total_length_ = 0;
|
|
};
|
|
|
|
}
|
|
|
|
stream_ptr fade_out(stream_ptr stream, duration length, duration start)
|
|
{
|
|
return std::make_shared<fade_out_impl>(std::move(stream), length, start);
|
|
}
|
|
|
|
}
|