@@ -0,0 +1,108 @@
|
||||
#include <vamp_zero/audio.hpp>
|
||||
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <modulus.hpp>
|
||||
#include <sonus.hpp>
|
||||
|
||||
#include <vamp_zero/navigation.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
auto score_active(vamp_zero::app_state const& state) -> std::bool_t {
|
||||
if (state.mode == vamp_zero::app_mode::PERFORMANCE_SCORE) {
|
||||
return vamp_zero::active_part(state) != nullptr;
|
||||
}
|
||||
if (state.mode == vamp_zero::app_mode::PRACTICE_SCORE) {
|
||||
auto const* exercise = vamp_zero::active_practice(state);
|
||||
return exercise != nullptr && vamp_zero::selected_practice_variant(state, *exercise) != nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto log_audio_error(std::string const& action, modulus::error const& error) -> void {
|
||||
modulus::log_error(action + ": " + error.describe());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vamp_zero::audio_controller::audio_controller(vamp_zero::audio_config config, sonus::engine engine)
|
||||
: config_{config}, engine_{std::move(engine)} {}
|
||||
|
||||
vamp_zero::audio_controller::~audio_controller() {
|
||||
auto lock = std::scoped_lock{mutex_};
|
||||
engine_.stop_metronome();
|
||||
engine_.stop_all();
|
||||
engine_.stop();
|
||||
}
|
||||
|
||||
auto vamp_zero::audio_controller::make_metronome_config(vamp_zero::app_state const& state) const -> sonus::metronome_config {
|
||||
auto result = sonus::metronome_config{};
|
||||
result.bpm = state.audio.metronome_bpm;
|
||||
result.beats_per_bar = config_.beats_per_bar;
|
||||
result.volume = config_.metronome_volume;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto vamp_zero::audio_controller::sync(vamp_zero::app_state const& state) -> void {
|
||||
auto lock = std::scoped_lock{mutex_};
|
||||
auto const should_run_metronome = state.audio.metronome_enabled && score_active(state);
|
||||
if (!should_run_metronome) {
|
||||
if (metronome_running_) {
|
||||
engine_.stop_metronome();
|
||||
metronome_running_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto metronome = make_metronome_config(state);
|
||||
if (!metronome_running_) {
|
||||
auto started = engine_.start_metronome(metronome);
|
||||
if (!started) {
|
||||
log_audio_error("failed to start metronome", started.error());
|
||||
engine_.stop_metronome();
|
||||
metronome_running_ = false;
|
||||
return;
|
||||
}
|
||||
metronome_running_ = true;
|
||||
last_metronome_bpm_ = metronome.bpm;
|
||||
return;
|
||||
}
|
||||
|
||||
if (last_metronome_bpm_ != metronome.bpm) {
|
||||
auto updated = engine_.update_metronome(metronome);
|
||||
if (!updated) {
|
||||
log_audio_error("failed to update metronome", updated.error());
|
||||
engine_.stop_metronome();
|
||||
metronome_running_ = false;
|
||||
return;
|
||||
}
|
||||
last_metronome_bpm_ = metronome.bpm;
|
||||
}
|
||||
}
|
||||
|
||||
auto vamp_zero::create_audio_controller(vamp_zero::audio_config const& config) -> std::expected<std::unique_ptr<vamp_zero::audio_controller>, modulus::error> {
|
||||
if (!config.enabled) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto sonus_config = sonus::audio_config{};
|
||||
sonus_config.sample_rate = 48000;
|
||||
sonus_config.channels = 2;
|
||||
sonus_config.master_volume = config.master_volume;
|
||||
|
||||
auto engine = sonus::engine::create(sonus_config);
|
||||
if (!engine) {
|
||||
return std::unexpected(engine.error());
|
||||
}
|
||||
auto started = engine->start();
|
||||
if (!started) {
|
||||
return std::unexpected(started.error());
|
||||
}
|
||||
|
||||
return std::make_unique<vamp_zero::audio_controller>(config, std::move(*engine));
|
||||
}
|
||||
Reference in New Issue
Block a user