Implement loading raw audio tracks

This commit is contained in:
Nikita Lisitsa 2022-10-07 23:02:52 +03:00
parent 227236568b
commit f617f50930
2 changed files with 80 additions and 9 deletions

View file

@ -7,6 +7,8 @@
#include <psemek/util/pimpl.hpp> #include <psemek/util/pimpl.hpp>
#include <psemek/util/span.hpp> #include <psemek/util/span.hpp>
#include <psemek/io/stream.hpp>
#include <memory> #include <memory>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
@ -19,8 +21,8 @@ namespace psemek::audio
engine(); engine();
~engine(); ~engine();
track_ptr load(float const * data, std::size_t sample_count, bool copy = true); track_ptr load_raw(float const * data, std::size_t sample_count, bool copy = true);
track_ptr load(util::span<float> data, bool copy = true); track_ptr load_raw(util::span<float const> data, bool copy = true);
channel_ptr output(); channel_ptr output();

View file

@ -15,6 +15,70 @@
namespace psemek::audio namespace psemek::audio
{ {
namespace
{
struct track_data
{
util::span<float const> samples;
std::vector<float> storage;
};
struct track_stream_impl
: stream
{
track_stream_impl(std::shared_ptr<track_data> data)
: data_(std::move(data))
{}
std::optional<std::size_t> length() const override
{
return data_->samples.size();
}
std::size_t read(float * data, std::size_t sample_count) override
{
auto played = played_.load();
std::size_t result = std::min(sample_count, data_->samples.size() - played);
std::copy(data_->samples.data() + played, data_->samples.data() + played + result, data);
played_.fetch_add(result);
return result;
}
std::size_t played() const override
{
return played_.load();
}
private:
std::shared_ptr<track_data> data_;
std::atomic<std::size_t> played_{0};
};
struct track_impl
: track
{
track_impl(std::shared_ptr<track_data> data)
: data_(std::move(data))
{}
stream_ptr stream() const override
{
return std::make_shared<track_stream_impl>(data_);
}
std::size_t length() const override
{
return data_->samples.size();
}
private:
std::shared_ptr<track_data> data_;
};
}
struct engine::impl struct engine::impl
{ {
std::shared_ptr<void> sdl_init; std::shared_ptr<void> sdl_init;
@ -90,21 +154,26 @@ namespace psemek::audio
engine::~engine() = default; engine::~engine() = default;
track_ptr engine::load(float const * data, std::size_t sample_count, bool copy) track_ptr engine::load_raw(float const * data, std::size_t sample_count, bool copy)
{ {
if ((sample_count % 2) != 0) if ((sample_count % 2) != 0)
throw std::runtime_error("bad sample count"); throw std::runtime_error("bad sample count");
(void)data; auto tdata = std::make_shared<track_data>();
(void)sample_count; if (copy)
(void)copy; {
tdata->storage.assign(data, data + sample_count);
tdata->samples = tdata->storage;
}
else
tdata->samples = {data, data + sample_count};
return nullptr; return std::make_shared<track_impl>(std::move(tdata));
} }
track_ptr engine::load(util::span<float> data, bool copy) track_ptr engine::load_raw(util::span<float const> data, bool copy)
{ {
return load(data.data(), data.size(), copy); return load_raw(data.data(), data.size(), copy);
} }
channel_ptr engine::output() channel_ptr engine::output()