96 lines
2 KiB
C++
96 lines
2 KiB
C++
#include <psemek/audio/track.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 std::runtime_error("bad sample count");
|
|
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 std::runtime_error("bad sample count");
|
|
return std::make_shared<raw_track_impl>(std::make_shared<data_holder>(std::move(samples)));
|
|
}
|
|
|
|
}
|