Browse Source

Gates: Refactor Delay buffer. Only process Delay if output is patched.

tags/v2.3.0
Andrew Belt 2 years ago
parent
commit
c8ded5ea10
1 changed files with 37 additions and 45 deletions
  1. +37
    -45
      src/Gates.cpp

+ 37
- 45
src/Gates.cpp View File

@@ -37,15 +37,6 @@ struct Gates : Module {
dsp::BooleanTrigger resetParamTrigger; dsp::BooleanTrigger resetParamTrigger;
dsp::ClockDivider lightDivider; dsp::ClockDivider lightDivider;


struct StateEvent {
double time;
bool state;

bool operator<(const StateEvent& other) const {
return time < other.time;
}
};

struct Engine { struct Engine {
bool state = false; bool state = false;
dsp::SchmittTrigger resetTrigger; dsp::SchmittTrigger resetTrigger;
@@ -53,8 +44,8 @@ struct Gates : Module {
dsp::PulseGenerator fallPulse; dsp::PulseGenerator fallPulse;
bool flop = false; bool flop = false;
float gateTime = INFINITY; float gateTime = INFINITY;
// TODO Change this to a circular buffer with binary search, to avoid allocations.
std::set<StateEvent> stateEvents;
// TODO Change this to a circular buffer with binary search, to avoid allocations when events are pushed.
std::map<double, bool> stateEvents;
}; };
Engine engines[16]; Engine engines[16];


@@ -128,38 +119,6 @@ struct Gates : Module {
e.stateEvents.clear(); 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 // Outputs
bool rise = e.risePulse.process(args.sampleTime); bool rise = e.risePulse.process(args.sampleTime);
outputs[RISE_OUTPUT].setVoltage(rise ? 10.f : 0.f, c); 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); outputs[FLOP_OUTPUT].setVoltage(e.flop ? 10.f : 0.f, c);
anyFlop = anyFlop || e.flop; 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); bool gate = std::isfinite(e.gateTime);
outputs[GATE_OUTPUT].setVoltage(gate ? 10.f : 0.f, c); outputs[GATE_OUTPUT].setVoltage(gate ? 10.f : 0.f, c);
anyGate = anyGate || gate; 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; time += args.sampleTime;


Loading…
Cancel
Save