From e37c5f5048bb440140dc56ce773d105fc2129385 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 2 Sep 2017 10:30:02 +0200 Subject: Implement master bleed control in the instrument parser and engine. --- src/audiofile.cc | 3 ++- src/audiofile.h | 4 +++- src/channel.cc | 27 ++++------------------- src/channel.h | 9 +++++++- src/drumgizmo.cc | 13 +++++++++-- src/drumkitparser.cc | 15 +++++++------ src/events.h | 1 + src/inputprocessor.cc | 2 +- src/instrument.h | 2 ++ src/instrumentparser.cc | 58 +++++++++++++++++++++++++++++++++++++++---------- src/instrumentparser.h | 4 +++- src/powerlist.cc | 12 +++++----- src/powerlist.h | 6 ++--- src/sample.cc | 6 ++--- src/sample.h | 7 +++--- 15 files changed, 105 insertions(+), 64 deletions(-) diff --git a/src/audiofile.cc b/src/audiofile.cc index e274e61..a8e9d4a 100644 --- a/src/audiofile.cc +++ b/src/audiofile.cc @@ -35,9 +35,10 @@ #include -AudioFile::AudioFile(const std::string& filename, std::size_t filechannel) +AudioFile::AudioFile(const std::string& filename, std::size_t filechannel, bool main) : filename(filename) , filechannel(filechannel) + , main(main) , magic{this} { } diff --git a/src/audiofile.h b/src/audiofile.h index e393511..5d6cdae 100644 --- a/src/audiofile.h +++ b/src/audiofile.h @@ -39,7 +39,7 @@ class AudioFile { public: - AudioFile(const std::string& filename, std::size_t filechannel); + AudioFile(const std::string& filename, std::size_t filechannel, bool main = true); ~AudioFile(); void load(std::size_t sample_limit = std::numeric_limits::max()); @@ -59,6 +59,8 @@ public: std::size_t filechannel; + bool main; + private: void* magic{nullptr}; volatile bool is_loaded{false}; diff --git a/src/channel.cc b/src/channel.cc index 402a09a..812b43e 100644 --- a/src/channel.cc +++ b/src/channel.cc @@ -32,26 +32,7 @@ Channel::Channel(const std::string& name) { } -#ifdef TEST_CHANNEL -// deps: -// cflags: -// libs: -#include "test.h" - -TEST_BEGIN; - -Channel c1; -TEST_EQUAL_STR(c1.name, "", "Empty name?"); -TEST_EQUAL_INT(c1.num, NO_CHANNEL, "No physical channel assigned?"); - -Channel c2("ch2"); -TEST_EQUAL_STR(c2.name, "ch2", "Nonempty name?"); -TEST_EQUAL_INT(c2.num, NO_CHANNEL, "No physical channel assigned?"); - -Channels channels; -channels.push_back(c1); -channels.push_back(c2); - -TEST_END; - -#endif /*TEST_CHANNEL*/ +InstrumentChannel::InstrumentChannel(const std::string& name) + : Channel(name) +{ +} diff --git a/src/channel.h b/src/channel.h index 6cfee81..52b2a9b 100644 --- a/src/channel.h +++ b/src/channel.h @@ -43,6 +43,13 @@ public: channel_t num; }; -typedef Channel InstrumentChannel; +class InstrumentChannel + : public Channel +{ +public: + InstrumentChannel(const std::string& name = ""); + + bool main{true}; +}; typedef std::vector Channels; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 5fa2097..dad174b 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -248,6 +248,10 @@ typedef float vNsf __attribute__ ((vector_size(sizeof(sample_t)*N))); void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) { + // Store local values of settings to ensure they don't change intra-iteration + const auto enable_bleed_control = settings.enable_bleed_control.load(); + const auto master_bleed = settings.master_bleed.load(); + std::vector< Event* > erase_list; std::list< Event* >::iterator i = activeevents[ch].begin(); for(; i != activeevents[ch].end(); ++i) @@ -279,6 +283,11 @@ 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) + { + evt.scale = master_bleed; + } + evt.buffer_size = initial_chunksize; } @@ -336,7 +345,7 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) assert(t >= 0); assert(t < evt.buffer_size); - s[n] += evt.buffer[t]; + s[n] += evt.buffer[t] * evt.scale; ++t; } } @@ -345,7 +354,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] * scale; + s[n] += evt.buffer[t] * evt.scale * scale; ++t; evt.rampdown--; } diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index dd79bce..f517ef7 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -187,16 +187,17 @@ void DrumKitParser::endTag(const std::string& name) { 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.push_back(std::move(ptr)); + kit.instruments.emplace_back(std::move(ptr)); + Instrument& instrument = *kit.instruments.back(); // Assign kit channel numbers to instruments channels. - for (auto& c: parser.channellist) { - std::string cname = c->name; + for (auto& c: instrument.instrument_channels) { + std::string cname = c.name; if(channelmap.find(cname) != channelmap.end()) { cname = channelmap[cname]; @@ -206,14 +207,14 @@ void DrumKitParser::endTag(const std::string& name) { if(kit.channels[cnt].name == cname) { - c->num = kit.channels[cnt].num; + c.num = kit.channels[cnt].num; } } - if(c->num == NO_CHANNEL) + if(c.num == NO_CHANNEL) { ERR(kitparser, "Missing channel '%s' in instrument '%s'\n", - c->name.c_str(), ptr->getName().c_str()); + c.name.c_str(), instrument.getName().c_str()); } else { diff --git a/src/events.h b/src/events.h index b0ca6cf..30a9e8b 100644 --- a/src/events.h +++ b/src/events.h @@ -91,6 +91,7 @@ public: void* instrument; int rampdown; int ramp_start; + float scale{1.0f}; }; class EventQueue diff --git a/src/inputprocessor.cc b/src/inputprocessor.cc index af07dad..5d96e2d 100644 --- a/src/inputprocessor.cc +++ b/src/inputprocessor.cc @@ -151,7 +151,7 @@ bool InputProcessor::processOnset(event_t& event, for(Channel& ch: kit.channels) { - AudioFile* af = sample->getAudioFile(&ch); + AudioFile* af = sample->getAudioFile(ch); if(af == nullptr || !af->isValid()) { //DEBUG(inputprocessor, "Missing AudioFile.\n"); diff --git a/src/instrument.h b/src/instrument.h index 41fe886..4076b48 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -42,6 +42,7 @@ class Instrument { friend class InstrumentParser; + friend class DrumKitParser; public: Instrument(Settings& settings, Random& rand); ~Instrument(); @@ -78,6 +79,7 @@ private: void finalise(); ///< Signal instrument that no more samples will be added. std::vector samplelist; + std::vector instrument_channels; size_t lastpos; float mod; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 45e76d8..1f3948e 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -82,6 +82,28 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) } } + if(name == "channels") + { + } + + if(name == "channel") + { + if(attr.find("name") == attr.end()) + { + ERR(instrparser,"Missing channel required attribute 'name'.\n"); + return; + } + + bool main = false; + if(attr.find("main") != attr.end()) + { + main = attr.at("main") == "true"; + } + + InstrumentChannel* channel = addOrGetChannel(attr.at("name")); + channel->main = main; + } + if(name == "samples") { } @@ -142,19 +164,13 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) filechannel = filechannel - 1; // 1-based in file but zero-based internally. - auto audio_file = std::make_unique(path + "/" + attr.at("file"), filechannel); + InstrumentChannel *instrument_channel = addOrGetChannel(attr.at("channel")); - // note: memory leak! the channels are never released - // once I replaced this using unique_ptr, the channels were - // destroyed when the InstrumentParser went out of scope - // (see drumkitparser.cc, where the InstrumentParser lives in - // local scope). - // so.. we cannot replace this using smart ptr until we decided - // the ownership semantics for instances InstrumentChannel - InstrumentChannel *instrument_channel = - new InstrumentChannel(attr.at("channel")); + auto audio_file = + std::make_unique(path + "/" + attr.at("file"), + filechannel, + instrument_channel->main); - channellist.push_back(instrument_channel); sample->addAudioFile(instrument_channel, audio_file.get()); // Transfer audio_file ownership to the instrument. @@ -203,7 +219,7 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) if(sample_ref == nullptr) { - ERR(instrparser,"Samplref pointed at non-existing sample.\n"); + ERR(instrparser,"Sampleref pointed at non-existing sample.\n"); return; } @@ -234,3 +250,21 @@ void InstrumentParser::endTag(const std::string& name) instrument.finalise(); } } + +InstrumentChannel* InstrumentParser::addOrGetChannel(const std::string& name) +{ + for(auto& channel : instrument.instrument_channels) + { + if(channel.name == name) + { + return &channel; + } + } + + 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. + + return &channel; +} diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 512f12f..e87489f 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -41,13 +41,15 @@ public: virtual int parseFile(const std::string& filename) override; - std::vector channellist; + std::vector channellist; protected: virtual void startTag(const std::string& name, const attr_t& attr) override; virtual void endTag(const std::string& name) override; private: + InstrumentChannel* addOrGetChannel(const std::string& name); + Instrument& instrument; Sample* sample{nullptr}; diff --git a/src/powerlist.cc b/src/powerlist.cc index b502d03..b5e7c84 100644 --- a/src/powerlist.cc +++ b/src/powerlist.cc @@ -67,19 +67,19 @@ void PowerList::add(Sample* sample) samples.push_back(item); } -Channel* PowerList::getMasterChannel() +const Channel* PowerList::getMasterChannel() { - std::map count; + std::map count; for (auto& item: samples) { Sample* sample{item.sample}; - Channel* max_channel{nullptr}; + const Channel* max_channel{nullptr}; sample_t max_val{0}; for (auto& pair: sample->audiofiles) { - Channel* c = pair.first; + const Channel* c = pair.first; AudioFile* af = pair.second; af->load(LOAD_SIZE); @@ -116,7 +116,7 @@ Channel* PowerList::getMasterChannel() } } - Channel* master{nullptr}; + const Channel* master{nullptr}; int max_count{-1}; for (auto& pair: count) @@ -134,7 +134,7 @@ Channel* PowerList::getMasterChannel() void PowerList::finalise() { #ifdef AUTO_CALCULATE_POWER - Channel* master_channel = getMasterChannel(); + const Channel* master_channel = getMasterChannel(); if(master_channel == nullptr) { diff --git a/src/powerlist.h b/src/powerlist.h index ff360b4..9066ce1 100644 --- a/src/powerlist.h +++ b/src/powerlist.h @@ -38,7 +38,7 @@ public: void add(Sample* s); void finalise(); ///< Call this when no more samples will be added. - + Sample* get(level_t velocity); private: @@ -53,7 +53,7 @@ private: std::vector samples; float power_max; float power_min; - - Channel* getMasterChannel(); + + const Channel* getMasterChannel(); Sample* lastsample; }; diff --git a/src/sample.cc b/src/sample.cc index 9d28a17..1f624d3 100644 --- a/src/sample.cc +++ b/src/sample.cc @@ -39,12 +39,12 @@ Sample::~Sample() { } -void Sample::addAudioFile(Channel* c, AudioFile* a) +void Sample::addAudioFile(InstrumentChannel* c, AudioFile* a) { audiofiles[c] = a; } -AudioFile* Sample::getAudioFile(Channel* c) +AudioFile* Sample::getAudioFile(const Channel& channel) { /* if(audiofiles.find(c) == audiofiles.end()) return nullptr; @@ -54,7 +54,7 @@ AudioFile* Sample::getAudioFile(Channel* c) // todo: std::find_if ?? for (auto& pair: audiofiles) { - if (pair.first->num == c->num) + if (pair.first->num == channel.num) { return pair.second; } diff --git a/src/sample.h b/src/sample.h index f00db13..e9cbf18 100644 --- a/src/sample.h +++ b/src/sample.h @@ -32,16 +32,17 @@ #include "channel.h" #include "audiofile.h" -using AudioFiles = std::map; +using AudioFiles = std::map; -class Sample { +class Sample +{ friend class InstrumentParser; friend class PowerList; public: Sample(const std::string& name, float power); ~Sample(); - AudioFile* getAudioFile(InstrumentChannel *instrument_channel); + AudioFile* getAudioFile(const Channel& channel); private: void addAudioFile(InstrumentChannel* instrument_channel, -- cgit v1.2.3