From 1c25d3a69ac27dc1f93bca3a71996e757b452c4b Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 3 Sep 2017 14:08:41 +0200 Subject: Add bleed controls for the drumkit with priority over those set in the instrument files. --- src/audiofile.cc | 18 ++++++++++-- src/audiofile.h | 13 +++++++-- src/channel.h | 9 +++++- src/drumgizmo.cc | 7 +++-- src/drumkitparser.cc | 77 +++++++++++++++++++++++++++++++++---------------- src/drumkitparser.h | 7 ++++- src/instrumentparser.cc | 14 ++++----- 7 files changed, 102 insertions(+), 43 deletions(-) diff --git a/src/audiofile.cc b/src/audiofile.cc index a8e9d4a..c2c5cf9 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -35,11 +35,14 @@ #include -AudioFile::AudioFile(const std::string& filename, std::size_t filechannel, bool main) +#include "channel.h" + +AudioFile::AudioFile(const std::string& filename, std::size_t filechannel, + InstrumentChannel* instrument_channel) : filename(filename) , filechannel(filechannel) - , main(main) , magic{this} + , instrument_channel(instrument_channel) { } @@ -151,3 +154,14 @@ bool AudioFile::isLoaded() const { return is_loaded; } + +main_state_t AudioFile::mainState() const +{ + if(instrument_channel == nullptr) + { + DEBUG(audiofile, "no instrument_channel!"); + return main_state_t::unset; + } + + return instrument_channel->main; +} diff --git a/src/audiofile.h b/src/audiofile.h index 5d6cdae..d73dad8 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -35,11 +35,15 @@ #include #include "audio.h" +#include "channel.h" + +class InstrumentChannel; class AudioFile { public: - AudioFile(const std::string& filename, std::size_t filechannel, bool main = true); + AudioFile(const std::string& filename, std::size_t filechannel, + InstrumentChannel* instrument_channel = nullptr); ~AudioFile(); void load(std::size_t sample_limit = std::numeric_limits::max()); @@ -55,13 +59,16 @@ public: bool isValid() const; + //! Returns if this audio file is to be played on a main channel (ie. not a + //! secondary channel) + main_state_t mainState() const; + std::mutex mutex; std::size_t filechannel; - bool main; - private: void* magic{nullptr}; volatile bool is_loaded{false}; + InstrumentChannel* instrument_channel; }; diff --git a/src/channel.h b/src/channel.h index 52b2a9b..aaa2843 100644 --- a/src/channel.h +++ b/src/channel.h @@ -34,6 +34,13 @@ #define ALL_CHANNELS ((channel_t)0xffffffff) #define NO_CHANNEL ((channel_t)0xfffffffe) +enum class main_state_t +{ + unset, + is_main, + is_not_main +}; + class Channel { public: @@ -49,7 +56,7 @@ class InstrumentChannel public: InstrumentChannel(const std::string& name = ""); - bool main{true}; + main_state_t main{main_state_t::unset}; }; typedef std::vector Channels; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index dad174b..9874bbe 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -283,7 +283,8 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) size_t initial_chunksize = (pos + sz) - evt.offset; evt.buffer = audio_cache.open(af, initial_chunksize, af.filechannel, evt.cache_id); - if(!af.main && enable_bleed_control) + if((af.mainState() == main_state_t::is_not_main) && + enable_bleed_control) { evt.scale = master_bleed; } @@ -333,7 +334,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) for(; (n < optend) && (t < evt.buffer_size); n += N) { - *(vNsf*)&(s[n]) += *(vNsf*)&(evt.buffer[t]); + *(vNsf*)&(s[n]) += *(vNsf*)&(evt.buffer[t]) * evt.scale; t += N; } #endif @@ -354,7 +355,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) for(; (n < end) && (t < evt.buffer_size) && evt.rampdown; ++n) { float scale = (float)evt.rampdown/(float)evt.ramp_start; - s[n] += evt.buffer[t] * evt.scale * scale; + s[n] += evt.buffer[t] * evt.scale * scale; ++t; evt.rampdown--; } diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index f517ef7..2a49e47 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -177,7 +177,14 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr) return; } - channelmap[attr.at("in")] = attr.at("out"); + channel_attribute_t cattr{attr.at("out"), main_state_t::unset}; + if(attr.find("main") != attr.end()) + { + cattr.main_state = (attr.at("main") == "true") ? + main_state_t::is_main : main_state_t::is_not_main; + } + + channelmap[attr.at("in")] = cattr; } } @@ -185,43 +192,63 @@ void DrumKitParser::endTag(const std::string& name) { if(name == "instrument") { - auto ptr = std::make_unique(settings, rand); - ptr->setGroup(instr_group); + { + // Scope the std::unique_ptr 'ptr' so we don't accidentally use it after + // it is std::move'd to the instruments list. + auto ptr = std::make_unique(settings, rand); + ptr->setGroup(instr_group); + + InstrumentParser parser(*ptr); + parser.parseFile(path + "/" + instr_file); + + // Transfer ownership to the DrumKit object. + kit.instruments.emplace_back(std::move(ptr)); + } + + auto& instrument = *kit.instruments.back(); + + // Only use main attribute from drumkit file if at least one exists. + main_state_t default_main_state = main_state_t::unset; + for(const auto& channel: channelmap) + { + if(channel.second.main_state != main_state_t::unset) + { + default_main_state = main_state_t::is_not_main; + } + } - InstrumentParser parser(*ptr); - parser.parseFile(path + "/" + instr_file); + // Assign kit channel numbers to instruments channels and reset + // main_state attribute as needed. + for(auto& instrument_channel: instrument.instrument_channels) + { + channel_attribute_t cattr{instrument_channel.name, main_state_t::unset}; + if(channelmap.find(instrument_channel.name) != channelmap.end()) + { + cattr = channelmap[instrument_channel.name]; + } - // Transfer ownership to the DrumKit object. - kit.instruments.emplace_back(std::move(ptr)); - Instrument& instrument = *kit.instruments.back(); + if(cattr.main_state == main_state_t::unset) + { + cattr.main_state = default_main_state; + } - // Assign kit channel numbers to instruments channels. - for (auto& c: instrument.instrument_channels) { - std::string cname = c.name; - if(channelmap.find(cname) != channelmap.end()) + if(cattr.main_state != main_state_t::unset) { - cname = channelmap[cname]; + instrument_channel.main = cattr.main_state; } - for(std::size_t cnt = 0; cnt < kit.channels.size(); cnt++) + for(auto cnt = 0u; cnt < kit.channels.size(); ++cnt) { - if(kit.channels[cnt].name == cname) + if(kit.channels[cnt].name == cattr.cname) { - c.num = kit.channels[cnt].num; + instrument_channel.num = kit.channels[cnt].num; } } - if(c.num == NO_CHANNEL) + if(instrument_channel.num == NO_CHANNEL) { ERR(kitparser, "Missing channel '%s' in instrument '%s'\n", - c.name.c_str(), instrument.getName().c_str()); - } - else - { - /* - DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n", - c->name.c_str(), c->num, i.name().c_str()); - */ + instrument_channel.name.c_str(), instrument.getName().c_str()); } } diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 5c5cf9f..e4645c3 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -49,7 +49,12 @@ private: DrumKit& kit; std::string path; - std::unordered_map channelmap; + struct channel_attribute_t + { + std::string cname; + main_state_t main_state; + }; + std::unordered_map channelmap; std::string instr_file; std::string instr_name; std::string instr_group; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 1f3948e..f49a6af 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -94,14 +94,13 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) return; } - bool main = false; + InstrumentChannel* channel = addOrGetChannel(attr.at("name")); + channel->main = main_state_t::is_not_main; if(attr.find("main") != attr.end()) { - main = attr.at("main") == "true"; + channel->main = (attr.at("main") == "true") ? + main_state_t::is_main : main_state_t::is_not_main; } - - InstrumentChannel* channel = addOrGetChannel(attr.at("name")); - channel->main = main; } if(name == "samples") @@ -169,7 +168,7 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) auto audio_file = std::make_unique(path + "/" + attr.at("file"), filechannel, - instrument_channel->main); + instrument_channel); sample->addAudioFile(instrument_channel, audio_file.get()); @@ -263,8 +262,7 @@ InstrumentChannel* InstrumentParser::addOrGetChannel(const std::string& name) instrument.instrument_channels.emplace_back(name); InstrumentChannel& channel = instrument.instrument_channels.back(); - channel.main = true; // Ad-hoc added channels are all main by default for - // backwards compatibility. + channel.main = main_state_t::unset; return &channel; } -- cgit v1.2.3