summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/DGDOM.h2
-rw-r--r--src/channel.h2
-rw-r--r--src/dgxmlparser.cc9
-rw-r--r--src/domloader.cc2
-rw-r--r--src/drumgizmo.cc58
-rw-r--r--src/settings.h9
6 files changed, 81 insertions, 1 deletions
diff --git a/src/DGDOM.h b/src/DGDOM.h
index 474b29c..7d2bbc6 100644
--- a/src/DGDOM.h
+++ b/src/DGDOM.h
@@ -87,6 +87,8 @@ struct InstrumentDOM
struct ChannelDOM
{
std::string name;
+ double stereo_panning;
+ double stereo_volume;
};
struct ChannelMapDOM
diff --git a/src/channel.h b/src/channel.h
index aaa2843..fcc43e7 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -47,6 +47,8 @@ public:
Channel(const std::string& name = "");
std::string name;
+ double stereo_panning; //! [-1; 1] where -1 i left, 0 is center and 1 is right
+ double stereo_volume; //! [0; 1] volume scalar
channel_t num;
};
diff --git a/src/dgxmlparser.cc b/src/dgxmlparser.cc
index 0d3cdcd..983c2fd 100644
--- a/src/dgxmlparser.cc
+++ b/src/dgxmlparser.cc
@@ -256,7 +256,14 @@ bool parseDrumkitFile(const std::string& filename, DrumkitDOM& dom, LogFunction
for(pugi::xml_node channel: channels.children("channel"))
{
dom.channels.emplace_back();
- res &= attrcpy(dom.channels.back().name, channel, "name", logger, filename);
+ auto& ch = dom.channels.back();
+ res &= attrcpy(ch.name, channel, "name", logger, filename);
+ ch.stereo_panning = 0.0f;
+ ch.stereo_volume = 1.0f;
+ res &= attrcpy(ch.stereo_panning, channel, "stereo_panning",
+ logger, filename, true);
+ res &= attrcpy(ch.stereo_volume, channel, "stereo_volume",
+ logger, filename, true);
}
pugi::xml_node instruments = doc.child("drumkit").child("instruments");
diff --git a/src/domloader.cc b/src/domloader.cc
index c78ed75..bc5eea1 100644
--- a/src/domloader.cc
+++ b/src/domloader.cc
@@ -65,6 +65,8 @@ bool DOMLoader::loadDom(const std::string& basepath,
{
drumkit.channels.emplace_back();
drumkit.channels.back().name = channel.name;
+ drumkit.channels.back().stereo_panning = channel.stereo_panning;
+ drumkit.channels.back().stereo_volume = channel.stereo_volume;
drumkit.channels.back().num = drumkit.channels.size() - 1;
}
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index ca91c12..a67dace 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -185,6 +185,63 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
//
// Write audio
//
+ if(settings.enable_stereo_mode)
+ {
+ static sample_t left[4096];
+ static sample_t right[4096];
+ std::memset(left, 0, sizeof(left));
+ std::memset(right, 0, sizeof(right));
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ const auto& channel = kit.channels[c];
+ (void)channel;
+ const auto pan = channel.stereo_panning * 0.5 + 0.5; // -> [0; 1]
+ const auto scale = channel.stereo_volume;
+ static sample_t buf[4096];
+ std::memset(buf, 0, sizeof(buf));
+ getSamples(c, pos, buf, nsamples);
+ for(auto i = 0u; i < nsamples; ++i)
+ {
+ left[i] += buf[i] * pan * scale;
+ right[i] += buf[i] * (1 - pan) * scale;
+ }
+ }
+
+ for(size_t c = 0; c < kit.channels.size(); ++c)
+ {
+ sample_t *buf = samples;
+ bool internal = false;
+ if(oe.getBuffer(c))
+ {
+ buf = oe.getBuffer(c);
+ internal = true;
+ }
+
+ if(buf)
+ {
+ if(c == 0) // left channel
+ {
+ memcpy(buf, left, nsamples * sizeof(sample_t));
+ }
+ else if(c == 1) // right channel
+ {
+ memcpy(buf, right, nsamples * sizeof(sample_t));
+ }
+ else
+ {
+ std::memset(buf, 0, nsamples * sizeof(sample_t));
+ }
+
+ if(!internal)
+ {
+ oe.run(c, samples, nsamples);
+ }
+ }
+ }
+
+ }
+ else
+ {
if(!enable_resampling || ratio == 1.0)
{
// No resampling needed
@@ -250,6 +307,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
}
}
}
+ }
ie.post();
oe.post(nsamples);
diff --git a/src/settings.h b/src/settings.h
index 7507827..39c3534 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -174,6 +174,8 @@ struct Settings
// Time it takes for an old sample to completely fall silent.
static float constexpr voice_limit_rampdown_default = 0.5f;
Atomic<float> voice_limit_rampdown{voice_limit_rampdown_default};
+
+ Atomic<bool> enable_stereo_mode{true};
};
//! Settings getter class.
@@ -256,6 +258,8 @@ struct SettingsGetter
SettingRef<std::size_t> voice_limit_max;
SettingRef<float> voice_limit_rampdown;
+ SettingRef<bool> enable_stereo_mode;
+
SettingsGetter(Settings& settings)
: drumkit_file(settings.drumkit_file)
, drumkit_load_status(settings.drumkit_load_status)
@@ -316,6 +320,7 @@ struct SettingsGetter
, enable_voice_limit{settings.enable_voice_limit}
, voice_limit_max{settings.voice_limit_max}
, voice_limit_rampdown{settings.voice_limit_rampdown}
+ , enable_stereo_mode{settings.enable_stereo_mode}
{
}
};
@@ -399,6 +404,8 @@ public:
Notifier<std::size_t> voice_limit_max;
Notifier<float> voice_limit_rampdown;
+ Notifier<bool> enable_stereo_mode;
+
void evaluate()
{
#define EVAL(x) if(settings.x.hasChanged()) { x(settings.x.getValue()); }
@@ -477,6 +484,8 @@ public:
EVAL(enable_voice_limit);
EVAL(voice_limit_max);
EVAL(voice_limit_rampdown);
+
+ EVAL(enable_stereo_mode);
}
SettingsNotifier(Settings& settings)