commit fc9025f5b2d934a96d35bc82bbbc9153a56d47b9
parent ea1347964e82bcccfe4a302b6c9c361b1445ee92
Author: Matt Demanett <matt@demanett.net>
Date: Wed, 7 Oct 2020 23:00:33 -0400
MX44CVM, MX88M: add "solo by columns" option.
Diffstat:
14 files changed, 82 insertions(+), 18 deletions(-)
diff --git a/README-prerelease.md b/README-prerelease.md
@@ -646,6 +646,8 @@ _Polyphony:_ <a href="#polyphony">Polyphonic</a>, with polyphonic channels defin
An expander for MATRIX44, adding CVs and mutes for each point in the mix matrix. The CVs are bipolar (+/-5v), and each is attenuverted by its corresponding knob when in use. The mute buttons will mute the corresponding mix point, overriding the knob and CV. As on <a href="mix8">MIX8</a> and others, the mute buttons can be right-clicked to solo that mix point -- all others will be muted. A subsequent click on a soloed button restores the previous state, and other muted buttons retake effect.
+If the context menu option "Solo mutes by column" is enabled, the solo feature applies within the columns of mutes, which is to say soloing a mix point will only affect the output for that mix point, rather than all outputs.
+
MX44CVM must be positioned to the right of, and adjacent to, the MATRIX44 module it will expand. See <a href="#expanders">notes on expanders</a>.
#### <a name="matrix88"></a> MATRIX88
@@ -664,6 +666,8 @@ MX88CV must be positioned to the right of, and adjacent to, the MATRIX88 module
An expander for MATRIX88, adding mutes for each point in the mix matrix. The mute buttons will mute the corresponding mix point, overriding the knob (and CV if a MX88CV is in use). As on <a href="mix8">MIX8</a> and others, the mute buttons can be right-clicked to solo that mix point -- all others will be muted. A subsequent click on a soloed button restores the previous state, and other muted buttons retake effect.
+If the context menu option "Solo mutes by column" is enabled, the solo feature applies within the columns of mutes, which is to say soloing a mix point will only affect the output for that mix point, rather than all outputs.
+
MX88M must be positioned to the right of, and adjacent to, the MATRIX88 module it will expand, or a MX88CV module that is itself expanding a MATRIX88. See <a href="#expanders">notes on expanders</a>.
#### <a name="switch81"></a> SWITCH81
diff --git a/src/Matrix44.cpp b/src/Matrix44.cpp
@@ -5,6 +5,7 @@ void Matrix44::elementsChanged() {
// base-class caller holds lock on _elements.
Input** cvs = NULL;
Param** mutes = NULL;
+ bool* soloByColumns = NULL;
if (_elements.size() > 1) {
auto e = _elements[1];
assert(e);
@@ -14,9 +15,13 @@ void Matrix44::elementsChanged() {
if (e->mutes) {
mutes = e->mutes;
}
+ if (e->soloByColumns) {
+ soloByColumns = e->soloByColumns;
+ }
}
setCVInputs(cvs);
setMuteParams(mutes);
+ setSoloByColumns(soloByColumns);
}
void Matrix44::processAlways(const ProcessArgs& args) {
diff --git a/src/Matrix44.hpp b/src/Matrix44.hpp
@@ -63,7 +63,7 @@ struct Matrix44 : Matrix44Base {
configParam(MIX34_PARAM, -1.0f, 1.0f, 0.0f, "Mix 3D", "%", 0.0f, 100.0f);
configParam(MIX44_PARAM, -1.0f, 1.0f, 0.0f, "Mix 4D", "%", 0.0f, 100.0f);
- setLocalElements({new Matrix44Element(NULL, NULL)});
+ setLocalElements({new Matrix44Element(NULL, NULL, NULL)});
registerBase();
setExpanderModelPredicate([](Model* m) { return m == modelMatrix44Cvm; });
}
diff --git a/src/Matrix44Cvm.cpp b/src/Matrix44Cvm.cpp
@@ -19,7 +19,7 @@ void Matrix44Cvm::processAlways(const ProcessArgs& args) {
}
}
-struct Matrix44CvmWidget : BGModuleWidget {
+struct Matrix44CvmWidget : MutesMatrixExpanderModuleWidget {
static constexpr int hp = 10;
Matrix44CvmWidget(Matrix44Cvm* module) {
diff --git a/src/Matrix44Cvm.hpp b/src/Matrix44Cvm.hpp
@@ -4,7 +4,7 @@
namespace bogaudio {
-typedef ChainableExpanderModule<Matrix44ExpanderMessage, Matrix44Element, 1, BGModule> Matrix44CvmBase;
+typedef ChainableExpanderModule<Matrix44ExpanderMessage, Matrix44Element, 1, MutesMatrixExpanderModule> Matrix44CvmBase;
struct Matrix44Cvm : Matrix44CvmBase {
enum ParamsIds {
@@ -79,7 +79,7 @@ struct Matrix44Cvm : Matrix44CvmBase {
_mutes[i] = ¶ms[MUTE11_PARAM + i];
_cvs[i] = &inputs[CV11_INPUT + i];
}
- setLocalElements({new Matrix44Element(_mutes, _cvs)});
+ setLocalElements({new Matrix44Element(_mutes, _cvs, &_soloByColumns)});
setBaseModelPredicate([](Model* m) { return m == modelMatrix44; });
}
virtual ~Matrix44Cvm() {
diff --git a/src/Matrix44_shared.hpp b/src/Matrix44_shared.hpp
@@ -14,13 +14,16 @@ typedef ChainableExpanderMessage Matrix44ExpanderMessage;
struct Matrix44Element {
Param** mutes;
Input** cvs;
+ bool* soloByColumns;
Matrix44Element(
Param** mutes,
- Input** cvs
+ Input** cvs,
+ bool* soloByColumns
)
: mutes(mutes)
, cvs(cvs)
+ , soloByColumns(soloByColumns)
{}
};
diff --git a/src/Matrix88.cpp b/src/Matrix88.cpp
@@ -5,6 +5,7 @@ void Matrix88::elementsChanged() {
// base-class caller holds lock on _elements.
Input** cvs = NULL;
Param** mutes = NULL;
+ bool* soloByColumns = NULL;
for (int i = 1, n = std::min(3, (int)_elements.size()); i < n; ++i) {
auto e = _elements[i];
assert(e);
@@ -14,9 +15,13 @@ void Matrix88::elementsChanged() {
if (e->mutes) {
mutes = e->mutes;
}
+ if (e->soloByColumns) {
+ soloByColumns = e->soloByColumns;
+ }
}
setCVInputs(cvs);
setMuteParams(mutes);
+ setSoloByColumns(soloByColumns);
}
void Matrix88::processAlways(const ProcessArgs& args) {
diff --git a/src/Matrix88.hpp b/src/Matrix88.hpp
@@ -167,7 +167,7 @@ struct Matrix88 : Matrix88Base {
configParam(MIX78_PARAM, -1.0f, 1.0f, 0.0f, "Mix 7H", "%", 0.0f, 100.0f);
configParam(MIX88_PARAM, -1.0f, 1.0f, 0.0f, "Mix 8H", "%", 0.0f, 100.0f);
- setLocalElements({new Matrix88Element(NULL, NULL)});
+ setLocalElements({new Matrix88Element(NULL, NULL, NULL)});
registerBase();
setExpanderModelPredicate([](Model* m) { return m == modelMatrix88Cv || m == modelMatrix88M; });
}
diff --git a/src/Matrix88Cv.hpp b/src/Matrix88Cv.hpp
@@ -91,7 +91,7 @@ struct Matrix88Cv : Matrix88CvBase {
for (int i = 0; i < 64; ++i) {
_cvs[i] = &inputs[CV11_INPUT + i];
}
- setLocalElements({new Matrix88Element(NULL, _cvs)});
+ setLocalElements({new Matrix88Element(NULL, _cvs, NULL)});
setBaseModelPredicate([](Model* m) { return m == modelMatrix88 || m == modelMatrix88M; });
setExpanderModelPredicate([](Model* m) { return m == modelMatrix88M; });
}
diff --git a/src/Matrix88M.cpp b/src/Matrix88M.cpp
@@ -19,7 +19,7 @@ void Matrix88M::processAlways(const ProcessArgs& args) {
}
}
-struct Matrix88MWidget : BGModuleWidget {
+struct Matrix88MWidget : MutesMatrixExpanderModuleWidget {
static constexpr int hp = 20;
Matrix88MWidget(Matrix88M* module) {
diff --git a/src/Matrix88M.hpp b/src/Matrix88M.hpp
@@ -4,7 +4,7 @@
namespace bogaudio {
-typedef ChainableExpanderModule<Matrix88ExpanderMessage, Matrix88Element, 1, BGModule> Matrix88MBase;
+typedef ChainableExpanderModule<Matrix88ExpanderMessage, Matrix88Element, 1, MutesMatrixExpanderModule> Matrix88MBase;
struct Matrix88M : Matrix88MBase {
enum ParamsIds {
@@ -163,7 +163,7 @@ struct Matrix88M : Matrix88MBase {
for (int i = 0; i < 64; ++i) {
_mutes[i] = ¶ms[MUTE11_PARAM + i];
}
- setLocalElements({new Matrix88Element(_mutes, NULL)});
+ setLocalElements({new Matrix88Element(_mutes, NULL, &_soloByColumns)});
setBaseModelPredicate([](Model* m) { return m == modelMatrix88 || m == modelMatrix88Cv; });
setExpanderModelPredicate([](Model* m) { return m == modelMatrix88Cv; });
}
diff --git a/src/Matrix88_shared.hpp b/src/Matrix88_shared.hpp
@@ -15,13 +15,16 @@ typedef ChainableExpanderMessage Matrix88ExpanderMessage;
struct Matrix88Element {
Param** mutes;
Input** cvs;
+ bool* soloByColumns;
Matrix88Element(
Param** mutes,
- Input** cvs
+ Input** cvs,
+ bool* soloByColumns
)
: mutes(mutes)
, cvs(cvs)
+ , soloByColumns(soloByColumns)
{}
};
diff --git a/src/matrix_base.cpp b/src/matrix_base.cpp
@@ -71,11 +71,20 @@ void MatrixModule::modulate() {
MatrixBaseModule::modulate();
bool solo = false;
+ bool soloColumn[maxN] {};
if (_muteParams) {
- for (int i = 0, n = _ins * _outs; i < n; ++i) {
- if (_muteParams[i]->getValue() > 1.5f) {
- solo = true;
- break;
+ bool soloByColumns = false;
+ if (_soloByColumns) {
+ soloByColumns = *_soloByColumns;
+ }
+
+ for (int i = 0; i < _outs; ++i) {
+ for (int j = 0; j < _ins; ++j) {
+ if (_muteParams[i * _ins + j]->getValue() > 1.5f) {
+ solo = !soloByColumns;
+ soloColumn[i] = soloByColumns;
+ break;
+ }
}
}
}
@@ -91,7 +100,7 @@ void MatrixModule::modulate() {
int ii = j * _ins + i;
float v = params[_firstParamID + ii].getValue();
if (_muteParams) {
- bool muted = solo ? _muteParams[ii]->getValue() < 2.0f : _muteParams[ii]->getValue() > 0.5f;
+ bool muted = (solo || soloColumn[j]) ? _muteParams[ii]->getValue() < 2.0f : _muteParams[ii]->getValue() > 0.5f;
v *= !muted;
}
_paramValues[ii] = _sls[ii].next(v);
@@ -381,3 +390,25 @@ void SwitchMatrixModuleWidget::contextMenu(Menu* menu) {
menu->addChild(new OptionMenuItem(label.c_str(), [m]() { return m->_rowExclusive; }, [m]() { m->setRowExclusive(!m->_rowExclusive); }));
}
}
+
+
+#define SOLO_BY_COLUMNS "solo_by_columns"
+
+json_t* MutesMatrixExpanderModule::toJson(json_t* root) {
+ json_object_set_new(root, SOLO_BY_COLUMNS, json_boolean(_soloByColumns));
+ return root;
+}
+
+void MutesMatrixExpanderModule::fromJson(json_t* root) {
+ json_t* sbc = json_object_get(root, SOLO_BY_COLUMNS);
+ if (sbc) {
+ _soloByColumns = json_is_true(sbc);
+ }
+}
+
+
+void MutesMatrixExpanderModuleWidget::contextMenu(Menu* menu) {
+ auto m = dynamic_cast<MutesMatrixExpanderModule*>(module);
+ assert(m);
+ menu->addChild(new BoolOptionMenuItem("Solo mutes by column", [m]() { return &m->_soloByColumns; }));
+}
diff --git a/src/matrix_base.hpp b/src/matrix_base.hpp
@@ -35,8 +35,9 @@ struct MatrixModule : MatrixBaseModule {
int _firstParamID = 0;
int _firstInputID = 0;
int _firstOutputID = 0;
- Input** _cvInputs = NULL; // owned elsewhere.
- Param** _muteParams = NULL; // owned elsewhere.
+ Input** _cvInputs = NULL; // owned elsewhere
+ Param** _muteParams = NULL; // owned elsewhere
+ bool* _soloByColumns = NULL; // owned elsewhere
float* _paramValues = NULL;
bogaudio::dsp::SlewLimiter* _sls = NULL;
@@ -58,6 +59,7 @@ struct MatrixModule : MatrixBaseModule {
void configMatrixModule(int ins, int outs, int firstParamID, int firstInputID, int firstOutputID);
inline void setCVInputs(Input** cvs) { _cvInputs = cvs; }
inline void setMuteParams(Param** mutes) { _muteParams = mutes; }
+ inline void setSoloByColumns(bool* sbc) { _soloByColumns = sbc; }
void sampleRateChange() override;
int channels() override;
void modulate() override;
@@ -126,4 +128,15 @@ struct SwitchMatrixModuleWidget : MatrixModuleWidget {
void contextMenu(Menu* menu) override;
};
+struct MutesMatrixExpanderModule : BGModule {
+ bool _soloByColumns = false;
+
+ json_t* toJson(json_t* root) override;
+ void fromJson(json_t* root) override;
+};
+
+struct MutesMatrixExpanderModuleWidget : BGModuleWidget {
+ void contextMenu(Menu* menu) override;
+};
+
} // namespace bogaudio