Browse Source

Add Module::process and Module::ProcessContext.

tags/v1.0.0
Andrew Belt 6 years ago
parent
commit
9c275dd20d
11 changed files with 52 additions and 40 deletions
  1. +9
    -4
      include/dsp/digital.hpp
  2. +7
    -0
      include/engine/Module.hpp
  3. +3
    -4
      src/Core/AudioInterface.cpp
  4. +2
    -2
      src/Core/CV_CC.cpp
  5. +1
    -1
      src/Core/CV_Gate.cpp
  6. +2
    -2
      src/Core/CV_MIDI.cpp
  7. +2
    -4
      src/Core/MIDI_CC.cpp
  8. +11
    -12
      src/Core/MIDI_CV.cpp
  9. +2
    -3
      src/Core/MIDI_Gate.cpp
  10. +2
    -4
      src/Core/MIDI_Map.cpp
  11. +11
    -4
      src/engine/Engine.cpp

+ 9
- 4
include/dsp/digital.hpp View File

@@ -130,9 +130,13 @@ struct Timer {
};


/** Counts the number of `process()` calls.
If `period > 0`, `count` is reset to 0 when that number is reached.
Useful for clock dividing and waiting to fill a fixed buffer.
*/
struct Counter {
int count;
int period;
int period = 0;

Counter() {
reset();
@@ -140,16 +144,17 @@ struct Counter {

void reset() {
count = 0;
period = 1;
}

void setPeriod(int period) {
this->period = period;
reset();
}

/** Returns true if the counter reaches `period` and resets. */
/** Returns true when the counter reaches `period` and resets. */
bool process() {
if (++count >= period) {
count++;
if (count == period) {
count = 0;
return true;
}


+ 7
- 0
include/engine/Module.hpp View File

@@ -38,9 +38,16 @@ struct Module {
void reset();
void randomize();

struct ProcessContext {
float sampleRate;
float sampleTime;
};

/** Advances the module by one audio sample.
Override this method to read Inputs and Params and to write Outputs and Lights.
*/
virtual void process(const ProcessContext &ctx) {}
/** Deprecated. Override process() instead. */
virtual void step() {}

/** Called when the engine sample rate is changed. */


+ 3
- 4
src/Core/AudioInterface.cpp View File

@@ -122,11 +122,10 @@ struct AudioInterface : Module {
onSampleRateChange();
}

void step() override {
void process(const ProcessContext &ctx) override {
// Update SRC states
int sampleRate = (int) APP->engine->getSampleRate();
inputSrc.setRates(port.sampleRate, sampleRate);
outputSrc.setRates(sampleRate, port.sampleRate);
inputSrc.setRates(port.sampleRate, ctx.sampleRate);
outputSrc.setRates(ctx.sampleRate, port.sampleRate);

inputSrc.setChannels(port.numInputs);
outputSrc.setChannels(port.numOutputs);


+ 2
- 2
src/Core/CV_CC.cpp View File

@@ -62,9 +62,9 @@ struct CV_CC : Module {
midiOutput.midi::Output::reset();
}

void step() override {
void process(const ProcessContext &ctx) override {
const float rateLimiterPeriod = 0.010f;
rateLimiterPhase += APP->engine->getSampleTime() / rateLimiterPeriod;
rateLimiterPhase += ctx.sampleTime / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) {
rateLimiterPhase -= 1.f;
}


+ 1
- 1
src/Core/CV_Gate.cpp View File

@@ -89,7 +89,7 @@ struct CV_Gate : Module {
midiOutput.midi::Output::reset();
}

void step() override {
void process(const ProcessContext &ctx) override {
for (int i = 0; i < 16; i++) {
int note = learnedNotes[i];
if (velocityMode) {


+ 2
- 2
src/Core/CV_MIDI.cpp View File

@@ -241,9 +241,9 @@ struct CV_MIDI : Module {
midiOutput.midi::Output::reset();
}

void step() override {
void process(const ProcessContext &ctx) override {
const float rateLimiterPeriod = 0.005f;
rateLimiterPhase += APP->engine->getSampleTime() / rateLimiterPeriod;
rateLimiterPhase += ctx.sampleTime / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) {
rateLimiterPhase -= 1.f;
}


+ 2
- 4
src/Core/MIDI_CC.cpp View File

@@ -42,14 +42,12 @@ struct MIDI_CC : Module {
midiInput.reset();
}

void step() override {
void process(const ProcessContext &ctx) override {
midi::Message msg;
while (midiInput.shift(&msg)) {
processMessage(msg);
}

float deltaTime = APP->engine->getSampleTime();

for (int i = 0; i < 16; i++) {
if (!outputs[CC_OUTPUT + i].isConnected())
continue;
@@ -65,7 +63,7 @@ struct MIDI_CC : Module {
}
else {
// Smooth value with filter
valueFilters[i].process(deltaTime, value);
valueFilters[i].process(ctx.sampleTime, value);
}
lastValues[i] = values[cc];
outputs[CC_OUTPUT + i].setVoltage(valueFilters[i].out);


+ 11
- 12
src/Core/MIDI_CV.cpp View File

@@ -103,12 +103,11 @@ struct MIDI_CV : Module {
heldNotes.clear();
}

void step() override {
void process(const ProcessContext &ctx) override {
midi::Message msg;
while (midiInput.shift(&msg)) {
processMessage(msg);
}
float deltaTime = APP->engine->getSampleTime();

outputs[CV_OUTPUT].setChannels(channels);
outputs[GATE_OUTPUT].setChannels(channels);
@@ -120,29 +119,29 @@ struct MIDI_CV : Module {
outputs[GATE_OUTPUT].setVoltage(gates[c] ? 10.f : 0.f, c);
outputs[VELOCITY_OUTPUT].setVoltage(rescale(velocities[c], 0, 127, 0.f, 10.f), c);
outputs[AFTERTOUCH_OUTPUT].setVoltage(rescale(aftertouches[c], 0, 127, 0.f, 10.f), c);
outputs[RETRIGGER_OUTPUT].setVoltage(retriggerPulses[c].process(deltaTime) ? 10.f : 0.f, c);
outputs[RETRIGGER_OUTPUT].setVoltage(retriggerPulses[c].process(ctx.sampleTime) ? 10.f : 0.f, c);
}

if (polyMode == MPE_MODE) {
for (int c = 0; c < channels; c++) {
outputs[PITCH_OUTPUT].setChannels(channels);
outputs[MOD_OUTPUT].setChannels(channels);
outputs[PITCH_OUTPUT].setVoltage(pitchFilters[c].process(deltaTime, rescale(pitches[c], 0, 1<<14, -5.f, 5.f)), c);
outputs[MOD_OUTPUT].setVoltage(modFilters[c].process(deltaTime, rescale(mods[c], 0, 127, 0.f, 10.f)), c);
outputs[PITCH_OUTPUT].setVoltage(pitchFilters[c].process(ctx.sampleTime, rescale(pitches[c], 0, 1<<14, -5.f, 5.f)), c);
outputs[MOD_OUTPUT].setVoltage(modFilters[c].process(ctx.sampleTime, rescale(mods[c], 0, 127, 0.f, 10.f)), c);
}
}
else {
outputs[PITCH_OUTPUT].setChannels(1);
outputs[MOD_OUTPUT].setChannels(1);
outputs[PITCH_OUTPUT].setVoltage(pitchFilters[0].process(deltaTime, rescale(pitches[0], 0, 1<<14, -5.f, 5.f)));
outputs[MOD_OUTPUT].setVoltage(modFilters[0].process(deltaTime, rescale(mods[0], 0, 127, 0.f, 10.f)));
outputs[PITCH_OUTPUT].setVoltage(pitchFilters[0].process(ctx.sampleTime, rescale(pitches[0], 0, 1<<14, -5.f, 5.f)));
outputs[MOD_OUTPUT].setVoltage(modFilters[0].process(ctx.sampleTime, rescale(mods[0], 0, 127, 0.f, 10.f)));
}

outputs[CLOCK_OUTPUT].setVoltage(clockPulse.process(deltaTime) ? 10.f : 0.f);
outputs[CLOCK_DIV_OUTPUT].setVoltage(clockDividerPulse.process(deltaTime) ? 10.f : 0.f);
outputs[START_OUTPUT].setVoltage(startPulse.process(deltaTime) ? 10.f : 0.f);
outputs[STOP_OUTPUT].setVoltage(stopPulse.process(deltaTime) ? 10.f : 0.f);
outputs[CONTINUE_OUTPUT].setVoltage(continuePulse.process(deltaTime) ? 10.f : 0.f);
outputs[CLOCK_OUTPUT].setVoltage(clockPulse.process(ctx.sampleTime) ? 10.f : 0.f);
outputs[CLOCK_DIV_OUTPUT].setVoltage(clockDividerPulse.process(ctx.sampleTime) ? 10.f : 0.f);
outputs[START_OUTPUT].setVoltage(startPulse.process(ctx.sampleTime) ? 10.f : 0.f);
outputs[STOP_OUTPUT].setVoltage(stopPulse.process(ctx.sampleTime) ? 10.f : 0.f);
outputs[CONTINUE_OUTPUT].setVoltage(continuePulse.process(ctx.sampleTime) ? 10.f : 0.f);
}

void processMessage(midi::Message msg) {


+ 2
- 3
src/Core/MIDI_Gate.cpp View File

@@ -46,12 +46,11 @@ struct MIDI_Gate : Module {
}
}

void step() override {
void process(const ProcessContext &ctx) override {
midi::Message msg;
while (midiInput.shift(&msg)) {
processMessage(msg);
}
float deltaTime = APP->engine->getSampleTime();

for (int i = 0; i < 16; i++) {
if (gateTimes[i] > 0.f) {
@@ -59,7 +58,7 @@ struct MIDI_Gate : Module {
// If the gate is off, wait 1 ms before turning the pulse off.
// This avoids drum controllers sending a pulse with 0 ms duration.
if (!gates[i]) {
gateTimes[i] -= deltaTime;
gateTimes[i] -= ctx.sampleTime;
}
}
else {


+ 2
- 4
src/Core/MIDI_Map.cpp View File

@@ -65,14 +65,12 @@ struct MIDI_Map : Module {
midiInput.reset();
}

void step() override {
void process(const ProcessContext &ctx) override {
midi::Message msg;
while (midiInput.shift(&msg)) {
processMessage(msg);
}

float deltaTime = APP->engine->getSampleTime();

// Step channels
for (int id = 0; id < mapLen; id++) {
int cc = ccs[id];
@@ -92,7 +90,7 @@ struct MIDI_Map : Module {
continue;
// Set param
float v = rescale(values[cc], 0, 127, 0.f, 1.f);
v = valueFilters[id].process(deltaTime, v);
v = valueFilters[id].process(ctx.sampleTime, v);
v = rescale(v, 0.f, 1.f, param->minValue, param->maxValue);
APP->engine->setParam(module, paramId, v);
}


+ 11
- 4
src/engine/Engine.cpp View File

@@ -190,7 +190,11 @@ static void Engine_stepModules(Engine *engine, int threadId) {

// int threadCount = internal->threadCount;
int modulesLen = internal->modules.size();
float deltaTime = internal->sampleTime;
float sampleTime = internal->sampleTime;

Module::ProcessContext processCtx;
processCtx.sampleRate = internal->sampleRate;
processCtx.sampleTime = internal->sampleTime;

// Step each module
// for (int i = threadId; i < modulesLen; i += threadCount) {
@@ -206,25 +210,28 @@ static void Engine_stepModules(Engine *engine, int threadId) {
if (settings.cpuMeter) {
auto startTime = std::chrono::high_resolution_clock::now();

module->process(processCtx);
module->step();

auto stopTime = std::chrono::high_resolution_clock::now();
float cpuTime = std::chrono::duration<float>(stopTime - startTime).count();
// Smooth CPU time
const float cpuTau = 2.f /* seconds */;
module->cpuTime += (cpuTime - module->cpuTime) * deltaTime / cpuTau;
module->cpuTime += (cpuTime - module->cpuTime) * sampleTime / cpuTau;
}
else {
module->process(processCtx);
// Call deprecated method
module->step();
}
}

// Iterate ports to step plug lights
for (Input &input : module->inputs) {
input.process(deltaTime);
input.process(sampleTime);
}
for (Output &output : module->outputs) {
output.process(deltaTime);
output.process(sampleTime);
}
}
}


Loading…
Cancel
Save