From 3255aaf15d8086b406223ec41720215edf7cb89b Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 8 Oct 2022 14:36:24 +0300 Subject: [PATCH] Move loading raw & wav tracks from engine to free functions --- libs/audio/include/psemek/audio/engine.hpp | 3 - libs/audio/include/psemek/audio/track.hpp | 8 ++ libs/audio/source/engine.cpp | 133 --------------------- libs/audio/source/track_raw.cpp | 17 +++ libs/audio/source/track_wav.cpp | 70 +++++++++++ 5 files changed, 95 insertions(+), 136 deletions(-) create mode 100644 libs/audio/source/track_raw.cpp create mode 100644 libs/audio/source/track_wav.cpp diff --git a/libs/audio/include/psemek/audio/engine.hpp b/libs/audio/include/psemek/audio/engine.hpp index e955a0db..b03d0af4 100644 --- a/libs/audio/include/psemek/audio/engine.hpp +++ b/libs/audio/include/psemek/audio/engine.hpp @@ -21,9 +21,6 @@ namespace psemek::audio engine(); ~engine(); - track_ptr load_raw(util::span data, bool copy = true); - track_ptr load_wav(util::span data); - channel_ptr output(); private: diff --git a/libs/audio/include/psemek/audio/track.hpp b/libs/audio/include/psemek/audio/track.hpp index 87b86e36..bcbb4068 100644 --- a/libs/audio/include/psemek/audio/track.hpp +++ b/libs/audio/include/psemek/audio/track.hpp @@ -1,8 +1,10 @@ #pragma once #include +#include #include +#include namespace psemek::audio { @@ -17,4 +19,10 @@ namespace psemek::audio using track_ptr = std::shared_ptr; + track_ptr load_raw(util::span data); + track_ptr load_raw(std::vector data); + + track_ptr load_wav(util::span data); + track_ptr load_wav(std::vector const & data); + } diff --git a/libs/audio/source/engine.cpp b/libs/audio/source/engine.cpp index 64e06808..40d488f6 100644 --- a/libs/audio/source/engine.cpp +++ b/libs/audio/source/engine.cpp @@ -17,105 +17,6 @@ namespace psemek::audio { - namespace - { - - struct track_data - { - util::span samples; - std::vector storage; - }; - - struct track_stream_impl - : stream - { - track_stream_impl(std::shared_ptr data) - : data_(std::move(data)) - {} - - std::optional 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 data_; - std::atomic played_{0}; - }; - - struct track_impl - : track - { - track_impl(std::shared_ptr data) - : data_(std::move(data)) - {} - - stream_ptr stream() const override - { - return std::make_shared(data_); - } - - std::optional length() const override - { - return data_->samples.size(); - } - - private: - std::shared_ptr data_; - }; - - std::vector convert_audio(SDL_AudioSpec const & spec, std::uint8_t * samples, std::size_t length) - { - if (spec.channels > 2) - throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast(spec.channels), " channels")); - - if (spec.freq != 44100) - throw std::runtime_error(util::to_string("Can't convert audio with frequency ", spec.freq)); - - if (spec.format != AUDIO_S16SYS) - throw std::runtime_error(util::to_string("Can't convert audio with format ", spec.format)); - - auto p = reinterpret_cast(samples); - - std::vector result; - - if (spec.channels == 1) - { - result.resize(length); - for (std::size_t i = 0; i < length / 2; ++i) - { - float v = (p[i] * 2.f + 1.f) / 65536.f; - result[2 * i + 0] = v; - result[2 * i + 1] = v; - } - } - else - { - result.resize(length / 2); - for (std::size_t i = 0; i < length / 2; ++i) - result[i] = (p[i] * 2.f + 1.f) / 65536.f; - } - - return result; - } - - } - struct engine::impl { std::shared_ptr sdl_init; @@ -191,40 +92,6 @@ namespace psemek::audio engine::~engine() = default; - track_ptr engine::load_raw(util::span data, bool copy) - { - if ((data.size() % 2) != 0) - throw std::runtime_error("bad sample count"); - - auto tdata = std::make_shared(); - if (copy) - { - tdata->storage.assign(data.begin(), data.end()); - tdata->samples = tdata->storage; - } - else - tdata->samples = data; - - return std::make_shared(std::move(tdata)); - } - - track_ptr engine::load_wav(util::span data) - { - SDL_AudioSpec spec; - std::uint8_t * samples; - std::uint32_t length; - if (!SDL_LoadWAV_RW(SDL_RWFromConstMem(data.data(), data.size()), 1, &spec, &samples, &length)) - sdl2::fail("SDL_LoadWAV_RW failed:"); - - util::at_scope_exit release_samples([samples]{ SDL_FreeWAV(samples); }); - - auto tdata = std::make_shared(); - tdata->storage = convert_audio(spec, samples, length); - tdata->samples = tdata->storage; - - return std::make_shared(std::move(tdata)); - } - channel_ptr engine::output() { return impl().output; diff --git a/libs/audio/source/track_raw.cpp b/libs/audio/source/track_raw.cpp new file mode 100644 index 00000000..eafe3701 --- /dev/null +++ b/libs/audio/source/track_raw.cpp @@ -0,0 +1,17 @@ +#include +#include + +namespace psemek::audio +{ + + track_ptr load_raw(util::span data) + { + return make_duplicator(make_recorder(data)); + } + + track_ptr load_raw(std::vector data) + { + return make_duplicator(make_recorder(std::move(data))); + } + +} diff --git a/libs/audio/source/track_wav.cpp b/libs/audio/source/track_wav.cpp new file mode 100644 index 00000000..5faa10cc --- /dev/null +++ b/libs/audio/source/track_wav.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include + +#include + +namespace psemek::audio +{ + + namespace + { + + std::vector convert_audio(SDL_AudioSpec const & spec, std::uint8_t * samples, std::size_t length) + { + if (spec.channels > 2) + throw std::runtime_error(util::to_string("Can't convert audio with ", static_cast(spec.channels), " channels")); + + if (spec.freq != audio::frequency) + throw std::runtime_error(util::to_string("Can't convert audio with frequency ", spec.freq)); + + if (spec.format != AUDIO_S16SYS) + throw std::runtime_error(util::to_string("Can't convert audio with format ", spec.format)); + + auto p = reinterpret_cast(samples); + + std::vector result; + + if (spec.channels == 1) + { + result.resize(length); + for (std::size_t i = 0; i < length / 2; ++i) + { + float v = (p[i] * 2.f + 1.f) / 65536.f; + result[2 * i + 0] = v; + result[2 * i + 1] = v; + } + } + else + { + result.resize(length / 2); + for (std::size_t i = 0; i < length / 2; ++i) + result[i] = (p[i] * 2.f + 1.f) / 65536.f; + } + + return result; + } + + } + + track_ptr load_wav(util::span data) + { + SDL_AudioSpec spec; + std::uint8_t * samples; + std::uint32_t length; + if (!SDL_LoadWAV_RW(SDL_RWFromConstMem(data.data(), data.size()), 1, &spec, &samples, &length)) + sdl2::fail("SDL_LoadWAV_RW failed:"); + + util::at_scope_exit release_samples([samples]{ SDL_FreeWAV(samples); }); + return make_duplicator(make_recorder(convert_audio(spec, samples, length))); + } + + track_ptr load_wav(std::vector const & data) + { + return load_wav(util::span(data)); + } + +}