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_out.hpp>
|
||||
#include <psemek/audio/effect/compressor.hpp>
|
||||
#include <psemek/audio/effect/pause.hpp>
|
||||
#include <psemek/audio/duplicate.hpp>
|
||||
#include <psemek/audio/stereo.hpp>
|
||||
#include <psemek/audio/mixer.hpp>
|
||||
|
|
@ -69,7 +70,9 @@ struct audio_app
|
|||
{
|
||||
mixer_ = audio::make_mixer();
|
||||
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
|
||||
|
|
@ -80,7 +83,12 @@ 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(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::mixer_ptr mixer_;
|
||||
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_;
|
||||
|
||||
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