From ac8684faa3d455c8acf052a15925dfd287ec16e0 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Tue, 22 Sep 2020 20:20:48 +0300 Subject: [PATCH] Audio: query actual frequency & channels, initialize effects based on that --- libs/audio/include/psemek/audio/effect.hpp | 2 ++ libs/audio/include/psemek/audio/engine.hpp | 6 ++-- libs/audio/source/echo.cpp | 9 ++++-- libs/audio/source/engine.cpp | 36 +++++++++++++++++++--- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/libs/audio/include/psemek/audio/effect.hpp b/libs/audio/include/psemek/audio/effect.hpp index f4bea74a..b1487490 100644 --- a/libs/audio/include/psemek/audio/effect.hpp +++ b/libs/audio/include/psemek/audio/effect.hpp @@ -11,6 +11,8 @@ namespace psemek::audio { virtual std::string_view name() const = 0; + virtual void init(int frequency, int channels) = 0; + virtual void operator()(std::int16_t * data, std::size_t count) = 0; virtual ~effect() {} diff --git a/libs/audio/include/psemek/audio/engine.hpp b/libs/audio/include/psemek/audio/engine.hpp index 90684acb..ececc7b9 100644 --- a/libs/audio/include/psemek/audio/engine.hpp +++ b/libs/audio/include/psemek/audio/engine.hpp @@ -12,12 +12,12 @@ namespace psemek::audio struct engine { - static const int frequency = 44100; - static const int channels = 2; - engine(); ~engine(); + int frequency() const; + int channels() const; + std::shared_ptr load_raw(std::int16_t const * data, std::size_t sample_count, bool copy = true); std::shared_ptr load(char const * data, std::size_t size); diff --git a/libs/audio/source/echo.cpp b/libs/audio/source/echo.cpp index 0973b114..e50eb80b 100644 --- a/libs/audio/source/echo.cpp +++ b/libs/audio/source/echo.cpp @@ -15,9 +15,13 @@ namespace psemek::audio : audio::effect { echo_impl(float delay, float volume) - : volume_(volume) + : delay_(delay) + , volume_(volume) + {} + + void init(int frequency, int channels) override { - int sample_count = std::round(delay * audio::engine::frequency * audio::engine::channels); + int sample_count = std::round(delay_ * frequency) * channels; samples_.reserve(sample_count); } @@ -55,6 +59,7 @@ namespace psemek::audio private: std::vector samples_; std::size_t pos_ = 0; + float delay_; float volume_; }; diff --git a/libs/audio/source/engine.cpp b/libs/audio/source/engine.cpp index 496fe661..21fe7cee 100644 --- a/libs/audio/source/engine.cpp +++ b/libs/audio/source/engine.cpp @@ -35,6 +35,12 @@ namespace psemek::audio } }; + struct spec_t + { + int frequency = 44100; + int channels = 2; + }; + struct track_impl : track { @@ -69,12 +75,15 @@ namespace psemek::audio std::shared_ptr track; bool loop; + spec_t spec; + std::vector> effects; - stream_impl(int channel, std::shared_ptr track, bool loop) + stream_impl(int channel, std::shared_ptr track, bool loop, spec_t spec) : channel(channel) , track(track) , loop(loop) + , spec(spec) {} void volume(float value) @@ -85,6 +94,7 @@ namespace psemek::audio void push_effect(std::shared_ptr e) override { + e->init(spec.frequency, spec.channels); effects.push_back(e); Mix_RegisterEffect(channel, &effect_func, nullptr, e.get()); } @@ -143,6 +153,8 @@ namespace psemek::audio std::shared_ptr sdl_init; sdl2_mixer_initializer mix_init; + spec_t spec; + struct channel { std::shared_ptr stream; @@ -181,12 +193,18 @@ namespace psemek::audio engine::impl::impl() : sdl_init(sdl2::init(SDL_INIT_AUDIO)) { - if (Mix_OpenAudio(engine::frequency, AUDIO_S16SYS, engine::channels, 4096) != 0) + if (Mix_OpenAudio(spec.frequency, AUDIO_S16SYS, spec.channels, 4096) != 0) mix_fail("Mix_OpenAudio: "); + Uint16 format; + Mix_QuerySpec(&spec.frequency, &format, &spec.channels); + + if (format != AUDIO_S16SYS) + throw std::runtime_error("Failed to initialize audio with int16 samples"); + Mix_ChannelFinished(&channel_finished); - log::info() << "Initialized audio"; + log::info() << "Initialized audio: " << spec.channels << " channels, " << spec.frequency << " Hz"; } engine::impl::~impl() @@ -226,7 +244,7 @@ namespace psemek::audio ch = c; } - auto str = std::make_shared(*ch, std::move(ss), loop); + auto str = std::make_shared(*ch, std::move(ss), loop, spec); channels[*ch].stream = str; @@ -253,6 +271,16 @@ namespace psemek::audio engine::~engine() {} + int engine::frequency() const + { + return impl::instance()->spec.frequency; + } + + int engine::channels() const + { + return impl::instance()->spec.channels; + } + std::shared_ptr engine::load(char const * data, std::size_t size) { return std::make_shared(Mix_LoadWAV_RW(SDL_RWFromConstMem(data, size), 1));