diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2017-10-14 15:24:36 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2018-02-18 11:43:40 +0100 |
commit | 0dc69ba161bb0c8fce2eb0ab3c5eb897f7aa92a7 (patch) | |
tree | d33fcf6f429124cd551177e3d28aa3ac7bc29272 | |
parent | 3515fe8b970bd7cd849ea44e24bc01331e894314 (diff) |
Implemented engine part of the latency filter aka. humized timing.
-rw-r--r-- | src/drumgizmo.cc | 2 | ||||
-rw-r--r-- | src/events.h | 2 | ||||
-rw-r--r-- | src/inputprocessor.cc | 5 | ||||
-rw-r--r-- | src/inputprocessor.h | 4 | ||||
-rw-r--r-- | src/latencyfilter.cc | 63 | ||||
-rw-r--r-- | src/latencyfilter.h | 10 | ||||
-rw-r--r-- | src/settings.h | 23 |
7 files changed, 95 insertions, 14 deletions
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 9874bbe..d30952e 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -47,7 +47,7 @@ DrumGizmo::DrumGizmo(Settings& settings, , oe(o) , ie(i) , audio_cache(settings) - , input_processor(settings, kit, activeevents) + , input_processor(settings, kit, activeevents, rand) , settings(settings) , settings_getter(settings) { diff --git a/src/events.h b/src/events.h index 30a9e8b..f953031 100644 --- a/src/events.h +++ b/src/events.h @@ -54,7 +54,7 @@ public: virtual type_t getType() const = 0; channel_t channel; - timepos_t offset; + timepos_t offset; //< Global position (ie. not relative to buffer) }; #define NO_RAMPDOWN -1 diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index 5d96e2d..1dbd79e 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -39,14 +39,15 @@ InputProcessor::InputProcessor(Settings& settings, DrumKit& kit, - std::list<Event*>* activeevents) + std::list<Event*>* activeevents, + Random& random) : kit(kit) , activeevents(activeevents) , is_stopping(false) { // Build filter list filters.emplace_back(std::make_unique<StaminaFilter>(settings)); - filters.emplace_back(std::make_unique<LatencyFilter>(settings)); + filters.emplace_back(std::make_unique<LatencyFilter>(settings, random)); } bool InputProcessor::process(std::vector<event_t>& events, diff --git a/src/inputprocessor.h b/src/inputprocessor.h index fe72292..cf62ea2 100644 --- a/src/inputprocessor.h +++ b/src/inputprocessor.h @@ -37,13 +37,15 @@ #include "inputfilter.h" struct Settings; +class Random; class InputProcessor { public: InputProcessor(Settings& settings, DrumKit& kit, - std::list<Event*>* activeevents); + std::list<Event*>* activeevents, + Random& random); bool process(std::vector<event_t>& events, std::size_t pos, diff --git a/src/latencyfilter.cc b/src/latencyfilter.cc index d83eab6..2f4bfe5 100644 --- a/src/latencyfilter.cc +++ b/src/latencyfilter.cc @@ -26,19 +26,70 @@ */ #include "latencyfilter.h" -LatencyFilter::LatencyFilter(Settings& settings) - //: settings(settings) +#include <cmath> +#include <hugin.hpp> + +#include "settings.h" +#include "random.h" + +LatencyFilter::LatencyFilter(Settings& settings, Random& random) + : settings(settings) + , random(random) { } -bool LatencyFilter::filter(event_t& events, size_t pos) +bool LatencyFilter::filter(event_t& event, std::size_t pos) { + auto enabled = settings.enable_latency_modifier.load(); + auto latency = settings.latency_max.load(); + auto samplerate = settings.samplerate.load(); + auto latency_laid_back = settings.latency_laid_back.load(); + auto latency_stddev = settings.latency_stddev.load(); + auto latency_regain = settings.latency_regain.load(); + + if(!enabled) + { + return true; + } + + // Assert latency_regain is within range [0; 1]. + assert(latency_regain >= 0.0f && latency_regain <= 1.0f); + + float duration = (pos - latency_last_pos) / samplerate; + latency_offset *= pow(latency_regain, duration); + + latency_last_pos = pos; + + float offset_min = latency * -1.0f; + float offset_max = latency * 1.0f; + + float mean = latency_laid_back; + float stddev = latency_stddev; + + float offset = random.normalDistribution(mean, stddev); + + latency_offset += offset; + + if(latency_offset > offset_max) latency_offset = offset_max; + if(latency_offset < offset_min) latency_offset = offset_min; + + DEBUG(offset, "latency: %d, offset: %f, drift: %f", + (int)latency, offset, latency_offset); + + event.offset += latency; + event.offset += latency_offset;//(int)std::round(offset); + return true; } std::size_t LatencyFilter::getLatency() const { - // TODO: If enabled in settings, return the maximum number of samples - // with which the latency filter can move notes forward. - return 0; + bool enabled = settings.enable_latency_modifier.load(); + std::size_t max_latency = settings.latency_max.load(); + if(enabled) + { + return max_latency; + } + + return 0u; } diff --git a/src/latencyfilter.h b/src/latencyfilter.h index e34b050..a49dd47 100644 --- a/src/latencyfilter.h +++ b/src/latencyfilter.h @@ -29,17 +29,21 @@ #include "inputfilter.h" struct Settings; +class Random; class LatencyFilter : public InputFilter { public: - LatencyFilter(Settings& settings); + LatencyFilter(Settings& settings, Random& random); - bool filter(event_t& events, size_t pos) override; + bool filter(event_t& events, std::size_t pos) override; std::size_t getLatency() const override; private: - //Settings& settings; + Settings& settings; + Random& random; + double latency_offset{0.0}; + std::size_t latency_last_pos{0}; }; diff --git a/src/settings.h b/src/settings.h index 6bba237..cdce066 100644 --- a/src/settings.h +++ b/src/settings.h @@ -90,6 +90,29 @@ struct Settings Atomic<bool> enable_bleed_control{false}; Atomic<float> master_bleed{1.0f}; + + Atomic<bool> enable_latency_modifier{true}; + + //! Maximum "early hits" introduces latency. In no. samples. + Atomic<std::size_t> latency_max{5000u}; + + //! 0 := on-beat + //! positive := laid back + //! negative := up-beat + Atomic<int> latency_laid_back{0}; + + //! 0 := Robot + //! 100 := Good drummer + //! 200 := Decent drummer + //! 300 := Decent drummer on a bad day + //! 400 := Bad drummer + //! 500 := Bad and drunk drummer + Atomic<float> latency_stddev{100.0f}; + + //! Regain on-beat position. + //! 0: instantaniously + //! 1: never + Atomic<float> latency_regain{0.9f}; }; //! Settings getter class. |