summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/DGDOM.h7
-rw-r--r--src/dgxmlparser.cc40
-rw-r--r--src/domloader.cc54
-rw-r--r--src/events.h6
-rw-r--r--src/inputprocessor.cc48
-rw-r--r--src/instrument.cc10
-rw-r--r--src/instrument.h12
7 files changed, 154 insertions, 23 deletions
diff --git a/src/DGDOM.h b/src/DGDOM.h
index dea4228..1adf391 100644
--- a/src/DGDOM.h
+++ b/src/DGDOM.h
@@ -95,12 +95,19 @@ struct ChannelMapDOM
main_state_t main;
};
+struct ChokeDOM
+{
+ std::string instrument;
+ double choketime;
+};
+
struct InstrumentRefDOM
{
std::string name;
std::string file; // Probably shouldn't be there
std::string group;
std::vector<ChannelMapDOM> channel_map;
+ std::vector<ChokeDOM> chokes;
};
struct ClickMapDOM
diff --git a/src/dgxmlparser.cc b/src/dgxmlparser.cc
index 28e183a..ae0842a 100644
--- a/src/dgxmlparser.cc
+++ b/src/dgxmlparser.cc
@@ -193,18 +193,40 @@ bool parseDrumkitFile(const std::string& filename, DrumkitDOM& dom)
for(pugi::xml_node instrument : instruments.children("instrument"))
{
dom.instruments.emplace_back();
-
- res &= attrcpy(dom.instruments.back().name, instrument, "name");
- res &= attrcpy(dom.instruments.back().file, instrument, "file");
- res &= attrcpy(dom.instruments.back().group, instrument, "group", true);
+ auto& instrument_ref = dom.instruments.back();
+ res &= attrcpy(instrument_ref.name, instrument, "name");
+ res &= attrcpy(instrument_ref.file, instrument, "file");
+ res &= attrcpy(instrument_ref.group, instrument, "group", true);
for(pugi::xml_node cmap: instrument.children("channelmap"))
{
- dom.instruments.back().channel_map.emplace_back();
- res &= attrcpy(dom.instruments.back().channel_map.back().in, cmap, "in");
- res &= attrcpy(dom.instruments.back().channel_map.back().out, cmap, "out");
- dom.instruments.back().channel_map.back().main = main_state_t::unset;
- res &= attrcpy(dom.instruments.back().channel_map.back().main, cmap, "main", true);
+ instrument_ref.channel_map.emplace_back();
+ auto& channel_map_ref = instrument_ref.channel_map.back();
+ res &= attrcpy(channel_map_ref.in, cmap, "in");
+ res &= attrcpy(channel_map_ref.out, cmap, "out");
+ channel_map_ref.main = main_state_t::unset;
+ res &= attrcpy(channel_map_ref.main, cmap, "main", true);
+ }
+
+ auto num_chokes = std::distance(instrument.children("chokes").begin(),
+ instrument.children("chokes").end());
+ if(num_chokes > 1)
+ {
+ // error
+ ERR(dgxmlparser, "At most one 'chokes' node allowed pr. instrument.");
+ res = false;
+ }
+
+ if(num_chokes == 1)
+ {
+ for(pugi::xml_node choke : instrument.child("chokes").children("choke"))
+ {
+ instrument_ref.chokes.emplace_back();
+ auto& choke_ref = instrument_ref.chokes.back();
+ res &= attrcpy(choke_ref.instrument, choke, "instrument");
+ choke_ref.choketime = 68; // default to 68 ms
+ res &= attrcpy(choke_ref.choketime, choke, "choketime", true);
+ }
}
}
diff --git a/src/domloader.cc b/src/domloader.cc
index ad97165..0e06239 100644
--- a/src/domloader.cc
+++ b/src/domloader.cc
@@ -68,6 +68,9 @@ bool DOMLoader::loadDom(const std::string& basepath,
drumkit.channels.back().num = drumkit.channels.size() - 1;
}
+ // Pass 1 - handling everything that is instrument name based and ultimately
+ // inserts the instrument into the drumkit instrument list which results in
+ // it getting an instrument id (ie. the index in the list).
for(const auto& instrumentref : dom.instruments)
{
bool found{false};
@@ -198,6 +201,7 @@ bool DOMLoader::loadDom(const std::string& basepath,
// Transfer ownership to the DrumKit object.
drumkit.instruments.emplace_back(std::move(instrument));
+ drumkit.instruments.back()->id = drumkit.instruments.size() - 1;
found = true;
}
@@ -209,6 +213,56 @@ bool DOMLoader::loadDom(const std::string& basepath,
}
}
+ // Pass 2 - handle nodes that require instrument name to instrument id
+ // mappings
+ for(const auto& instrumentref : dom.instruments)
+ {
+ std::size_t instr_id{0};
+ {
+ bool found{false};
+ for(std::size_t idx = 0; idx < drumkit.instruments.size(); ++idx)
+ {
+ if(drumkit.instruments[idx]->getName() == instrumentref.name)
+ {
+ instr_id = idx;
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ // Missing instrument - skip
+ continue;
+ }
+ }
+
+ for(const auto& choke : instrumentref.chokes)
+ {
+ std::size_t choke_instr_id{0};
+ bool choke_found{false};
+ for(std::size_t idx = 0; idx < drumkit.instruments.size(); ++idx)
+ {
+ if(drumkit.instruments[idx]->getName() == choke.instrument)
+ {
+ choke_instr_id = idx;
+ choke_found = true;
+ break;
+ }
+ }
+
+ if(!choke_found)
+ {
+ // Missing choke target instrument - skip
+ continue;
+ }
+
+ drumkit.instruments[instr_id]->chokes.emplace_back();
+ drumkit.instruments[instr_id]->chokes.back().instrument_id = choke_instr_id;
+ drumkit.instruments[instr_id]->chokes.back().choketime = choke.choketime;
+ }
+ }
+
return true;
}
diff --git a/src/events.h b/src/events.h
index f43fbe2..18f9af3 100644
--- a/src/events.h
+++ b/src/events.h
@@ -65,16 +65,16 @@ class EventSample
{
public:
EventSample(channel_t c, float g, AudioFile* af,
- const std::string& grp, void* instr)
+ const std::string& grp, std::size_t instrument_id)
: Event(c)
, cache_id(CACHE_NOID)
, gain(g)
, t(0)
, file(af)
, group(grp)
- , instrument(instr)
, rampdown_count(-1)
, ramp_length(0)
+ , instrument_id(instrument_id)
{
}
@@ -98,11 +98,11 @@ public:
unsigned int t; //< Internal sample position.
AudioFile* file;
std::string group;
- void* instrument;
int rampdown_count;
int ramp_length;
std::size_t rampdown_offset{0};
float scale{1.0f};
+ std::size_t instrument_id;
};
class EventQueue
diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc
index 1570afe..1a3246c 100644
--- a/src/inputprocessor.cc
+++ b/src/inputprocessor.cc
@@ -95,17 +95,17 @@ bool InputProcessor::processOnset(event_t& event,
return false;
}
- std::size_t ev_instr = event.instrument;
+ std::size_t instrument_id = event.instrument;
Instrument* instr = nullptr;
- if(ev_instr < kit.instruments.size())
+ if(instrument_id < kit.instruments.size())
{
- instr = kit.instruments[ev_instr].get();
+ instr = kit.instruments[instrument_id].get();
}
if(instr == nullptr || !instr->isValid())
{
- ERR(inputprocessor, "Missing Instrument %d.\n", (int)ev_instr);
+ ERR(inputprocessor, "Missing Instrument %d.\n", (int)instrument_id);
return false;
}
@@ -124,19 +124,18 @@ bool InputProcessor::processOnset(event_t& event,
if(instr->getGroup() != "")
{
// Add event to ramp down all existing events with the same groupname.
- for(Channel& ch: kit.channels)
+ for(const auto& ch : kit.channels)
{
- for(Event* active_event: activeevents[ch.num])
+ for(auto active_event : activeevents[ch.num])
{
if(active_event->getType() == Event::sample)
{
auto& event_sample = *static_cast<EventSample*>(active_event);
if(event_sample.group == instr->getGroup() &&
- event_sample.instrument != instr)
+ event_sample.instrument_id != instrument_id &&
+ event_sample.rampdown_count == -1) // Only if not already ramping.
{
- // Fixed ramp of 68ms, independent of samplerate
- // TODO: This must be configurable at some point...
- // ... perhaps even by instrument (ie. in the xml file)
+ // Fixed group rampdown time of 68ms, independent of samplerate
std::size_t ramp_length = (68./1000.)*settings.samplerate.load();
event_sample.rampdown_count = ramp_length;
event_sample.rampdown_offset = event.offset;
@@ -147,6 +146,32 @@ bool InputProcessor::processOnset(event_t& event,
}
}
+ for(const auto& choke : instr->getChokes())
+ {
+ // Add event to ramp down all existing events with the same groupname.
+ for(const auto& ch : kit.channels)
+ {
+ for(auto active_event : activeevents[ch.num])
+ {
+ if(active_event->getType() == Event::sample)
+ {
+ auto& event_sample = *static_cast<EventSample*>(active_event);
+ if(choke.instrument_id == event_sample.instrument_id &&
+ event_sample.rampdown_count == -1) // Only if not already ramping.
+ {
+ // Choketime is in ms
+ std::size_t ramp_length =
+ (choke.choketime / 1000.0) * settings.samplerate.load();
+ event_sample.rampdown_count = ramp_length;
+ event_sample.rampdown_offset = event.offset;
+ event_sample.ramp_length = ramp_length;
+ }
+ }
+ }
+ }
+
+ }
+
const auto sample = instr->sample(event.velocity, event.offset + pos);
if(sample == nullptr)
@@ -170,7 +195,8 @@ bool InputProcessor::processOnset(event_t& event,
else
{
//DEBUG(inputprocessor, "Adding event %d.\n", event.offset);
- Event* evt = new EventSample(ch.num, 1.0, af, instr->getGroup(), instr);
+ Event* evt = new EventSample(ch.num, 1.0, af, instr->getGroup(),
+ instrument_id);
evt->offset = (event.offset + pos) * resample_ratio;
activeevents[ch.num].push_back(evt);
}
diff --git a/src/instrument.cc b/src/instrument.cc
index 29619d8..6cc4ee9 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -94,6 +94,11 @@ void Instrument::finalise()
}
}
+std::size_t Instrument::getID() const
+{
+ return id;
+}
+
const std::string& Instrument::getName() const
{
return _name;
@@ -146,3 +151,8 @@ float Instrument::getMinPower() const
return 0.0f;
}
}
+
+const std::vector<Choke>& Instrument::getChokes()
+{
+ return chokes;
+}
diff --git a/src/instrument.h b/src/instrument.h
index 125d7ab..e4cf481 100644
--- a/src/instrument.h
+++ b/src/instrument.h
@@ -40,6 +40,12 @@
#include "settings.h"
+struct Choke
+{
+ std::size_t instrument_id;
+ double choketime;
+};
+
class Instrument
{
public:
@@ -48,6 +54,7 @@ public:
const Sample* sample(level_t level, size_t pos);
+ std::size_t getID() const;
const std::string& getName() const;
const std::string& getDescription() const;
const std::string& getGroup() const;
@@ -66,6 +73,8 @@ public:
float getMaxPower() const;
float getMinPower() const;
+ const std::vector<Choke>& getChokes();
+
private:
// For unit-tests:
friend class DOMLoaderTest;
@@ -75,6 +84,7 @@ private:
void* magic;
+ std::size_t id;
std::string _group;
std::string _name;
std::string _description;
@@ -94,6 +104,8 @@ private:
Settings& settings;
Random& rand;
PowerList powerlist;
+
+ std::vector<Choke> chokes;
};
// typedef std::map< std::string, Instrument > Instruments;