diff --git a/src/Gates.cpp b/src/Gates.cpp index c916c8e..e1a5753 100644 --- a/src/Gates.cpp +++ b/src/Gates.cpp @@ -37,15 +37,6 @@ struct Gates : Module { dsp::BooleanTrigger resetParamTrigger; dsp::ClockDivider lightDivider; - struct StateEvent { - double time; - bool state; - - bool operator<(const StateEvent& other) const { - return time < other.time; - } - }; - struct Engine { bool state = false; dsp::SchmittTrigger resetTrigger; @@ -53,8 +44,8 @@ struct Gates : Module { dsp::PulseGenerator fallPulse; bool flop = false; float gateTime = INFINITY; - // TODO Change this to a circular buffer with binary search, to avoid allocations. - std::set stateEvents; + // TODO Change this to a circular buffer with binary search, to avoid allocations when events are pushed. + std::map stateEvents; }; Engine engines[16]; @@ -128,38 +119,6 @@ struct Gates : Module { e.stateEvents.clear(); } - // Gate - float gatePitch = params[LENGTH_PARAM].getValue() + inputs[LENGTH_INPUT].getPolyVoltage(c); - float gateLength = dsp::approxExp2_taylor5(gatePitch + 30.f) / 1073741824; - if (std::isfinite(e.gateTime)) { - e.gateTime += args.sampleTime; - if (reset || e.gateTime >= gateLength) { - e.gateTime = INFINITY; - } - } - - // Gate delay output - bool delayGate = false; - // Timestamp of past gate - double delayTime = time - gateLength; - // Find event less than or equal to delayTime. - // If not found, gate will be off. - auto eventIt = e.stateEvents.upper_bound({delayTime, false}); - if (eventIt != e.stateEvents.begin()) { - eventIt--; - const StateEvent& event = *eventIt; - delayGate = event.state; - } - - if (newState) { - // Keep buffer a reasonable size - if (e.stateEvents.size() >= (1 << 12) - 1) { - e.stateEvents.erase(e.stateEvents.begin()); - } - // Insert current state at current time - e.stateEvents.insert({time, e.state}); - } - // Outputs bool rise = e.risePulse.process(args.sampleTime); outputs[RISE_OUTPUT].setVoltage(rise ? 10.f : 0.f, c); @@ -175,12 +134,45 @@ struct Gates : Module { outputs[FLOP_OUTPUT].setVoltage(e.flop ? 10.f : 0.f, c); anyFlop = anyFlop || e.flop; + // Gate output + float gatePitch = params[LENGTH_PARAM].getValue() + inputs[LENGTH_INPUT].getPolyVoltage(c); + float gateLength = dsp::approxExp2_taylor5(gatePitch + 30.f) / 1073741824; + if (std::isfinite(e.gateTime)) { + e.gateTime += args.sampleTime; + if (reset || e.gateTime >= gateLength) { + e.gateTime = INFINITY; + } + } + bool gate = std::isfinite(e.gateTime); outputs[GATE_OUTPUT].setVoltage(gate ? 10.f : 0.f, c); anyGate = anyGate || gate; - outputs[DELAY_OUTPUT].setVoltage(delayGate ? 10.f : 0.f, c); - anyDelay = anyDelay || delayGate; + // Gate delay output + if (outputs[DELAY_OUTPUT].isConnected()) { + bool delayGate = false; + // Timestamp of past gate + double delayTime = time - gateLength; + // Find event less than or equal to delayTime. + // If not found, gate will be off. + auto eventIt = e.stateEvents.upper_bound(delayTime); + if (eventIt != e.stateEvents.begin()) { + eventIt--; + delayGate = eventIt->second; + } + + if (newState) { + // Keep buffer a reasonable size + if (e.stateEvents.size() >= (1 << 10) - 1) { + e.stateEvents.erase(e.stateEvents.begin()); + } + // Insert current state at current time + e.stateEvents[time] = e.state; + } + + outputs[DELAY_OUTPUT].setVoltage(delayGate ? 10.f : 0.f, c); + anyDelay = anyDelay || delayGate; + } } time += args.sampleTime;