@@ -130,5 +130,29 @@ struct Timer { | |||||
}; | }; | ||||
struct Counter { | |||||
int count; | |||||
int period; | |||||
Counter() { | |||||
reset(); | |||||
} | |||||
void reset() { | |||||
count = 0; | |||||
period = 1; | |||||
} | |||||
/** Returns true if the counter reaches `period` and resets. */ | |||||
bool process() { | |||||
if (++count >= period) { | |||||
count = 0; | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
}; | |||||
} // namespace dsp | } // namespace dsp | ||||
} // namespace rack | } // namespace rack |
@@ -6,8 +6,8 @@ namespace rack { | |||||
namespace dsp { | namespace dsp { | ||||
/** Deprecated. Use VUMeter2. */ | |||||
struct VUMeter { | |||||
/** Deprecated. Use VuMeter2. */ | |||||
struct VuMeter { | |||||
/** Decibel level difference between adjacent meter lights */ | /** Decibel level difference between adjacent meter lights */ | ||||
float dBInterval = 3.0; | float dBInterval = 3.0; | ||||
float dBScaled; | float dBScaled; | ||||
@@ -30,7 +30,10 @@ struct VUMeter { | |||||
}; | }; | ||||
struct VUMeter2 { | |||||
DEPRECATED typedef VuMeter VUMeter; | |||||
struct VuMeter2 { | |||||
enum Mode { | enum Mode { | ||||
PEAK, | PEAK, | ||||
RMS | RMS | ||||
@@ -7,12 +7,12 @@ namespace engine { | |||||
struct Light { | struct Light { | ||||
/** The mean-square of the brightness. | |||||
/** The square of the brightness. | |||||
Unstable API. Use set/getBrightness(). | Unstable API. Use set/getBrightness(). | ||||
*/ | */ | ||||
float value = 0.f; | float value = 0.f; | ||||
/** Sets the brightness directly with no LED modeling. */ | |||||
/** Sets the brightness immediately with no light decay. */ | |||||
void setBrightness(float brightness) { | void setBrightness(float brightness) { | ||||
value = (brightness > 0.f) ? std::pow(brightness, 2) : 0.f; | value = (brightness > 0.f) ? std::pow(brightness, 2) : 0.f; | ||||
} | } | ||||
@@ -21,23 +21,24 @@ struct Light { | |||||
return std::sqrt(value); | return std::sqrt(value); | ||||
} | } | ||||
/** Emulates slow fall (but immediate rise) of LED brightness. | |||||
`frames` rescales the timestep. | |||||
For example, if your module calls this method every 16 frames, use 16.f. | |||||
*/ | |||||
void setBrightnessSmooth(float brightness, float frames = 1.f) { | |||||
/** Emulates light decay with slow fall but immediate rise. */ | |||||
void setSmoothBrightness(float brightness, float deltaTime) { | |||||
float v = (brightness > 0.f) ? std::pow(brightness, 2) : 0.f; | float v = (brightness > 0.f) ? std::pow(brightness, 2) : 0.f; | ||||
if (v < value) { | if (v < value) { | ||||
// Fade out light with lambda = framerate | |||||
// Use 44.1k here to avoid the call to Engine::getSampleRate(). | |||||
// This is close enough to look okay up to 96k | |||||
value += (v - value) * frames * 30.f / 44100.f; | |||||
// Fade out light | |||||
const float lambda = 30.f; | |||||
value += (v - value) * lambda * deltaTime; | |||||
} | } | ||||
else { | else { | ||||
// Immediately illuminate light | // Immediately illuminate light | ||||
value = v; | value = v; | ||||
} | } | ||||
} | } | ||||
/** Use `setSmoothBrightness(brightness, APP->engine->getSampleTime())` instead. */ | |||||
DEPRECATED void setBrightnessSmooth(float brightness, float frames = 1.f) { | |||||
setSmoothBrightness(brightness, frames / 44100.f); | |||||
} | |||||
}; | }; | ||||
@@ -75,7 +75,7 @@ struct Port { | |||||
return active; | return active; | ||||
} | } | ||||
void step(); | |||||
void process(float deltaTime); | |||||
/** Use getNormalVoltage() instead. */ | /** Use getNormalVoltage() instead. */ | ||||
DEPRECATED float normalize(float normalVoltage) { | DEPRECATED float normalize(float normalVoltage) { | ||||
@@ -190,6 +190,7 @@ 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; | |||||
// Step each module | // Step each module | ||||
// for (int i = threadId; i < modulesLen; i += threadCount) { | // for (int i = threadId; i < modulesLen; i += threadCount) { | ||||
@@ -211,7 +212,7 @@ static void Engine_stepModules(Engine *engine, int threadId) { | |||||
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) * internal->sampleTime / cpuTau; | |||||
module->cpuTime += (cpuTime - module->cpuTime) * deltaTime / cpuTau; | |||||
} | } | ||||
else { | else { | ||||
module->step(); | module->step(); | ||||
@@ -220,10 +221,10 @@ static void Engine_stepModules(Engine *engine, int threadId) { | |||||
// Iterate ports to step plug lights | // Iterate ports to step plug lights | ||||
for (Input &input : module->inputs) { | for (Input &input : module->inputs) { | ||||
input.step(); | |||||
input.process(deltaTime); | |||||
} | } | ||||
for (Output &output : module->outputs) { | for (Output &output : module->outputs) { | ||||
output.step(); | |||||
output.process(deltaTime); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -5,7 +5,7 @@ namespace rack { | |||||
namespace engine { | namespace engine { | ||||
void Port::step() { | |||||
void Port::process(float deltaTime) { | |||||
// Set plug lights | // Set plug lights | ||||
if (!isConnected() || getChannels() == 0) { | if (!isConnected() || getChannels() == 0) { | ||||
plugLights[0].setBrightness(0.f); | plugLights[0].setBrightness(0.f); | ||||
@@ -14,8 +14,8 @@ void Port::step() { | |||||
} | } | ||||
else if (getChannels() == 1) { | else if (getChannels() == 1) { | ||||
float v = getVoltage() / 10.f; | float v = getVoltage() / 10.f; | ||||
plugLights[0].setBrightnessSmooth(v); | |||||
plugLights[1].setBrightnessSmooth(-v); | |||||
plugLights[0].setSmoothBrightness(v, deltaTime); | |||||
plugLights[1].setSmoothBrightness(-v, deltaTime); | |||||
plugLights[2].setBrightness(0.f); | plugLights[2].setBrightness(0.f); | ||||
} | } | ||||
else { | else { | ||||
@@ -26,7 +26,7 @@ void Port::step() { | |||||
float v = std::sqrt(v2) / 10.f; | float v = std::sqrt(v2) / 10.f; | ||||
plugLights[0].setBrightness(0.f); | plugLights[0].setBrightness(0.f); | ||||
plugLights[1].setBrightness(0.f); | plugLights[1].setBrightness(0.f); | ||||
plugLights[2].setBrightnessSmooth(v); | |||||
plugLights[2].setSmoothBrightness(v, deltaTime); | |||||
} | } | ||||
} | } | ||||