Set the fader values as [0.1, 0, 0.2, 0, 0.3, 0, 0.4, 0] from left to right
I chose 0 at even-numbered steps, so I thought no gates would occur at it, but a short trigger occurred. I don’t have a hardware, so I can’t tell it is intended or not. I put an image which I hope to explain this situation.
Nice bug report thanks! I’ll take a look. My worry is that it’s due to the one sample delay introduced by cables, and that produces one sample trigger (from the previous step’s COM IO).
The below (truncated) patch technically works as a possible fix but is unfortunately too slow. At least confirms the 1-sample delay theory. Does anyone know a more efficient way to detect if the current module is self patched (i.e. without iterating over all cables)?
I also initially tried a hook in draw doing something like APP->scene->rack->getCompleteCablesOnPort(this->getInput(Muxlicer::GATE_MODE_INPUT)); etc but that seems wrong (e.g. it wouldn’t work in headless).
diff --git a/src/Muxlicer.cpp b/src/Muxlicer.cpp
index 8f24a0e..2ae079e 100644
--- a/src/Muxlicer.cpp
+++ b/src/Muxlicer.cpp
// there is an option to stop output clock when play stops
const bool playStateMask = !outputClockFollowsPlayMode || (playState != STATE_STOPPED);
// NOTE: outputClockOut can also be read by expanders
@@ -611,6 +611,31 @@ struct Muxlicer : Module {
}
}
+ bool isCOMIOSelfPatchedToGateInput() {
+ // if either is not connected then we're not self patched
+ if (!inputs[GATE_MODE_INPUT].isConnected() || !outputs[COM_OUTPUT].isConnected()) {
+ return false;
+ }
+
+ // loop over all cables
+ for (int64_t cableId : APP->engine->getCableIds()) {
+
+ // if _this_ muxlicer has a self patching cable
+ const bool selfPatchedCurrentModule = (APP->engine->getCable(cableId)->inputModule->id == this->id &&
+ APP->engine->getCable(cableId)->outputModule->id == this->id);
+ if (selfPatchedCurrentModule) {
+ // and that self patch is COM IO -> Gate Input
+ const bool comIOToGateInput = (APP->engine->getCable(cableId)->inputId == GATE_MODE_INPUT &&
+ APP->engine->getCable(cableId)->outputId == COM_OUTPUT);
+
+ if (comIOToGateInput) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
// determines how many gates to yield per step
int getGateMode() {
@@ -618,9 +643,12 @@ struct Muxlicer : Module {
int gate;
if (inputs[GATE_MODE_INPUT].isConnected()) {
+
+ float cvIn = isCOMIOSelfPatchedToGateInput() ? outputs[COM_OUTPUT].getVoltage() : inputs[GATE_MODE_INPUT].getVoltage();
+
// with gate acting as attenuator, hardware reacts in 1V increments,
// where x V -> (x + 1) V yields (x - 1) gates in that time
- float gateCV = clamp(inputs[GATE_MODE_INPUT].getVoltage(), 0.f, 10.f);
+ float gateCV = clamp(cvIn, 0.f, 10.f);
float knobAttenuation = rescale(params[GATE_MODE_PARAM].getValue(), -1.f, 8.f, 0.f, 1.f);
gate = int (floor(gateCV * knobAttenuation)) - 1;