commit fe0d05f7dd38737381b45cd42519b6af21e54840
parent 0b877235a79c4b0eeaf249cceffbfa118cee7a62
Author: Matt Demanett <matt@demanett.net>
Date: Sat, 11 Apr 2020 02:13:27 -0400
PGMR: performance improvements; better performance for expandable/expander modules generally. #107
Diffstat:
7 files changed, 72 insertions(+), 38 deletions(-)
diff --git a/src/Mix4.hpp b/src/Mix4.hpp
@@ -15,7 +15,7 @@ struct Mix4x;
typedef MixerExpanderMessage<4> Mix4ExpanderMessage;
-struct Mix4 : ExpandableModule<Mix4ExpanderMessage, Mix4x, BGModule> {
+struct Mix4 : ExpandableModule<Mix4ExpanderMessage, BGModule> {
enum ParamsIds {
LEVEL1_PARAM,
PAN1_PARAM,
@@ -90,8 +90,10 @@ struct Mix4 : ExpandableModule<Mix4ExpanderMessage, Mix4x, BGModule> {
_channels[1] = new MixerChannel(params[LEVEL2_PARAM], params[MUTE2_PARAM], inputs[CV2_INPUT]);
_channels[2] = new MixerChannel(params[LEVEL3_PARAM], params[MUTE3_PARAM], inputs[CV3_INPUT]);
_channels[3] = new MixerChannel(params[LEVEL4_PARAM], params[MUTE4_PARAM], inputs[CV4_INPUT]);
+
sampleRateChange();
_rms.setSensitivity(0.05f);
+ setExpanderModel(modelMix4x);
}
virtual ~Mix4() {
for (int i = 0; i < 4; ++i) {
@@ -105,7 +107,7 @@ struct Mix4 : ExpandableModule<Mix4ExpanderMessage, Mix4x, BGModule> {
void processAll(const ProcessArgs& args) override;
};
-struct Mix4x : ExpanderModule<Mix4ExpanderMessage, Mix4, BGModule> {
+struct Mix4x : ExpanderModule<Mix4ExpanderMessage, BGModule> {
enum ParamsIds {
LOW1_PARAM,
MID1_PARAM,
@@ -205,6 +207,8 @@ struct Mix4x : ExpanderModule<Mix4ExpanderMessage, Mix4, BGModule> {
_channels[1] = new MixerExpanderChannel(params[LOW2_PARAM], params[MID2_PARAM], params[HIGH2_PARAM], params[A2_PARAM], params[B2_PARAM], params[PRE_A2_PARAM], params[PRE_B2_PARAM], inputs[A2_INPUT], inputs[B2_INPUT]);
_channels[2] = new MixerExpanderChannel(params[LOW3_PARAM], params[MID3_PARAM], params[HIGH3_PARAM], params[A3_PARAM], params[B3_PARAM], params[PRE_A3_PARAM], params[PRE_B3_PARAM], inputs[A3_INPUT], inputs[B3_INPUT]);
_channels[3] = new MixerExpanderChannel(params[LOW4_PARAM], params[MID4_PARAM], params[HIGH4_PARAM], params[A4_PARAM], params[B4_PARAM], params[PRE_A4_PARAM], params[PRE_B4_PARAM], inputs[A4_INPUT], inputs[B4_INPUT]);
+
+ setBaseModel(modelMix4);
}
virtual ~Mix4x() {
for (int i = 0; i < 4; ++i) {
diff --git a/src/Mix8.hpp b/src/Mix8.hpp
@@ -15,7 +15,7 @@ struct Mix8x;
typedef MixerExpanderMessage<8> Mix8ExpanderMessage;
-struct Mix8 : ExpandableModule<Mix8ExpanderMessage, Mix8x, BGModule> {
+struct Mix8 : ExpandableModule<Mix8ExpanderMessage, BGModule> {
enum ParamsIds {
LEVEL1_PARAM,
MUTE1_PARAM,
@@ -130,8 +130,10 @@ struct Mix8 : ExpandableModule<Mix8ExpanderMessage, Mix8x, BGModule> {
_channels[5] = new MixerChannel(params[LEVEL6_PARAM], params[MUTE6_PARAM], inputs[CV6_INPUT]);
_channels[6] = new MixerChannel(params[LEVEL7_PARAM], params[MUTE7_PARAM], inputs[CV7_INPUT]);
_channels[7] = new MixerChannel(params[LEVEL8_PARAM], params[MUTE8_PARAM], inputs[CV8_INPUT]);
+
sampleRateChange();
_rms.setSensitivity(0.05f);
+ setExpanderModel(modelMix8x);
}
virtual ~Mix8() {
for (int i = 0; i < 8; ++i) {
@@ -145,7 +147,7 @@ struct Mix8 : ExpandableModule<Mix8ExpanderMessage, Mix8x, BGModule> {
void processAll(const ProcessArgs& args) override;
};
-struct Mix8x : ExpanderModule<Mix8ExpanderMessage, Mix8, BGModule> {
+struct Mix8x : ExpanderModule<Mix8ExpanderMessage, BGModule> {
enum ParamsIds {
LOW1_PARAM,
MID1_PARAM,
@@ -313,6 +315,8 @@ struct Mix8x : ExpanderModule<Mix8ExpanderMessage, Mix8, BGModule> {
_channels[5] = new MixerExpanderChannel(params[LOW6_PARAM], params[MID6_PARAM], params[HIGH6_PARAM], params[A6_PARAM], params[B6_PARAM], params[PRE_A6_PARAM], params[PRE_B6_PARAM], inputs[A6_INPUT], inputs[B6_INPUT]);
_channels[6] = new MixerExpanderChannel(params[LOW7_PARAM], params[MID7_PARAM], params[HIGH7_PARAM], params[A7_PARAM], params[B7_PARAM], params[PRE_A7_PARAM], params[PRE_B7_PARAM], inputs[A7_INPUT], inputs[B7_INPUT]);
_channels[7] = new MixerExpanderChannel(params[LOW8_PARAM], params[MID8_PARAM], params[HIGH8_PARAM], params[A8_PARAM], params[B8_PARAM], params[PRE_A8_PARAM], params[PRE_B8_PARAM], inputs[A8_INPUT], inputs[B8_INPUT]);
+
+ setBaseModel(modelMix8);
}
virtual ~Mix8x() {
for (int i = 0; i < 8; ++i) {
diff --git a/src/Pgmr.cpp b/src/Pgmr.cpp
@@ -80,7 +80,7 @@ PgmrRegistry& PgmrRegistry::registry() {
void Pgmr::reset() {
- std::lock_guard<std::mutex> lock(_stepsLock);
+ std::lock_guard<SpinLock> lock(_stepsLock);
for (int c = 0; c < maxChannels; ++c) {
_lastSteps[c] = -1;
@@ -124,7 +124,7 @@ void Pgmr::processAlways(const ProcessArgs& args) {
}
void Pgmr::processChannel(const ProcessArgs& args, int c) {
- std::lock_guard<std::mutex> lock(_stepsLock);
+ std::lock_guard<SpinLock> lock(_stepsLock);
int steps = _steps.size();
if (c == 0) {
for (int i = 0, n = _steps.size(); i < n; ++i) {
@@ -200,7 +200,7 @@ void Pgmr::processChannel(const ProcessArgs& args, int c) {
}
void Pgmr::setSteps(std::vector<PgmrStep*>& steps) {
- std::lock_guard<std::mutex> lock(_stepsLock);
+ std::lock_guard<SpinLock> lock(_stepsLock);
_steps = steps;
}
@@ -342,7 +342,7 @@ struct PgmrWidget : AddressableSequenceBaseModuleWidget {
mi->addItem(RangeOptionMenuItem(m, "+/-1V", 0.0f, 1.0f));
OptionsMenuItem::addToMenu(mi, menu);
- OptionsMenuItem* so = new OptionsMenuItem("Step-selected output");
+ OptionsMenuItem* so = new OptionsMenuItem("Output on selected step");
so->addItem(OptionMenuItem("Gate", [m]() { return !m->_selectTriggers; }, [m]() { m->_selectTriggers = false; }));
so->addItem(OptionMenuItem("Trigger", [m]() { return m->_selectTriggers; }, [m]() { m->_selectTriggers = true; }));
OptionsMenuItem::addToMenu(so, menu);
diff --git a/src/Pgmr.hpp b/src/Pgmr.hpp
@@ -94,7 +94,7 @@ public:
static PgmrRegistry& registry();
};
-struct Pgmr : ExpandableModule<PgmrExpanderMessage, PgmrX, OutputRangeAddressableSequenceModule>, PgmrBase {
+struct Pgmr : ExpandableModule<PgmrExpanderMessage, OutputRangeAddressableSequenceModule>, PgmrBase {
enum ParamsIds {
DIRECTION_PARAM,
SELECT_ON_CLOCK_PARAM,
@@ -154,7 +154,7 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, PgmrX, OutputRangeAddressabl
float _sampleTime = 0.001f;
bool _selectTriggers = false;
- std::mutex _stepsLock;
+ SpinLock _stepsLock;
std::vector<PgmrStep*> _steps;
int _lastSteps[maxChannels] {};
rack::dsp::PulseGenerator _allPulseGens[maxChannels];
@@ -190,6 +190,8 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, PgmrX, OutputRangeAddressabl
_localSteps[1] = new PgmrStep(params[CVA2_PARAM], params[CVB2_PARAM], params[CVC2_PARAM], params[CVD2_PARAM], lights[SELECT2_LIGHT], params[SELECT2_PARAM], inputs[SELECT2_INPUT], outputs[SELECT2_OUTPUT]);
_localSteps[2] = new PgmrStep(params[CVA3_PARAM], params[CVB3_PARAM], params[CVC3_PARAM], params[CVD3_PARAM], lights[SELECT3_LIGHT], params[SELECT3_PARAM], inputs[SELECT3_INPUT], outputs[SELECT3_OUTPUT]);
_localSteps[3] = new PgmrStep(params[CVA4_PARAM], params[CVB4_PARAM], params[CVC4_PARAM], params[CVD4_PARAM], lights[SELECT4_LIGHT], params[SELECT4_PARAM], inputs[SELECT4_INPUT], outputs[SELECT4_OUTPUT]);
+
+ setExpanderModel(modelPgmrX);
_id = PgmrRegistry::registry().registerBase(*this);
}
virtual ~Pgmr() {
@@ -206,7 +208,7 @@ struct Pgmr : ExpandableModule<PgmrExpanderMessage, PgmrX, OutputRangeAddressabl
void setSteps(std::vector<PgmrStep*>& steps);
};
-struct PgmrX : ExpanderModule<PgmrExpanderMessage, PgmrBase, ExpandableModule<PgmrExpanderMessage, PgmrX, BGModule>>, PgmrBase {
+struct PgmrX : ExpanderModule<PgmrExpanderMessage, ExpandableModule<PgmrExpanderMessage, BGModule>>, PgmrBase {
enum ParamsIds {
CVA1_PARAM,
CVB1_PARAM,
@@ -288,10 +290,15 @@ struct PgmrX : ExpanderModule<PgmrExpanderMessage, PgmrBase, ExpandableModule<Pg
configParam<OutputParamQuantity>(CVC4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4C", " V");
configParam<OutputParamQuantity>(CVD4_PARAM, -1.0f, 1.0f, 0.0f, "Step 4D", " V");
configParam<OutputParamQuantity>(SELECT4_PARAM, 0.0f, 1.0f, 0.0f, "Select 4");
+
_localSteps[0] = new PgmrStep(params[CVA1_PARAM], params[CVB1_PARAM], params[CVC1_PARAM], params[CVD1_PARAM], lights[SELECT1_LIGHT], params[SELECT1_PARAM], inputs[SELECT1_INPUT], outputs[SELECT1_OUTPUT]);
_localSteps[1] = new PgmrStep(params[CVA2_PARAM], params[CVB2_PARAM], params[CVC2_PARAM], params[CVD2_PARAM], lights[SELECT2_LIGHT], params[SELECT2_PARAM], inputs[SELECT2_INPUT], outputs[SELECT2_OUTPUT]);
_localSteps[2] = new PgmrStep(params[CVA3_PARAM], params[CVB3_PARAM], params[CVC3_PARAM], params[CVD3_PARAM], lights[SELECT3_LIGHT], params[SELECT3_PARAM], inputs[SELECT3_INPUT], outputs[SELECT3_OUTPUT]);
_localSteps[3] = new PgmrStep(params[CVA4_PARAM], params[CVB4_PARAM], params[CVC4_PARAM], params[CVD4_PARAM], lights[SELECT4_LIGHT], params[SELECT4_PARAM], inputs[SELECT4_INPUT], outputs[SELECT4_OUTPUT]);
+
+ setBaseModel(modelPgmr);
+ setChainableModel(modelPgmrX);
+ setExpanderModel(modelPgmrX);
}
virtual ~PgmrX() {
PgmrRegistry::registry().deregisterExpander(_baseID, _position);
diff --git a/src/TestExpander.hpp b/src/TestExpander.hpp
@@ -14,7 +14,7 @@ struct TestExpanderMessage : ExpanderMessage {
struct TestExpanderExtension;
-struct TestExpanderBase : ExpandableModule<TestExpanderMessage, TestExpanderExtension, BGModule> {
+struct TestExpanderBase : ExpandableModule<TestExpanderMessage, BGModule> {
enum ParamsIds {
NUM_PARAMS
};
@@ -36,6 +36,7 @@ struct TestExpanderBase : ExpandableModule<TestExpanderMessage, TestExpanderExte
TestExpanderBase() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
+ setExpanderModel(modelTestExpanderExtension);
}
int channels() override;
@@ -43,7 +44,7 @@ struct TestExpanderBase : ExpandableModule<TestExpanderMessage, TestExpanderExte
void processChannel(const ProcessArgs& args, int c) override;
};
-struct TestExpanderExtension : ExpanderModule<TestExpanderMessage, TestExpanderBase, BGModule> {
+struct TestExpanderExtension : ExpanderModule<TestExpanderMessage, BGModule> {
enum ParamsIds {
NUM_PARAMS
};
@@ -64,6 +65,7 @@ struct TestExpanderExtension : ExpanderModule<TestExpanderMessage, TestExpanderB
TestExpanderExtension() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
+ setBaseModel(modelTestExpanderBase);
}
void processAll(const ProcessArgs& args) override;
diff --git a/src/expanders.hpp b/src/expanders.hpp
@@ -15,8 +15,9 @@ struct ExpanderMessage {
virtual ~ExpanderMessage() {}
};
-template<class MSG, class EM, class BASE>
+template<class MSG, class BASE>
struct ExpandableModule : BASE {
+ Model* _expanderModel = NULL;
MSG _messages[2] {};
bool _wasConnected = false;
@@ -28,27 +29,24 @@ struct ExpandableModule : BASE {
BGModule::rightExpander.consumerMessage = &_messages[1];
}
+ void setExpanderModel(Model* m) {
+ _expanderModel = m;
+ }
+
bool expanderConnected() {
- bool connected = BGModule::rightExpander.module && dynamic_cast<EM*>(BGModule::rightExpander.module);
+ bool connected = BGModule::rightExpander.module && _expanderModel && BGModule::rightExpander.module->model == _expanderModel;
if (!connected && _wasConnected) {
_messages[1] = _messages[0] = MSG();
}
return _wasConnected = connected;
}
- MSG* toExpander() {
- assert(expanderConnected());
- MSG* m = (MSG*)BGModule::rightExpander.module->leftExpander.producerMessage;
- assert(m);
- m->channels = BGModule::_channels;
- return m;
+ inline MSG* toExpander() {
+ return (MSG*)BGModule::rightExpander.module->leftExpander.producerMessage;
}
- MSG* fromExpander() {
- assert(expanderConnected());
- MSG* m = (MSG*)BGModule::rightExpander.consumerMessage;
- assert(m);
- return m;
+ inline MSG* fromExpander() {
+ return (MSG*)BGModule::rightExpander.consumerMessage;
}
void process(const BGModule::ProcessArgs& args) override {
@@ -60,8 +58,10 @@ struct ExpandableModule : BASE {
};
// An expander must be to the right of the expanded module to work.
-template<class MSG, class BM, class BASE>
+template<class MSG, class BASE>
struct ExpanderModule : BASE {
+ Model* _baseModel = NULL;
+ Model* _chainableModel = NULL;
MSG _messages[2] {};
bool _wasConnected = false;
@@ -73,26 +73,28 @@ struct ExpanderModule : BASE {
BGModule::leftExpander.consumerMessage = &_messages[1];
}
+ void setBaseModel(Model* m) {
+ _baseModel = m;
+ }
+
+ void setChainableModel(Model* m) {
+ _chainableModel = m;
+ }
+
bool baseConnected() {
- bool connected = BGModule::leftExpander.module && dynamic_cast<BM*>(BGModule::leftExpander.module);
+ bool connected = BGModule::leftExpander.module && ((_baseModel && BGModule::leftExpander.module->model == _baseModel) || (_chainableModel && BGModule::leftExpander.module->model == _chainableModel));
if (!connected && _wasConnected) {
_messages[1] = _messages[0] = MSG();
}
return _wasConnected = connected;
}
- MSG* fromBase() {
- assert(baseConnected());
- MSG* m = (MSG*)BGModule::leftExpander.consumerMessage;
- assert(m);
- return m;
+ inline MSG* fromBase() {
+ return (MSG*)BGModule::leftExpander.consumerMessage;
}
- MSG* toBase() {
- assert(baseConnected());
- MSG* m = (MSG*)BGModule::leftExpander.module->rightExpander.producerMessage;
- assert(m);
- return m;
+ inline MSG* toBase() {
+ return (MSG*)BGModule::leftExpander.module->rightExpander.producerMessage;
}
int channels() override final {
diff --git a/src/utils.hpp b/src/utils.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <atomic>
+
#include "rack.hpp"
using namespace rack;
@@ -17,4 +19,17 @@ Model* createModel(
return rack::createModel<TModule, TModuleWidget>(slug);
}
+// https://stackoverflow.com/questions/26583433/c11-implementation-of-spinlock-using-atomic
+struct SpinLock {
+ std::atomic_flag locked = ATOMIC_FLAG_INIT ;
+
+ void lock() {
+ while (locked.test_and_set(std::memory_order_acquire)) {}
+ }
+
+ void unlock() {
+ locked.clear(std::memory_order_release);
+ }
+};
+
} // namespace bogaudio