psemek/libs/audio/source/track_raw.cpp

97 lines
2.1 KiB
C++

#include <psemek/audio/track.hpp>
#include <psemek/util/exception.hpp>
#include <atomic>
namespace psemek::audio
{
namespace
{
struct data_holder
{
std::vector<float> storage;
util::span<float const> samples;
data_holder(util::span<float const> samples)
: samples(samples)
{}
data_holder(std::vector<float> storage)
: storage(std::move(storage))
, samples(this->storage)
{}
};
struct raw_stream_impl
: stream
{
raw_stream_impl(std::shared_ptr<data_holder> data_holder)
: data_holder_(std::move(data_holder))
{}
std::optional<std::size_t> length() const override
{
return data_holder_->samples.size();
}
std::size_t read(util::span<float> samples) override
{
auto played = played_.load();
auto count = std::min(data_holder_->samples.size() - played, samples.size());
std::copy(data_holder_->samples.begin() + played, data_holder_->samples.begin() + played + count, samples.begin());
played_.fetch_add(count);
return count;
}
std::size_t played() const override
{
return played_;
}
private:
std::shared_ptr<data_holder> data_holder_;
std::atomic<std::size_t> played_{0};
};
struct raw_track_impl
: track
{
raw_track_impl(std::shared_ptr<data_holder> data_holder)
: data_holder_(std::move(data_holder))
{}
stream_ptr stream() const override
{
return std::make_shared<raw_stream_impl>(data_holder_);
}
std::optional<std::size_t> length() const override
{
return data_holder_->samples.size();
}
private:
std::shared_ptr<data_holder> data_holder_;
};
}
track_ptr load_raw(util::span<float const> samples)
{
if ((samples.size() % 2) != 0)
throw util::exception("Sample count must be even");
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(samples));
}
track_ptr load_raw(std::vector<float> samples)
{
if ((samples.size() % 2) != 0)
throw util::exception("Sample count must be even");
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(std::move(samples)));
}
}