summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2017-09-02 10:30:02 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2017-09-02 10:30:02 +0200
commite37c5f5048bb440140dc56ce773d105fc2129385 (patch)
tree0dfe0ab9faec524fd1ee085c6cf763aa15484331 /src
parent6a96bcf1659d07cd3a7f7e65519007abfaeda2a0 (diff)
Implement master bleed control in the instrument parser and engine.
Diffstat (limited to 'src')
-rw-r--r--src/audiofile.cc3
-rw-r--r--src/audiofile.h4
-rw-r--r--src/channel.cc27
-rw-r--r--src/channel.h9
-rw-r--r--src/drumgizmo.cc13
-rw-r--r--src/drumkitparser.cc15
-rw-r--r--src/events.h1
-rw-r--r--src/inputprocessor.cc2
-rw-r--r--src/instrument.h2
-rw-r--r--src/instrumentparser.cc58
-rw-r--r--src/instrumentparser.h4
-rw-r--r--src/powerlist.cc12
-rw-r--r--src/powerlist.h6
-rw-r--r--src/sample.cc6
-rw-r--r--src/sample.h7
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 <hugin.hpp>
-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<std::size_t>::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<Channel> 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<Instrument>(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<Sample*> samplelist;
+ std::vector<InstrumentChannel> 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<AudioFile>(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<AudioFile>(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<InstrumentChannel*> channellist;
+ std::vector<InstrumentChannel> 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<Channel*, int> count;
+ std::map<const Channel*, int> 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<PowerListItem> 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<Channel*, AudioFile*>;
+using AudioFiles = std::map<const InstrumentChannel*, AudioFile*>;
-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,