Make audio channel a separate class
This commit is contained in:
parent
cab34558ce
commit
26b44a9fa3
4 changed files with 81 additions and 56 deletions
|
|
@ -5,6 +5,8 @@
|
|||
#include <psemek/audio/wave/square.hpp>
|
||||
#include <psemek/audio/wave/triangle.hpp>
|
||||
#include <psemek/audio/effect/volume.hpp>
|
||||
#include <psemek/audio/effect/fade_in.hpp>
|
||||
#include <psemek/audio/effect/fade_out.hpp>
|
||||
#include <psemek/audio/duplicate.hpp>
|
||||
#include <psemek/audio/stereo.hpp>
|
||||
#include <psemek/audio/mixer.hpp>
|
||||
|
|
@ -19,6 +21,16 @@ using namespace psemek;
|
|||
|
||||
static std::map<SDL_Keycode, int> 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<SDL_Keycode, int> 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<audio::volume_control> left_volume_, right_volume_;
|
||||
std::map<SDL_Keycode, audio::mixer::channel_ptr> channels_;
|
||||
std::map<SDL_Keycode, audio::channel_ptr> channels_;
|
||||
|
||||
util::clock<> clock_;
|
||||
};
|
||||
|
|
|
|||
43
libs/audio/include/psemek/audio/channel.hpp
Normal file
43
libs/audio/include/psemek/audio/channel.hpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/audio/stream.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
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<channel>;
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/audio/stream.hpp>
|
||||
#include <psemek/util/function.hpp>
|
||||
#include <psemek/audio/channel.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -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<stream_ptr(stream_ptr)> modifier) = 0;
|
||||
|
||||
virtual ~channel() {}
|
||||
};
|
||||
|
||||
using channel_ptr = std::shared_ptr<channel>;
|
||||
|
||||
virtual channel_ptr add(stream_ptr stream) = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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<stream_ptr(stream_ptr)> 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<stream_ptr(stream_ptr)> 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<mixer_impl>
|
||||
|
|
@ -48,19 +19,18 @@ namespace psemek::audio
|
|||
std::size_t read(float * data, std::size_t sample_count) override;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<channel_impl>> channels_;
|
||||
std::vector<std::shared_ptr<channel_impl>> alive_channels_;
|
||||
std::vector<channel_ptr> channels_;
|
||||
std::vector<channel_ptr> alive_channels_;
|
||||
|
||||
std::vector<float> buffer_;
|
||||
|
||||
std::mutex new_channels_mutex_;
|
||||
std::vector<std::shared_ptr<channel_impl>> new_channels_;
|
||||
std::vector<channel_ptr> new_channels_;
|
||||
};
|
||||
|
||||
mixer::channel_ptr mixer_impl::add(stream_ptr stream)
|
||||
channel_ptr mixer_impl::add(stream_ptr stream)
|
||||
{
|
||||
auto result = std::make_shared<channel_impl>();
|
||||
result->stream = std::move(stream);
|
||||
auto result = std::make_shared<channel>(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<std::shared_ptr<channel_impl>> new_channels;
|
||||
std::vector<channel_ptr> 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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue