summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2023-07-16 18:57:50 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2023-07-17 12:10:05 +0200
commit55e8a6a963abce921343fdbb7d01fee7cfd1741f (patch)
tree5425fe51527927b5430c55ee19064b89c12f6819
parent6c9b69b0471fe72c8793d671f267ead3634ef3ac (diff)
Add support for non-percussive instruments, responding to note-off events.
-rw-r--r--src/DGDOM.h1
-rw-r--r--src/audioinputenginemidi.cc3
-rw-r--r--src/dgxmlparser.cc2
-rw-r--r--src/domloader.cc1
-rw-r--r--src/engineevent.h1
-rw-r--r--src/inputprocessor.cc76
-rw-r--r--src/inputprocessor.h1
-rw-r--r--src/instrument.cc5
-rw-r--r--src/instrument.h2
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<SampleDOM> samples;
std::vector<InstrumentChannelDOM> 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<event_t>& 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<SampleEvent>(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;