Implement audio pause control
This commit is contained in:
parent
81fabbbf02
commit
227236568b
3 changed files with 127 additions and 2 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
#include <psemek/audio/effect/fade_in.hpp>
|
#include <psemek/audio/effect/fade_in.hpp>
|
||||||
#include <psemek/audio/effect/fade_out.hpp>
|
#include <psemek/audio/effect/fade_out.hpp>
|
||||||
#include <psemek/audio/effect/compressor.hpp>
|
#include <psemek/audio/effect/compressor.hpp>
|
||||||
|
#include <psemek/audio/effect/pause.hpp>
|
||||||
#include <psemek/audio/duplicate.hpp>
|
#include <psemek/audio/duplicate.hpp>
|
||||||
#include <psemek/audio/stereo.hpp>
|
#include <psemek/audio/stereo.hpp>
|
||||||
#include <psemek/audio/mixer.hpp>
|
#include <psemek/audio/mixer.hpp>
|
||||||
|
|
@ -69,7 +70,9 @@ struct audio_app
|
||||||
{
|
{
|
||||||
mixer_ = audio::make_mixer();
|
mixer_ = audio::make_mixer();
|
||||||
volume_control_ = audio::volume_stereo(mixer_, 0.5f, 0.5f, 0.1f);
|
volume_control_ = audio::volume_stereo(mixer_, 0.5f, 0.5f, 0.1f);
|
||||||
engine_.output()->stream(audio::compressor(volume_control_, audio::from_db(-2.f), 0.95f, 0.002f, 1.f, audio::from_db(1.f)));
|
auto compressor = audio::compressor(volume_control_, audio::from_db(-2.f), 0.95f, 0.002f, 1.f, audio::from_db(1.f));
|
||||||
|
pause_control_ = audio::pause(compressor, false, 0.01f);
|
||||||
|
engine_.output()->stream(pause_control_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_key_down(SDL_Keycode key) override
|
void on_key_down(SDL_Keycode key) override
|
||||||
|
|
@ -80,7 +83,12 @@ struct audio_app
|
||||||
{
|
{
|
||||||
int midi = key_to_midi.at(key);
|
int midi = key_to_midi.at(key);
|
||||||
auto tone = audio::sine_wave(440.f * std::pow(2.f, (midi - 69) / 12.f));
|
auto tone = audio::sine_wave(440.f * std::pow(2.f, (midi - 69) / 12.f));
|
||||||
channels_[key] = mixer_->add(audio::fade_in(tone, 0.01f));
|
channels_[key] = mixer_->add(audio::fade_in(tone, 0.002f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == SDLK_SPACE)
|
||||||
|
{
|
||||||
|
pause_control_->paused(!pause_control_->paused());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,6 +139,7 @@ private:
|
||||||
audio::engine engine_;
|
audio::engine engine_;
|
||||||
audio::mixer_ptr mixer_;
|
audio::mixer_ptr mixer_;
|
||||||
std::shared_ptr<audio::volume_control_stereo> volume_control_;
|
std::shared_ptr<audio::volume_control_stereo> volume_control_;
|
||||||
|
std::shared_ptr<audio::pause_control> pause_control_;
|
||||||
std::map<SDL_Keycode, audio::channel_ptr> channels_;
|
std::map<SDL_Keycode, audio::channel_ptr> channels_;
|
||||||
|
|
||||||
util::clock<> clock_;
|
util::clock<> clock_;
|
||||||
|
|
|
||||||
21
libs/audio/include/psemek/audio/effect/pause.hpp
Normal file
21
libs/audio/include/psemek/audio/effect/pause.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/audio/stream.hpp>
|
||||||
|
#include <psemek/audio/duration.hpp>
|
||||||
|
|
||||||
|
namespace psemek::audio
|
||||||
|
{
|
||||||
|
|
||||||
|
struct pause_control
|
||||||
|
: stream
|
||||||
|
{
|
||||||
|
virtual bool paused() const = 0;
|
||||||
|
virtual bool paused(bool value) = 0;
|
||||||
|
|
||||||
|
virtual void pause() { paused(true); }
|
||||||
|
virtual void resume() { paused(false); }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<pause_control> pause(stream_ptr stream, bool paused = false, duration length = 0.01f);
|
||||||
|
|
||||||
|
}
|
||||||
95
libs/audio/source/effect/pause.cpp
Normal file
95
libs/audio/source/effect/pause.cpp
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include <psemek/audio/effect/pause.hpp>
|
||||||
|
#include <psemek/audio/smooth.hpp>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace psemek::audio
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct pause_control_impl
|
||||||
|
: pause_control
|
||||||
|
{
|
||||||
|
pause_control_impl(stream_ptr stream, bool paused, duration length)
|
||||||
|
: stream_(std::move(stream))
|
||||||
|
, paused_{paused}
|
||||||
|
, length_(length)
|
||||||
|
, level_(paused ? 0 : length_.samples())
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool paused() const override
|
||||||
|
{
|
||||||
|
return paused_.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool paused(bool value) override
|
||||||
|
{
|
||||||
|
return paused_.exchange(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::size_t> length() const override
|
||||||
|
{
|
||||||
|
return stream_->length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t read(float * data, std::size_t sample_count) override
|
||||||
|
{
|
||||||
|
bool const paused = paused_.load();
|
||||||
|
|
||||||
|
if (paused)
|
||||||
|
{
|
||||||
|
auto result = stream_->read(data, std::min(sample_count, level_));
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < result; i += 2)
|
||||||
|
{
|
||||||
|
float gain = static_cast<float>(level_) / length_.samples();
|
||||||
|
data[i + 0] *= gain;
|
||||||
|
data[i + 1] *= gain;
|
||||||
|
level_ -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fill(data + result, data + sample_count, 0.f);
|
||||||
|
return sample_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto result = stream_->read(data, sample_count);
|
||||||
|
|
||||||
|
auto const max_level = static_cast<std::size_t>(length_.samples());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < result; i += 2)
|
||||||
|
{
|
||||||
|
float gain = static_cast<float>(level_) / max_level;
|
||||||
|
data[i + 0] *= gain;
|
||||||
|
data[i + 1] *= gain;
|
||||||
|
|
||||||
|
if (level_ < max_level)
|
||||||
|
level_ += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t played() const override
|
||||||
|
{
|
||||||
|
return stream_->played();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
stream_ptr stream_;
|
||||||
|
std::atomic<bool> paused_;
|
||||||
|
duration length_;
|
||||||
|
std::size_t level_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<pause_control> pause(stream_ptr stream, bool paused, duration length)
|
||||||
|
{
|
||||||
|
return std::make_shared<pause_control_impl>(std::move(stream), paused, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue