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 { struct Counter {
int count; int count;
int period;
int period = 0;


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


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


void setPeriod(int period) { void setPeriod(int period) {
this->period = 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() { bool process() {
if (++count >= period) {
count++;
if (count == period) {
count = 0; count = 0;
return true; return true;
} }


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

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


struct ProcessContext {
float sampleRate;
float sampleTime;
};

/** Advances the module by one audio sample. /** Advances the module by one audio sample.
Override this method to read Inputs and Params and to write Outputs and Lights. 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() {} virtual void step() {}


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


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

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


void step() override {
void process(const ProcessContext &ctx) override {
// Update SRC states // 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); inputSrc.setChannels(port.numInputs);
outputSrc.setChannels(port.numOutputs); 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(); midiOutput.midi::Output::reset();
} }


void step() override {
void process(const ProcessContext &ctx) override {
const float rateLimiterPeriod = 0.010f; const float rateLimiterPeriod = 0.010f;
rateLimiterPhase += APP->engine->getSampleTime() / rateLimiterPeriod;
rateLimiterPhase += ctx.sampleTime / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) { if (rateLimiterPhase >= 1.f) {
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(); midiOutput.midi::Output::reset();
} }


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


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

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


void step() override {
void process(const ProcessContext &ctx) override {
const float rateLimiterPeriod = 0.005f; const float rateLimiterPeriod = 0.005f;
rateLimiterPhase += APP->engine->getSampleTime() / rateLimiterPeriod;
rateLimiterPhase += ctx.sampleTime / rateLimiterPeriod;
if (rateLimiterPhase >= 1.f) { if (rateLimiterPhase >= 1.f) {
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(); midiInput.reset();
} }


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


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

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


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


outputs[CV_OUTPUT].setChannels(channels); outputs[CV_OUTPUT].setChannels(channels);
outputs[GATE_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[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[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[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) { if (polyMode == MPE_MODE) {
for (int c = 0; c < channels; c++) { for (int c = 0; c < channels; c++) {
outputs[PITCH_OUTPUT].setChannels(channels); outputs[PITCH_OUTPUT].setChannels(channels);
outputs[MOD_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 { else {
outputs[PITCH_OUTPUT].setChannels(1); outputs[PITCH_OUTPUT].setChannels(1);
outputs[MOD_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) { 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; midi::Message msg;
while (midiInput.shift(&msg)) { while (midiInput.shift(&msg)) {
processMessage(msg); processMessage(msg);
} }
float deltaTime = APP->engine->getSampleTime();


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


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

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


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


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

// Step channels // Step channels
for (int id = 0; id < mapLen; id++) { for (int id = 0; id < mapLen; id++) {
int cc = ccs[id]; int cc = ccs[id];
@@ -92,7 +90,7 @@ struct MIDI_Map : Module {
continue; continue;
// Set param // Set param
float v = rescale(values[cc], 0, 127, 0.f, 1.f); 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); v = rescale(v, 0.f, 1.f, param->minValue, param->maxValue);
APP->engine->setParam(module, paramId, v); 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 threadCount = internal->threadCount;
int modulesLen = internal->modules.size(); 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 // Step each module
// for (int i = threadId; i < modulesLen; i += threadCount) { // for (int i = threadId; i < modulesLen; i += threadCount) {
@@ -206,25 +210,28 @@ static void Engine_stepModules(Engine *engine, int threadId) {
if (settings.cpuMeter) { if (settings.cpuMeter) {
auto startTime = std::chrono::high_resolution_clock::now(); auto startTime = std::chrono::high_resolution_clock::now();


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


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


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


Loading…
Cancel
Save