diff options
-rw-r--r-- | include/event.h | 23 | ||||
-rw-r--r-- | plugin/Makefile.mingw32.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/Makefile.am.drumgizmo | 2 | ||||
-rw-r--r-- | src/drumgizmo.cc | 6 | ||||
-rw-r--r-- | src/inputfilter.h | 50 | ||||
-rw-r--r-- | src/inputprocessor.cc | 47 | ||||
-rw-r--r-- | src/inputprocessor.h | 20 | ||||
-rw-r--r-- | src/instrument.cc | 44 | ||||
-rw-r--r-- | src/latencyfilter.cc | 44 | ||||
-rw-r--r-- | src/latencyfilter.h | 45 | ||||
-rw-r--r-- | src/staminafilter.cc | 80 | ||||
-rw-r--r-- | src/staminafilter.h | 51 |
13 files changed, 351 insertions, 70 deletions
diff --git a/include/event.h b/include/event.h index f8bced3..afb1db4 100644 --- a/include/event.h +++ b/include/event.h @@ -24,17 +24,20 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_EVENT_H__ -#define __DRUMGIZMO_EVENT_H__ +#pragma once +#include <cstddef> + +// TODO: Make enum class +//! Event types #define TYPE_ONSET 0 #define TYPE_STOP 1 -typedef struct { - size_t type; - size_t instrument; - size_t offset; - float velocity; -} event_t; - -#endif/*__DRUMGIZMO_EVENT_H__*/ +//! POD datatype for input event transport. +struct event_t +{ + std::size_t type; //!< The type of the event. + std::size_t instrument; //!< The instrument number. + std::size_t offset; //!< The offset position in the input buffer + float velocity; //!< The velocity if the type is a note on [0; 1] +}; diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index d218430..7a9d412 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -28,6 +28,7 @@ DG_SRC = \ @top_srcdir@/src/inputprocessor.cc \ @top_srcdir@/src/instrument.cc \ @top_srcdir@/src/instrumentparser.cc \ + @top_srcdir@/src/latencyfilter.cc \ @top_srcdir@/src/memchecker.cc \ @top_srcdir@/src/midimapparser.cc \ @top_srcdir@/src/midimapper.cc \ @@ -38,6 +39,7 @@ DG_SRC = \ @top_srcdir@/src/sample.cc \ @top_srcdir@/src/semaphore.cc \ @top_srcdir@/src/saxparser.cc \ + @top_srcdir@/src/staminafilter.cc \ @top_srcdir@/src/thread.cc \ @top_srcdir@/src/versionstr.cc DG_CFLAGS = -I@top_srcdir@ -I@top_srcdir@/include -I@top_srcdir@/src \ diff --git a/src/Makefile.am b/src/Makefile.am index 4d167af..f149aa5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,6 +22,9 @@ EXTRA_DIST = \ events.h \ instrument.h \ instrumentparser.h \ + inputfiler.h \ + inputprocessor.h \ + latencyfilter.h \ memchecker.h \ midimapparser.h \ midimapper.h \ @@ -34,6 +37,7 @@ EXTRA_DIST = \ sample.h \ saxparser.h \ semaphore.h \ + staminafilter.h \ thread.h \ velocity.h \ versionstr.h \ @@ -59,6 +63,8 @@ EXTRA_DIST = \ events.cc \ instrument.cc \ instrumentparser.cc \ + inputprocessor.cc \ + latencyfilter.cc \ memchecker.cc \ midimapparser.cc \ midimapper.cc \ @@ -68,6 +74,7 @@ EXTRA_DIST = \ sample.cc \ saxparser.cc \ semaphore.cc \ + staminafilter.cc \ thread.cc \ velocity.cc \ versionstr.cc diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index af822f4..9a5b211 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -20,6 +20,7 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/inputprocessor.cc \ $(top_srcdir)/src/instrument.cc \ $(top_srcdir)/src/instrumentparser.cc \ + $(top_srcdir)/src/latencyfilter.cc \ $(top_srcdir)/src/memchecker.cc \ $(top_srcdir)/src/midimapparser.cc \ $(top_srcdir)/src/midimapper.cc \ @@ -30,6 +31,7 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/sample.cc \ $(top_srcdir)/src/semaphore.cc \ $(top_srcdir)/src/saxparser.cc \ + $(top_srcdir)/src/staminafilter.cc \ $(top_srcdir)/src/thread.cc \ $(top_srcdir)/src/versionstr.cc diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index a1278a1..e07b7a1 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -54,7 +54,7 @@ DrumGizmo::DrumGizmo(Settings& settings, , oe(o) , ie(i) , kit() - , input_processor(kit, activeevents) + , input_processor(settings, kit, activeevents) , framesize(0) , freewheel(false) , events{} @@ -162,12 +162,14 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) ie.run(pos, nsamples, events); double resample_ratio = resamplers.getRatio(); - bool active_events_left = input_processor.process(events, pos, resample_ratio); + bool active_events_left = + input_processor.process(events, pos, resample_ratio); if(!active_events_left) { return false; } + events.clear(); // diff --git a/src/inputfilter.h b/src/inputfilter.h new file mode 100644 index 0000000..26f7294 --- /dev/null +++ b/src/inputfilter.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * inputfilter.h + * + * Tue Jun 14 20:42:52 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <event.h> + +//! An abstract filter component for the InputProcessor class filter chain. +class InputFilter +{ +public: + //! Implement to filter a single event. + //! \param[in,out] event The event being processed. The filter method + //! might alter any of the event parameters. + //! \param pos The absolute position of the buffer in which the event in + //! event was received. Add event.pos to it to get the absolute position of + //! the event in the stream. + //! \return true to keep the event, false to discard it. + virtual bool filter(event_t& event, std::size_t pos) = 0; + + //! Returns the filter delay in samples. + //! Overload if needed. + virtual std::size_t getLatency() const + { + return 0; + } +}; diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index b83855f..b59f0e5 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -32,17 +32,28 @@ #include "instrument.h" -InputProcessor::InputProcessor(DrumKit& kit, std::list<Event*>* activeevents) +#include "staminafilter.h" +#include "latencyfilter.h" + +#include "cpp11fix.h" + +InputProcessor::InputProcessor(Settings& settings, + DrumKit& kit, + std::list<Event*>* activeevents) : 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)); } -bool InputProcessor::process(const std::vector<event_t>& events, size_t pos, double resample_ratio) +bool InputProcessor::process(std::vector<event_t>& events, + std::size_t pos, + double resample_ratio) { - for(const auto& event: events) + for(auto& event: events) { if(event.type == TYPE_ONSET) { @@ -63,16 +74,26 @@ bool InputProcessor::process(const std::vector<event_t>& events, size_t pos, dou std::size_t InputProcessor::getLatency() const { - return 0; + std::size_t latency = 0; + + for(const auto& filter : filters) + { + latency += filter->getLatency(); + } + + return latency; } -bool InputProcessor::processOnset(const event_t& event, size_t pos, double resample_ratio) +bool InputProcessor::processOnset(event_t& event, + std::size_t pos, + double resample_ratio) { - if(!kit.isValid()) { + if(!kit.isValid()) + { return false; } - size_t ev_instr = event.instrument; + std::size_t ev_instr = event.instrument; Instrument* instr = nullptr; if(ev_instr < kit.instruments.size()) @@ -109,6 +130,14 @@ bool InputProcessor::processOnset(const event_t& event, size_t pos, double resam } } + for(auto& filter : filters) + { + if(!filter->filter(event, event.offset + pos)) + { + return false; // Skip event completely + } + } + Sample* sample = instr->sample(event.velocity, event.offset + pos); if(sample == nullptr) @@ -136,7 +165,7 @@ bool InputProcessor::processOnset(const event_t& event, size_t pos, double resam return true; } -bool InputProcessor::processStop(const event_t& event) +bool InputProcessor::processStop(event_t& event) { if(event.type == TYPE_STOP) { diff --git a/src/inputprocessor.h b/src/inputprocessor.h index 83a4f5b..13ac4ad 100644 --- a/src/inputprocessor.h +++ b/src/inputprocessor.h @@ -28,17 +28,25 @@ #include <vector> #include <list> +#include <memory> + +#include <event.h> #include "drumkit.h" #include "events.h" -#include <event.h> +#include "inputfilter.h" + +class Settings; class InputProcessor { public: - InputProcessor(DrumKit& kit, std::list<Event*>* activeevents); + InputProcessor(Settings& settings, + DrumKit& kit, + std::list<Event*>* activeevents); - bool process(const std::vector<event_t>& events, size_t pos, + bool process(std::vector<event_t>& events, + std::size_t pos, double resample_ratio); std::size_t getLatency() const; @@ -48,6 +56,8 @@ private: std::list<Event*>* activeevents; bool is_stopping; ///< Is set to true when a TYPE_STOP event has been seen. - bool processOnset(const event_t& event, size_t pos, double resample_ratio); - bool processStop(const event_t& event); + bool processOnset(event_t& event, std::size_t pos, double resample_ratio); + bool processStop(event_t& event); + + std::vector<std::unique_ptr<InputFilter>> filters; }; diff --git a/src/instrument.cc b/src/instrument.cc index 8c78f40..5c96c6d 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -56,46 +56,8 @@ bool Instrument::isValid() const Sample* Instrument::sample(level_t level, size_t pos) { - // Read out all values from settings. - auto enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); - auto velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); - auto samplerate = settings.samplerate.load(); - auto velocity_modifier_falloff = settings.velocity_modifier_falloff.load(); - auto enable_velocity_modifier = settings.enable_velocity_modifier.load(); - auto velocity_modifier_weight = settings.velocity_modifier_weight.load(); - Sample *sample = nullptr; - if(enable_velocity_modifier == false) - { - mod = 1.0; - lastpos = 0; - } - - if(enable_velocity_randomiser) - { - float r = rand.floatInRange(-1.0 * velocity_randomiser_weight, - velocity_randomiser_weight); - level += r; - if(level > 1.0) - { - level = 1.0; - } - if(level < 0.0) - { - level = 0.0; - } - } - - if(enable_velocity_modifier) - { - mod += (pos - lastpos) / (samplerate * velocity_modifier_falloff); - if(mod > 1.0) - { - mod = 1.0; - } - } - if(version >= VersionStr("2.0")) { // Version 2.0 @@ -113,12 +75,6 @@ Sample* Instrument::sample(level_t level, size_t pos) sample = rand.choose(s); } - if(enable_velocity_modifier) - { - lastpos = pos; - mod *= velocity_modifier_weight; - } - return sample; } diff --git a/src/latencyfilter.cc b/src/latencyfilter.cc new file mode 100644 index 0000000..b3ef44d --- /dev/null +++ b/src/latencyfilter.cc @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * latencyfilter.cc + * + * Fri Jun 10 22:42:53 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "latencyfilter.h" + +LatencyFilter::LatencyFilter(Settings& settings) + : settings(settings) +{ +} + +bool LatencyFilter::filter(event_t& events, size_t pos) +{ + 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; +} diff --git a/src/latencyfilter.h b/src/latencyfilter.h new file mode 100644 index 0000000..9b7bdd1 --- /dev/null +++ b/src/latencyfilter.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * latencyfilter.h + * + * Fri Jun 10 22:42:52 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include "inputfilter.h" + +class Settings; + +class LatencyFilter + : public InputFilter +{ +public: + LatencyFilter(Settings& settings); + + bool filter(event_t& events, size_t pos) override; + + std::size_t getLatency() const override; + +private: + Settings& settings; +}; diff --git a/src/staminafilter.cc b/src/staminafilter.cc new file mode 100644 index 0000000..a8f6a86 --- /dev/null +++ b/src/staminafilter.cc @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * staminafilter.cc + * + * Sat Jun 11 08:49:36 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "staminafilter.h" + +#include "settings.h" + +StaminaFilter::StaminaFilter(Settings& settings) + : settings(settings) +{ +} + +bool StaminaFilter::filter(event_t& event, size_t pos) +{ + // Read out all values from settings. + auto samplerate = settings.samplerate.load(); + auto velocity_modifier_falloff = settings.velocity_modifier_falloff.load(); + auto enable_velocity_modifier = settings.enable_velocity_modifier.load(); + auto velocity_modifier_weight = settings.velocity_modifier_weight.load(); + + if(modifiers.find(event.instrument) == modifiers.end()) + { + // On first lookup make sure we have sane values. + auto& pair = modifiers[event.instrument]; + pair.first = 1.0f; + pair.second = 0; + } + + auto& pair = modifiers[event.instrument]; + auto& mod = pair.first; + auto& lastpos = pair.second; + + if(enable_velocity_modifier == false) + { + mod = 1.0f; + lastpos = 0; + } + + if(enable_velocity_modifier) + { + mod += (pos - lastpos) / (samplerate * velocity_modifier_falloff); + if(mod > 1.0f) + { + mod = 1.0f; + } + } + + event.velocity *= mod; + + if(enable_velocity_modifier) + { + lastpos = pos; + mod *= velocity_modifier_weight; + } + + return true; +} diff --git a/src/staminafilter.h b/src/staminafilter.h new file mode 100644 index 0000000..36ee5f1 --- /dev/null +++ b/src/staminafilter.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * staminafilter.h + * + * Sat Jun 11 08:49:36 CEST 2016 + * Copyright 2016 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include <cstddef> +#include <map> +#include <utility> + +#include "inputfilter.h" + +class Settings; + +class StaminaFilter + : public InputFilter +{ +public: + StaminaFilter(Settings& settings); + + bool filter(event_t& event, std::size_t pos) override; + + // Note getLatency not overloaded because this filter doesn't add latency. + +private: + Settings& settings; + + std::map<std::size_t, std::pair<float, std::size_t>> modifiers; +}; |