From 55e8a6a963abce921343fdbb7d01fee7cfd1741f Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 16 Jul 2023 18:57:50 +0200 Subject: Add support for non-percussive instruments, responding to note-off events. --- src/DGDOM.h | 1 + src/audioinputenginemidi.cc | 3 +- src/dgxmlparser.cc | 2 ++ src/domloader.cc | 1 + src/engineevent.h | 1 + src/inputprocessor.cc | 76 +++++++++++++++++++++++++++++++++++++++++++-- src/inputprocessor.h | 1 + src/instrument.cc | 5 +++ src/instrument.h | 2 ++ 9 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/DGDOM.h b/src/DGDOM.h index 474b29c..be8f463 100644 --- a/src/DGDOM.h +++ b/src/DGDOM.h @@ -74,6 +74,7 @@ struct InstrumentDOM std::string name; std::string version; std::string description; + std::string percussive; std::vector samples; std::vector instrument_channels; diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index 69aeeb6..dd05fcb 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -123,7 +123,8 @@ void AudioInputEngineMidi::processNote(const std::uint8_t* midi_buffer, switch(midi_buffer[0] & NoteMask) { case NoteOff: - // Ignore for now + events.push_back({EventType::Release, (std::size_t)instrument_idx, + offset, .0f}); break; case NoteOn: diff --git a/src/dgxmlparser.cc b/src/dgxmlparser.cc index 0d3cdcd..c8bfcae 100644 --- a/src/dgxmlparser.cc +++ b/src/dgxmlparser.cc @@ -333,6 +333,8 @@ bool parseInstrumentFile(const std::string& filename, InstrumentDOM& dom, LogFun dom.version = "1.0"; res &= attrcpy(dom.version, instrument, "version", logger, filename, true); res &= attrcpy(dom.description, instrument, "description", logger, filename, true); + dom.percussive = "true"; + res &= attrcpy(dom.percussive, instrument, "percussive", logger, filename, true); pugi::xml_node channels = instrument.child("channels"); for(pugi::xml_node channel : channels.children("channel")) diff --git a/src/domloader.cc b/src/domloader.cc index c78ed75..90dac5f 100644 --- a/src/domloader.cc +++ b/src/domloader.cc @@ -94,6 +94,7 @@ bool DOMLoader::loadDom(const std::string& basepath, instrument->_name = instrumentdom.name; instrument->version = instrumentdom.version; instrument->_description = instrumentdom.description; + instrument->_percussive = instrumentdom.percussive == "true"; auto path = getPath(basepath + "/" + instrumentref.file); for(const auto& sampledom : instrumentdom.samples) diff --git a/src/engineevent.h b/src/engineevent.h index 9c60a4a..508f679 100644 --- a/src/engineevent.h +++ b/src/engineevent.h @@ -32,6 +32,7 @@ enum class EventType { OnSet, + Release, Choke, Stop, }; diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index c0c0e92..bcfd45a 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -110,6 +110,14 @@ bool InputProcessor::process(std::vector& events, } } + if(event.type == EventType::Release) + { + if(!processRelease(event, pos, resample_ratio)) + { + continue; + } + } + if(event.type == EventType::Choke) { if(!processChoke(event, pos, resample_ratio)) @@ -185,7 +193,7 @@ void InputProcessor::applyDirectedChoke(Settings& settings, DrumKit& kit, { for(const auto& choke : instr.getChokes()) { - // Add event to ramp down all existing events with the same groupname. + // Add event to ramp down all existing events in the directed-choke list. for(const auto& ch : kit.channels) { if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine @@ -305,6 +313,68 @@ bool InputProcessor::processOnset(event_t& event, std::size_t pos, return true; } +bool InputProcessor::processRelease(event_t& event, + std::size_t pos, + double resample_ratio) +{ + if(!kit.isValid()) + { + return false; + } + + std::size_t instrument_id = event.instrument; + Instrument* instr = nullptr; + + if(instrument_id < kit.instruments.size()) + { + instr = kit.instruments[instrument_id].get(); + } + + if(instr == nullptr || !instr->isValid()) + { + ERR(inputprocessor, "Missing Instrument %d.\n", (int)instrument_id); + return false; + } + + if(instr->getPercussive()) + { + // Instrument is percussive, so release/note-off is ignored. + return false; + } + + for(auto& filter : filters) + { + // This line might change the 'event' variable + bool keep = filter->filter(event, event.offset + pos); + + if(!keep) + { + return false; // Skip event completely + } + } + + // Add event to ramp down all existing events with the same instrument id. + for(const auto& ch : kit.channels) + { + if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine + { + continue; + } + + for(auto& event_sample : events_ds.iterateOver(ch.num)) + { + if(event_sample.instrument_id == instrument_id && + event_sample.rampdown_count == -1) // Only if not already ramping. + { + // Fixed note-off rampdown time of 100ms, independent of samplerate + applyChoke(settings, event_sample, 100, event.offset, pos); + } + } + } + + return true; +} + bool InputProcessor::processChoke(event_t& event, std::size_t pos, double resample_ratio) @@ -339,7 +409,7 @@ bool InputProcessor::processChoke(event_t& event, } } - // Add event to ramp down all existing events with the same groupname. + // Add event to ramp down all existing events with the same instrument id. for(const auto& ch : kit.channels) { if(ch.num >= NUM_CHANNELS) // kit may have more channels than the engine @@ -352,7 +422,7 @@ bool InputProcessor::processChoke(event_t& event, if(event_sample.instrument_id == instrument_id && event_sample.rampdown_count == -1) // Only if not already ramping. { - // Fixed group rampdown time of 68ms, independent of samplerate + // Fixed group rampdown time of 450ms, independent of samplerate applyChoke(settings, event_sample, 450, event.offset, pos); } } diff --git a/src/inputprocessor.h b/src/inputprocessor.h index a8dc45b..1ae3fb7 100644 --- a/src/inputprocessor.h +++ b/src/inputprocessor.h @@ -61,6 +61,7 @@ private: bool is_stopping{false}; ///< Is set to true when a EventType::Stop event has been seen. bool processOnset(event_t& event, std::size_t pos, double resample_ratio); + bool processRelease(event_t& event, std::size_t pos, double resample_ratio); bool processChoke(event_t& event, std::size_t pos, double resample_ratio); bool processStop(event_t& event); diff --git a/src/instrument.cc b/src/instrument.cc index b7bcdd9..59537ea 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -115,6 +115,11 @@ const std::string& Instrument::getGroup() const return _group; } +bool Instrument::getPercussive() const +{ + return _percussive; +} + void Instrument::setGroup(const std::string& g) { _group = g; diff --git a/src/instrument.h b/src/instrument.h index c06ccdc..2520ce5 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -55,6 +55,7 @@ public: const std::string& getName() const; const std::string& getDescription() const; const std::string& getGroup() const; + bool getPercussive() const; void setGroup(const std::string& group); @@ -85,6 +86,7 @@ private: std::string _group; std::string _name; std::string _description; + bool _percussive{true}; VersionStr version; -- cgit v1.2.3