From 26b44a9fa3a79cafe4de03b6a1f19403002b2504 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Wed, 5 Oct 2022 22:39:54 +0300 Subject: [PATCH] Make audio channel a separate class --- examples/audio.cpp | 35 +++++++++++++--- libs/audio/include/psemek/audio/channel.hpp | 43 ++++++++++++++++++++ libs/audio/include/psemek/audio/mixer.hpp | 15 +------ libs/audio/source/mixer.cpp | 44 ++++----------------- 4 files changed, 81 insertions(+), 56 deletions(-) create mode 100644 libs/audio/include/psemek/audio/channel.hpp diff --git a/examples/audio.cpp b/examples/audio.cpp index 708fd7fd..3a821a1f 100644 --- a/examples/audio.cpp +++ b/examples/audio.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,6 +21,16 @@ using namespace psemek; static std::map const key_to_midi { + {SDLK_z, 59}, + {SDLK_x, 60}, + {SDLK_c, 61}, + {SDLK_v, 62}, + {SDLK_b, 63}, + {SDLK_n, 64}, + {SDLK_m, 65}, + {SDLK_COMMA, 66}, + {SDLK_PERIOD, 67}, + {SDLK_SLASH, 68}, {SDLK_a, 69}, {SDLK_s, 70}, {SDLK_d, 71}, @@ -30,6 +42,18 @@ static std::map const key_to_midi {SDLK_l, 77}, {SDLK_SEMICOLON, 78}, {SDLK_QUOTE, 79}, + {SDLK_q, 80}, + {SDLK_w, 81}, + {SDLK_e, 82}, + {SDLK_r, 83}, + {SDLK_t, 84}, + {SDLK_y, 85}, + {SDLK_u, 86}, + {SDLK_i, 87}, + {SDLK_o, 88}, + {SDLK_p, 89}, + {SDLK_LEFTBRACKET, 90}, + {SDLK_RIGHTBRACKET, 91}, }; struct audio_app @@ -41,8 +65,8 @@ struct audio_app mixer_ = audio::make_mixer(); auto [ dup1, dup2 ] = audio::duplicate(mixer_); - left_volume_ = audio::volume(dup1, 0.f, 0.1f); - right_volume_ = audio::volume(dup2, 0.f, 0.1f); + left_volume_ = audio::volume(dup1, 0.5f, 0.1f); + right_volume_ = audio::volume(dup2, 0.5f, 0.1f); auto result = audio::stereo(left_volume_, right_volume_); engine_.output(result); } @@ -55,7 +79,7 @@ struct audio_app { int midi = key_to_midi.at(key); auto tone = audio::sine_wave(440.f * std::pow(2.f, (midi - 69) / 12.f)); - channels_[key] = mixer_->add(tone); + channels_[key] = mixer_->add(audio::fade_in(tone, 0.01f)); } } @@ -65,7 +89,8 @@ struct audio_app if (channels_.contains(key)) { - channels_[key]->stop(); + auto & ch = channels_[key]; + ch->stream(audio::fade_out(ch->stream(), 0.01f)); channels_.erase(key); } } @@ -83,7 +108,7 @@ private: audio::engine engine_; audio::mixer_ptr mixer_; std::shared_ptr left_volume_, right_volume_; - std::map channels_; + std::map channels_; util::clock<> clock_; }; diff --git a/libs/audio/include/psemek/audio/channel.hpp b/libs/audio/include/psemek/audio/channel.hpp new file mode 100644 index 00000000..83d43606 --- /dev/null +++ b/libs/audio/include/psemek/audio/channel.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include +#include + +namespace psemek::audio +{ + + struct channel + { + channel(stream_ptr stream) + : stream_(std::move(stream)) + {} + + stream_ptr stream() const + { + return std::atomic_load(&stream_); + } + + stream_ptr stream(stream_ptr new_stream) + { + return std::atomic_exchange(&stream_, std::move(new_stream)); + } + + stream_ptr stop() + { + return stream(nullptr); + } + + bool is_stopped() const + { + return stream() != nullptr; + } + + private: + stream_ptr stream_; + }; + + using channel_ptr = std::shared_ptr; + +} diff --git a/libs/audio/include/psemek/audio/mixer.hpp b/libs/audio/include/psemek/audio/mixer.hpp index cc464584..0ef8f936 100644 --- a/libs/audio/include/psemek/audio/mixer.hpp +++ b/libs/audio/include/psemek/audio/mixer.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include @@ -11,19 +11,6 @@ namespace psemek::audio struct mixer : stream { - struct channel - { - virtual void stop() = 0; - - virtual bool is_stopped() const = 0; - - virtual void replace(util::function modifier) = 0; - - virtual ~channel() {} - }; - - using channel_ptr = std::shared_ptr; - virtual channel_ptr add(stream_ptr stream) = 0; }; diff --git a/libs/audio/source/mixer.cpp b/libs/audio/source/mixer.cpp index 52720ee8..af4ac4fe 100644 --- a/libs/audio/source/mixer.cpp +++ b/libs/audio/source/mixer.cpp @@ -10,35 +10,6 @@ namespace psemek::audio namespace { - struct channel_impl final - : mixer::channel - { - stream_ptr stream; - - void stop() override; - - bool is_stopped() const override; - - void replace(util::function modifier) override; - }; - - void channel_impl::stop() - { - std::atomic_store(&stream, stream_ptr()); - } - - bool channel_impl::is_stopped() const - { - return std::atomic_load(&stream) != nullptr; - } - - void channel_impl::replace(util::function modifier) - { - stream_ptr stream = std::atomic_load(&(this->stream)); - stream = modifier(std::move(stream)); - std::atomic_store(&(this->stream), std::move(stream)); - } - struct mixer_impl final : mixer , std::enable_shared_from_this @@ -48,19 +19,18 @@ namespace psemek::audio std::size_t read(float * data, std::size_t sample_count) override; private: - std::vector> channels_; - std::vector> alive_channels_; + std::vector channels_; + std::vector alive_channels_; std::vector buffer_; std::mutex new_channels_mutex_; - std::vector> new_channels_; + std::vector new_channels_; }; - mixer::channel_ptr mixer_impl::add(stream_ptr stream) + channel_ptr mixer_impl::add(stream_ptr stream) { - auto result = std::make_shared(); - result->stream = std::move(stream); + auto result = std::make_shared(std::move(stream)); { std::lock_guard lock{new_channels_mutex_}; @@ -73,7 +43,7 @@ namespace psemek::audio std::size_t mixer_impl::read(float * data, std::size_t sample_count) { { - std::vector> new_channels; + std::vector new_channels; { std::lock_guard lock{new_channels_mutex_}; new_channels = std::move(new_channels_); @@ -88,7 +58,7 @@ namespace psemek::audio for (auto & ch : channels_) { - auto stream = std::atomic_load(&(ch->stream)); + auto stream = ch->stream(); if (!stream) continue;