diff options
-rw-r--r-- | src/DGDOM.h | 7 | ||||
-rw-r--r-- | src/dgxmlparser.cc | 40 | ||||
-rw-r--r-- | src/domloader.cc | 54 | ||||
-rw-r--r-- | src/events.h | 6 | ||||
-rw-r--r-- | src/inputprocessor.cc | 48 | ||||
-rw-r--r-- | src/instrument.cc | 10 | ||||
-rw-r--r-- | src/instrument.h | 12 |
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; |