@@ -22,5 +22,5 @@ void init(rack::Plugin *p) { | |||||
createModel<BranchesWidget>(plugin, "Branches", "Bernoulli Gate"); | createModel<BranchesWidget>(plugin, "Branches", "Bernoulli Gate"); | ||||
createModel<BlindsWidget>(plugin, "Blinds", "Quad VC-polarizer"); | createModel<BlindsWidget>(plugin, "Blinds", "Quad VC-polarizer"); | ||||
createModel<VeilsWidget>(plugin, "Veils", "Quad VCA"); | createModel<VeilsWidget>(plugin, "Veils", "Quad VCA"); | ||||
createModel<FramesWidget>(plugin, "Frames", "Keyframer"); | |||||
// createModel<FramesWidget>(plugin, "Frames", "Keyframer"); | |||||
} | } |
@@ -36,50 +36,44 @@ struct Blinds : Module { | |||||
float lights[4] = {}; | float lights[4] = {}; | ||||
float gainLights[4] = {}; | float gainLights[4] = {}; | ||||
Blinds(); | |||||
Blinds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Blinds::Blinds() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
static float getChannelOutput(const float *in, float gain, const float *cv, float mod, float *light) { | |||||
gain += mod * fmaxf(getf(cv) / 5.0, 0.0); | |||||
*light = gain * 5.0; | |||||
return gain * getf(in, 5.0); | |||||
static float processChannel(Input &in, Param &gain, Input &cv, Param &mod, float *light) { | |||||
float g = gain.value + mod.value * cv.value / 5.0; | |||||
*light = g * 5.0; | |||||
return g * in.normalize(5.0); | |||||
} | } | ||||
void Blinds::step() { | void Blinds::step() { | ||||
float out = 0.0; | float out = 0.0; | ||||
out += getChannelOutput(inputs[IN1_INPUT], params[GAIN1_PARAM], inputs[CV1_INPUT], params[MOD1_PARAM], &gainLights[0]); | |||||
out += processChannel(inputs[IN1_INPUT], params[GAIN1_PARAM], inputs[CV1_INPUT], params[MOD1_PARAM], &gainLights[0]); | |||||
lights[0] = out; | lights[0] = out; | ||||
if (outputs[OUT1_OUTPUT]) { | |||||
*outputs[OUT1_OUTPUT] = out; | |||||
if (outputs[OUT1_OUTPUT].active) { | |||||
outputs[OUT1_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN2_INPUT], params[GAIN2_PARAM], inputs[CV2_INPUT], params[MOD2_PARAM], &gainLights[1]); | |||||
out += processChannel(inputs[IN2_INPUT], params[GAIN2_PARAM], inputs[CV2_INPUT], params[MOD2_PARAM], &gainLights[1]); | |||||
lights[1] = out; | lights[1] = out; | ||||
if (outputs[OUT2_OUTPUT]) { | |||||
*outputs[OUT2_OUTPUT] = out; | |||||
if (outputs[OUT2_OUTPUT].active) { | |||||
outputs[OUT2_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN3_INPUT], params[GAIN3_PARAM], inputs[CV3_INPUT], params[MOD3_PARAM], &gainLights[2]); | |||||
out += processChannel(inputs[IN3_INPUT], params[GAIN3_PARAM], inputs[CV3_INPUT], params[MOD3_PARAM], &gainLights[2]); | |||||
lights[2] = out; | lights[2] = out; | ||||
if (outputs[OUT3_OUTPUT]) { | |||||
*outputs[OUT3_OUTPUT] = out; | |||||
if (outputs[OUT3_OUTPUT].active) { | |||||
outputs[OUT3_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN4_INPUT], params[GAIN4_PARAM], inputs[CV4_INPUT], params[MOD4_PARAM], &gainLights[3]); | |||||
out += processChannel(inputs[IN4_INPUT], params[GAIN4_PARAM], inputs[CV4_INPUT], params[MOD4_PARAM], &gainLights[3]); | |||||
lights[3] = out; | lights[3] = out; | ||||
if (outputs[OUT4_OUTPUT]) { | |||||
*outputs[OUT4_OUTPUT] = out; | |||||
if (outputs[OUT4_OUTPUT].active) { | |||||
outputs[OUT4_OUTPUT].value = out; | |||||
} | } | ||||
} | } | ||||
@@ -69,11 +69,7 @@ struct Braids : Module { | |||||
}; | }; | ||||
Braids::Braids() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Braids::Braids() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&osc, 0, sizeof(osc)); | memset(&osc, 0, sizeof(osc)); | ||||
osc.Init(); | osc.Init(); | ||||
memset(&jitter_source, 0, sizeof(jitter_source)); | memset(&jitter_source, 0, sizeof(jitter_source)); | ||||
@@ -90,7 +86,7 @@ Braids::Braids() { | |||||
void Braids::step() { | void Braids::step() { | ||||
// Trigger | // Trigger | ||||
bool trig = getf(inputs[TRIG_INPUT]) >= 1.0; | |||||
bool trig = inputs[TRIG_INPUT].value >= 1.0; | |||||
if (!lastTrig && trig) { | if (!lastTrig && trig) { | ||||
osc.Strike(); | osc.Strike(); | ||||
} | } | ||||
@@ -98,10 +94,10 @@ void Braids::step() { | |||||
// Render frames | // Render frames | ||||
if (outputBuffer.empty()) { | if (outputBuffer.empty()) { | ||||
float fm = params[FM_PARAM] * getf(inputs[FM_INPUT]); | |||||
float fm = params[FM_PARAM].value * inputs[FM_INPUT].value; | |||||
// Set shape | // Set shape | ||||
int shape = roundf(params[SHAPE_PARAM] * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||||
int shape = roundf(params[SHAPE_PARAM].value * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||||
if (settings.meta_modulation) { | if (settings.meta_modulation) { | ||||
shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | ||||
} | } | ||||
@@ -111,14 +107,14 @@ void Braids::step() { | |||||
osc.set_shape((braids::MacroOscillatorShape) settings.shape); | osc.set_shape((braids::MacroOscillatorShape) settings.shape); | ||||
// Set timbre/modulation | // Set timbre/modulation | ||||
float timbre = params[TIMBRE_PARAM] + params[MODULATION_PARAM] * getf(inputs[TIMBRE_INPUT]) / 5.0; | |||||
float modulation = params[COLOR_PARAM] + getf(inputs[COLOR_INPUT]) / 5.0; | |||||
float timbre = params[TIMBRE_PARAM].value + params[MODULATION_PARAM].value * inputs[TIMBRE_INPUT].value / 5.0; | |||||
float modulation = params[COLOR_PARAM].value + inputs[COLOR_INPUT].value / 5.0; | |||||
int16_t param1 = rescalef(clampf(timbre, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX); | int16_t param1 = rescalef(clampf(timbre, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX); | ||||
int16_t param2 = rescalef(clampf(modulation, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX); | int16_t param2 = rescalef(clampf(modulation, 0.0, 1.0), 0.0, 1.0, 0, INT16_MAX); | ||||
osc.set_parameters(param1, param2); | osc.set_parameters(param1, param2); | ||||
// Set pitch | // Set pitch | ||||
float pitchV = getf(inputs[PITCH_INPUT]) + params[COARSE_PARAM] + params[FINE_PARAM] / 12.0; | |||||
float pitchV = inputs[PITCH_INPUT].value + params[COARSE_PARAM].value + params[FINE_PARAM].value / 12.0; | |||||
if (!settings.meta_modulation) | if (!settings.meta_modulation) | ||||
pitchV += fm; | pitchV += fm; | ||||
int32_t pitch = (pitchV * 12.0 + 60) * 128; | int32_t pitch = (pitchV * 12.0 + 60) * 128; | ||||
@@ -157,7 +153,7 @@ void Braids::step() { | |||||
// Output | // Output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<1> f = outputBuffer.shift(); | Frame<1> f = outputBuffer.shift(); | ||||
setf(outputs[OUT_OUTPUT], 5.0 * f.samples[0]); | |||||
outputs[OUT_OUTPUT].value = 5.0 * f.samples[0]; | |||||
} | } | ||||
} | } | ||||
@@ -28,26 +28,20 @@ struct Branches : Module { | |||||
bool outcome[2] = {}; | bool outcome[2] = {}; | ||||
float light[2] = {}; | float light[2] = {}; | ||||
Branches(); | |||||
Branches() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
float getOutput(int outputId); | float getOutput(int outputId); | ||||
}; | }; | ||||
Branches::Branches() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
static void computeChannel(const float *in, const float *p, float threshold, float mode, bool *lastGate, bool *outcome, float *out1, float *out2, float *light) { | |||||
float out = getf(in); | |||||
static void processChannel(Input &in, Input &p, Param &threshold, Param &mode, bool *lastGate, bool *outcome, Output &out1, Output &out2, float *light) { | |||||
float out = in.value; | |||||
bool gate = (out >= 1.0); | bool gate = (out >= 1.0); | ||||
if (gate && !*lastGate) { | if (gate && !*lastGate) { | ||||
// trigger | // trigger | ||||
float r = randomf(); | float r = randomf(); | ||||
bool toss = (r < threshold + getf(p)); | |||||
if (mode < 0.5) { | |||||
bool toss = (r < threshold.value + p.value); | |||||
if (mode.value < 0.5) { | |||||
// direct mode | // direct mode | ||||
*outcome = toss; | *outcome = toss; | ||||
} | } | ||||
@@ -59,17 +53,13 @@ static void computeChannel(const float *in, const float *p, float threshold, flo | |||||
*lastGate = gate; | *lastGate = gate; | ||||
*light = *outcome ? out : -out; | *light = *outcome ? out : -out; | ||||
if (out1) { | |||||
*out1 = *outcome ? 0.0 : out; | |||||
} | |||||
if (out2) { | |||||
*out2 = *outcome ? out : 0.0; | |||||
} | |||||
out1.value = *outcome ? 0.0 : out; | |||||
out2.value = *outcome ? out : 0.0; | |||||
} | } | ||||
void Branches::step() { | void Branches::step() { | ||||
computeChannel(inputs[IN1_INPUT], inputs[P1_INPUT], params[THRESHOLD1_PARAM], params[MODE1_PARAM], &lastGate[0], &outcome[0], outputs[OUT1A_OUTPUT], outputs[OUT1B_OUTPUT], &light[0]); | |||||
computeChannel(inputs[IN2_INPUT] ? inputs[IN2_INPUT] : inputs[IN1_INPUT], inputs[P2_INPUT], params[THRESHOLD2_PARAM], params[MODE2_PARAM], &lastGate[1], &outcome[1], outputs[OUT2A_OUTPUT], outputs[OUT2B_OUTPUT], &light[1]); | |||||
processChannel(inputs[IN1_INPUT], inputs[P1_INPUT], params[THRESHOLD1_PARAM], params[MODE1_PARAM], &lastGate[0], &outcome[0], outputs[OUT1A_OUTPUT], outputs[OUT1B_OUTPUT], &light[0]); | |||||
processChannel(inputs[IN2_INPUT].active ? inputs[IN2_INPUT] : inputs[IN1_INPUT], inputs[P2_INPUT], params[THRESHOLD2_PARAM], params[MODE2_PARAM], &lastGate[1], &outcome[1], outputs[OUT2A_OUTPUT], outputs[OUT2B_OUTPUT], &light[1]); | |||||
} | } | ||||
@@ -51,11 +51,7 @@ struct Clouds : Module { | |||||
}; | }; | ||||
Clouds::Clouds() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Clouds::Clouds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
const int memLen = 118784; | const int memLen = 118784; | ||||
const int ccmLen = 65536 - 128; | const int ccmLen = 65536 - 128; | ||||
block_mem = new uint8_t[memLen](); | block_mem = new uint8_t[memLen](); | ||||
@@ -76,13 +72,13 @@ void Clouds::step() { | |||||
// Get input | // Get input | ||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
Frame<2> inputFrame; | Frame<2> inputFrame; | ||||
inputFrame.samples[0] = getf(inputs[IN_L_INPUT]) * params[IN_GAIN_PARAM] / 5.0; | |||||
inputFrame.samples[1] = inputs[IN_R_INPUT] ? getf(inputs[IN_R_INPUT]) * params[IN_GAIN_PARAM] / 5.0 : inputFrame.samples[0]; | |||||
inputFrame.samples[0] = inputs[IN_L_INPUT].value * params[IN_GAIN_PARAM].value / 5.0; | |||||
inputFrame.samples[1] = inputs[IN_R_INPUT].active ? inputs[IN_R_INPUT].value * params[IN_GAIN_PARAM].value / 5.0 : inputFrame.samples[0]; | |||||
inputBuffer.push(inputFrame); | inputBuffer.push(inputFrame); | ||||
} | } | ||||
// Trigger | // Trigger | ||||
if (getf(inputs[TRIG_INPUT]) >= 1.0) { | |||||
if (inputs[TRIG_INPUT].value >= 1.0) { | |||||
triggered = true; | triggered = true; | ||||
} | } | ||||
@@ -115,13 +111,13 @@ void Clouds::step() { | |||||
clouds::Parameters* p = processor->mutable_parameters(); | clouds::Parameters* p = processor->mutable_parameters(); | ||||
p->trigger = triggered; | p->trigger = triggered; | ||||
p->gate = triggered; | p->gate = triggered; | ||||
p->freeze = (getf(inputs[FREEZE_INPUT]) >= 1.0); | |||||
p->position = clampf(params[POSITION_PARAM] + getf(inputs[POSITION_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->size = clampf(params[SIZE_PARAM] + getf(inputs[SIZE_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->pitch = clampf((params[PITCH_PARAM] + getf(inputs[PITCH_INPUT])) * 12.0, -48.0, 48.0); | |||||
p->density = clampf(params[DENSITY_PARAM] + getf(inputs[DENSITY_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->texture = clampf(params[TEXTURE_PARAM] + getf(inputs[TEXTURE_INPUT]) / 5.0, 0.0, 1.0); | |||||
float blend = clampf(params[BLEND_PARAM] + getf(inputs[BLEND_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->freeze = (inputs[FREEZE_INPUT].value >= 1.0); | |||||
p->position = clampf(params[POSITION_PARAM].value + inputs[POSITION_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->size = clampf(params[SIZE_PARAM].value + inputs[SIZE_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->pitch = clampf((params[PITCH_PARAM].value + inputs[PITCH_INPUT].value) * 12.0, -48.0, 48.0); | |||||
p->density = clampf(params[DENSITY_PARAM].value + inputs[DENSITY_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->texture = clampf(params[TEXTURE_PARAM].value + inputs[TEXTURE_INPUT].value / 5.0, 0.0, 1.0); | |||||
float blend = clampf(params[BLEND_PARAM].value + inputs[BLEND_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->dry_wet = blend; | p->dry_wet = blend; | ||||
p->stereo_spread = 0.0; | p->stereo_spread = 0.0; | ||||
p->feedback = 0.0; | p->feedback = 0.0; | ||||
@@ -151,8 +147,8 @@ void Clouds::step() { | |||||
// Set output | // Set output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | Frame<2> outputFrame = outputBuffer.shift(); | ||||
setf(outputs[OUT_L_OUTPUT], 5.0 * outputFrame.samples[0]); | |||||
setf(outputs[OUT_R_OUTPUT], 5.0 * outputFrame.samples[1]); | |||||
outputs[OUT_L_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||||
outputs[OUT_R_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||||
} | } | ||||
} | } | ||||
@@ -102,11 +102,7 @@ struct Elements : Module { | |||||
}; | }; | ||||
Elements::Elements() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Elements::Elements() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
part = new elements::Part(); | part = new elements::Part(); | ||||
// In the Mutable Instruments code, Part doesn't initialize itself, so zero it here. | // In the Mutable Instruments code, Part doesn't initialize itself, so zero it here. | ||||
memset(part, 0, sizeof(*part)); | memset(part, 0, sizeof(*part)); | ||||
@@ -124,8 +120,8 @@ void Elements::step() { | |||||
// Get input | // Get input | ||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
Frame<2> inputFrame; | Frame<2> inputFrame; | ||||
inputFrame.samples[0] = getf(inputs[BLOW_INPUT]) / 5.0; | |||||
inputFrame.samples[1] = getf(inputs[STRIKE_INPUT]) / 5.0; | |||||
inputFrame.samples[0] = inputs[BLOW_INPUT].value / 5.0; | |||||
inputFrame.samples[1] = inputs[STRIKE_INPUT].value / 5.0; | |||||
inputBuffer.push(inputFrame); | inputBuffer.push(inputFrame); | ||||
} | } | ||||
@@ -153,12 +149,12 @@ void Elements::step() { | |||||
// Set patch from parameters | // Set patch from parameters | ||||
elements::Patch* p = part->mutable_patch(); | elements::Patch* p = part->mutable_patch(); | ||||
p->exciter_envelope_shape = params[CONTOUR_PARAM]; | |||||
p->exciter_bow_level = params[BOW_PARAM]; | |||||
p->exciter_blow_level = params[BLOW_PARAM]; | |||||
p->exciter_strike_level = params[STRIKE_PARAM]; | |||||
p->exciter_envelope_shape = params[CONTOUR_PARAM].value; | |||||
p->exciter_bow_level = params[BOW_PARAM].value; | |||||
p->exciter_blow_level = params[BLOW_PARAM].value; | |||||
p->exciter_strike_level = params[STRIKE_PARAM].value; | |||||
#define BIND(_p, _m, _i) clampf(params[_p] + 3.3*quadraticBipolar(params[_m])*getf(inputs[_i])/5.0, 0.0, 0.9995) | |||||
#define BIND(_p, _m, _i) clampf(params[_p].value + 3.3*quadraticBipolar(params[_m].value)*inputs[_i].value/5.0, 0.0, 0.9995) | |||||
p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | ||||
p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | ||||
@@ -169,14 +165,14 @@ void Elements::step() { | |||||
p->resonator_brightness = BIND(BRIGHTNESS_PARAM, BRIGHTNESS_MOD_PARAM, BRIGHTNESS_MOD_INPUT); | p->resonator_brightness = BIND(BRIGHTNESS_PARAM, BRIGHTNESS_MOD_PARAM, BRIGHTNESS_MOD_INPUT); | ||||
p->resonator_damping = BIND(DAMPING_PARAM, DAMPING_MOD_PARAM, DAMPING_MOD_INPUT); | p->resonator_damping = BIND(DAMPING_PARAM, DAMPING_MOD_PARAM, DAMPING_MOD_INPUT); | ||||
p->resonator_position = BIND(POSITION_PARAM, POSITION_MOD_PARAM, POSITION_MOD_INPUT); | p->resonator_position = BIND(POSITION_PARAM, POSITION_MOD_PARAM, POSITION_MOD_INPUT); | ||||
p->space = clampf(params[SPACE_PARAM] + params[SPACE_MOD_PARAM]*getf(inputs[SPACE_MOD_INPUT])/5.0, 0.0, 2.0); | |||||
p->space = clampf(params[SPACE_PARAM].value + params[SPACE_MOD_PARAM].value*inputs[SPACE_MOD_INPUT].value/5.0, 0.0, 2.0); | |||||
// Get performance inputs | // Get performance inputs | ||||
elements::PerformanceState performance; | elements::PerformanceState performance; | ||||
performance.note = 12.0*getf(inputs[NOTE_INPUT]) + roundf(params[COARSE_PARAM]) + params[FINE_PARAM] + 69.0; | |||||
performance.modulation = 3.3*quarticBipolar(params[FM_PARAM]) * 49.5 * getf(inputs[FM_INPUT])/5.0; | |||||
performance.gate = params[PLAY_PARAM] >= 1.0 || getf(inputs[GATE_INPUT]) >= 1.0; | |||||
performance.strength = clampf(1.0 - getf(inputs[STRENGTH_INPUT])/5.0, 0.0, 1.0); | |||||
performance.note = 12.0*inputs[NOTE_INPUT].value + roundf(params[COARSE_PARAM].value) + params[FINE_PARAM].value + 69.0; | |||||
performance.modulation = 3.3*quarticBipolar(params[FM_PARAM].value) * 49.5 * inputs[FM_INPUT].value/5.0; | |||||
performance.gate = params[PLAY_PARAM].value >= 1.0 || inputs[GATE_INPUT].value >= 1.0; | |||||
performance.strength = clampf(1.0 - inputs[STRENGTH_INPUT].value/5.0, 0.0, 1.0); | |||||
// Generate audio | // Generate audio | ||||
part->Process(performance, blow, strike, main, aux, 16); | part->Process(performance, blow, strike, main, aux, 16); | ||||
@@ -204,8 +200,8 @@ void Elements::step() { | |||||
// Set output | // Set output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | Frame<2> outputFrame = outputBuffer.shift(); | ||||
setf(outputs[AUX_OUTPUT], 5.0 * outputFrame.samples[0]); | |||||
setf(outputs[MAIN_OUTPUT], 5.0 * outputFrame.samples[1]); | |||||
outputs[AUX_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||||
outputs[MAIN_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||||
} | } | ||||
} | } | ||||
@@ -36,17 +36,11 @@ struct Frames : Module { | |||||
float lights[1] = {}; | float lights[1] = {}; | ||||
Frames(); | |||||
Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Frames::Frames() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
void Frames::step() { | void Frames::step() { | ||||
} | } | ||||
@@ -32,56 +32,36 @@ struct Kinks : Module { | |||||
float sample = 0.0; | float sample = 0.0; | ||||
float lights[3] = {}; | float lights[3] = {}; | ||||
Kinks(); | |||||
Kinks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Kinks::Kinks() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
void Kinks::step() { | void Kinks::step() { | ||||
// Gaussian noise generator | // Gaussian noise generator | ||||
float noise = 2.0 * randomNormal(); | float noise = 2.0 * randomNormal(); | ||||
// S&H | // S&H | ||||
float trig = getf(inputs[TRIG_INPUT]); | |||||
float trig = inputs[TRIG_INPUT].value; | |||||
float dtrig = (trig - lastTrig) * gSampleRate; | float dtrig = (trig - lastTrig) * gSampleRate; | ||||
if (dtrig > DTRIG) { | if (dtrig > DTRIG) { | ||||
sample = getf(inputs[SH_INPUT], noise); | |||||
sample = inputs[SH_INPUT].normalize(noise); | |||||
} | } | ||||
lastTrig = trig; | lastTrig = trig; | ||||
// lights | // lights | ||||
lights[0] = getf(inputs[SIGN_INPUT]); | |||||
lights[1] = getf(inputs[LOGIC_A_INPUT]) + getf(inputs[LOGIC_B_INPUT]); | |||||
lights[0] = inputs[SIGN_INPUT].value; | |||||
lights[1] = inputs[LOGIC_A_INPUT].value + inputs[LOGIC_B_INPUT].value; | |||||
lights[2] = sample; | lights[2] = sample; | ||||
// outputs | // outputs | ||||
if (outputs[INVERT_OUTPUT]) { | |||||
*outputs[INVERT_OUTPUT] = -getf(inputs[SIGN_INPUT]); | |||||
} | |||||
if (outputs[HALF_RECTIFY_OUTPUT]) { | |||||
*outputs[HALF_RECTIFY_OUTPUT] = fmaxf(0.0, getf(inputs[SIGN_INPUT])); | |||||
} | |||||
if (outputs[FULL_RECTIFY_OUTPUT]) { | |||||
*outputs[FULL_RECTIFY_OUTPUT] = fabsf(getf(inputs[SIGN_INPUT])); | |||||
} | |||||
if (outputs[MAX_OUTPUT]) { | |||||
*outputs[MAX_OUTPUT] = fmaxf(getf(inputs[LOGIC_A_INPUT]), getf(inputs[LOGIC_B_INPUT])); | |||||
} | |||||
if (outputs[MIN_OUTPUT]) { | |||||
*outputs[MIN_OUTPUT] = fminf(getf(inputs[LOGIC_A_INPUT]), getf(inputs[LOGIC_B_INPUT])); | |||||
} | |||||
if (outputs[NOISE_OUTPUT]) { | |||||
*outputs[NOISE_OUTPUT] = noise; | |||||
} | |||||
if (outputs[SH_OUTPUT]) { | |||||
*outputs[SH_OUTPUT] = sample; | |||||
} | |||||
outputs[INVERT_OUTPUT].value = -inputs[SIGN_INPUT].value; | |||||
outputs[HALF_RECTIFY_OUTPUT].value = fmaxf(0.0, inputs[SIGN_INPUT].value); | |||||
outputs[FULL_RECTIFY_OUTPUT].value = fabsf(inputs[SIGN_INPUT].value); | |||||
outputs[MAX_OUTPUT].value = fmaxf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||||
outputs[MIN_OUTPUT].value = fminf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||||
outputs[NOISE_OUTPUT].value = noise; | |||||
outputs[SH_OUTPUT].value = sample; | |||||
} | } | ||||
@@ -25,28 +25,22 @@ struct Links : Module { | |||||
}; | }; | ||||
float lights[3] = {}; | float lights[3] = {}; | ||||
Links(); | |||||
Links() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Links::Links() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
void Links::step() { | void Links::step() { | ||||
float in1 = getf(inputs[A1_INPUT]); | |||||
float in2 = getf(inputs[B1_INPUT]) + getf(inputs[B2_INPUT]); | |||||
float in3 = getf(inputs[C1_INPUT]) + getf(inputs[C2_INPUT]) + getf(inputs[C3_INPUT]); | |||||
setf(outputs[A1_OUTPUT], in1); | |||||
setf(outputs[A2_OUTPUT], in1); | |||||
setf(outputs[A3_OUTPUT], in1); | |||||
setf(outputs[B1_OUTPUT], in2); | |||||
setf(outputs[B2_OUTPUT], in2); | |||||
setf(outputs[C1_OUTPUT], in3); | |||||
float in1 = inputs[A1_INPUT].value; | |||||
float in2 = inputs[B1_INPUT].value + inputs[B2_INPUT].value; | |||||
float in3 = inputs[C1_INPUT].value + inputs[C2_INPUT].value + inputs[C3_INPUT].value; | |||||
outputs[A1_OUTPUT].value = in1; | |||||
outputs[A2_OUTPUT].value = in1; | |||||
outputs[A3_OUTPUT].value = in1; | |||||
outputs[B1_OUTPUT].value = in2; | |||||
outputs[B2_OUTPUT].value = in2; | |||||
outputs[C1_OUTPUT].value = in3; | |||||
lights[0] = in1 / 5.0; | lights[0] = in1 / 5.0; | ||||
lights[1] = in2 / 5.0; | lights[1] = in2 / 5.0; | ||||
@@ -95,11 +95,7 @@ struct Rings : Module { | |||||
}; | }; | ||||
Rings::Rings() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Rings::Rings() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&strummer, 0, sizeof(strummer)); | memset(&strummer, 0, sizeof(strummer)); | ||||
memset(&part, 0, sizeof(part)); | memset(&part, 0, sizeof(part)); | ||||
memset(&string_synth, 0, sizeof(string_synth)); | memset(&string_synth, 0, sizeof(string_synth)); | ||||
@@ -118,21 +114,21 @@ void Rings::step() { | |||||
// Get input | // Get input | ||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
Frame<1> f; | Frame<1> f; | ||||
f.samples[0] = getf(inputs[IN_INPUT]) / 5.0; | |||||
f.samples[0] = inputs[IN_INPUT].value / 5.0; | |||||
inputBuffer.push(f); | inputBuffer.push(f); | ||||
} | } | ||||
if (!strum) { | if (!strum) { | ||||
strum = getf(inputs[STRUM_INPUT]) >= 1.0; | |||||
strum = inputs[STRUM_INPUT].value >= 1.0; | |||||
} | } | ||||
// Polyphony / model | // Polyphony / model | ||||
if (polyphonyTrigger.process(params[POLYPHONY_PARAM])) { | |||||
if (polyphonyTrigger.process(params[POLYPHONY_PARAM].value)) { | |||||
polyphonyMode = (polyphonyMode + 1) % 3; | polyphonyMode = (polyphonyMode + 1) % 3; | ||||
} | } | ||||
lights[0] = (float)polyphonyMode; | lights[0] = (float)polyphonyMode; | ||||
if (modelTrigger.process(params[RESONATOR_PARAM])) { | |||||
if (modelTrigger.process(params[RESONATOR_PARAM].value)) { | |||||
model = (model + 1) % 3; | model = (model + 1) % 3; | ||||
} | } | ||||
lights[1] = (float)model; | lights[1] = (float)model; | ||||
@@ -157,26 +153,26 @@ void Rings::step() { | |||||
// Patch | // Patch | ||||
rings::Patch patch; | rings::Patch patch; | ||||
float structure = params[STRUCTURE_PARAM] + 3.3*quadraticBipolar(params[STRUCTURE_MOD_PARAM])*getf(inputs[STRUCTURE_MOD_INPUT])/5.0; | |||||
float structure = params[STRUCTURE_PARAM].value + 3.3*quadraticBipolar(params[STRUCTURE_MOD_PARAM].value)*inputs[STRUCTURE_MOD_INPUT].value/5.0; | |||||
patch.structure = clampf(structure, 0.0, 0.9995); | patch.structure = clampf(structure, 0.0, 0.9995); | ||||
patch.brightness = clampf(params[BRIGHTNESS_PARAM] + 3.3*quadraticBipolar(params[BRIGHTNESS_MOD_PARAM])*getf(inputs[BRIGHTNESS_MOD_INPUT])/5.0, 0.0, 1.0); | |||||
patch.damping = clampf(params[DAMPING_PARAM] + 3.3*quadraticBipolar(params[DAMPING_MOD_PARAM])*getf(inputs[DAMPING_MOD_INPUT])/5.0, 0.0, 0.9995); | |||||
patch.position = clampf(params[POSITION_PARAM] + 3.3*quadraticBipolar(params[POSITION_MOD_PARAM])*getf(inputs[POSITION_MOD_INPUT])/5.0, 0.0, 0.9995); | |||||
patch.brightness = clampf(params[BRIGHTNESS_PARAM].value + 3.3*quadraticBipolar(params[BRIGHTNESS_MOD_PARAM].value)*inputs[BRIGHTNESS_MOD_INPUT].value/5.0, 0.0, 1.0); | |||||
patch.damping = clampf(params[DAMPING_PARAM].value + 3.3*quadraticBipolar(params[DAMPING_MOD_PARAM].value)*inputs[DAMPING_MOD_INPUT].value/5.0, 0.0, 0.9995); | |||||
patch.position = clampf(params[POSITION_PARAM].value + 3.3*quadraticBipolar(params[POSITION_MOD_PARAM].value)*inputs[POSITION_MOD_INPUT].value/5.0, 0.0, 0.9995); | |||||
// Performance | // Performance | ||||
rings::PerformanceState performance_state; | rings::PerformanceState performance_state; | ||||
performance_state.note = 12.0*getf(inputs[PITCH_INPUT], 1/12.0); | |||||
float transpose = params[FREQUENCY_PARAM]; | |||||
performance_state.note = 12.0*inputs[PITCH_INPUT].normalize(1/12.0); | |||||
float transpose = params[FREQUENCY_PARAM].value; | |||||
// Quantize transpose if pitch input is connected | // Quantize transpose if pitch input is connected | ||||
if (inputs[PITCH_INPUT]) { | |||||
if (inputs[PITCH_INPUT].active) { | |||||
transpose = roundf(transpose); | transpose = roundf(transpose); | ||||
} | } | ||||
performance_state.tonic = 12.0 + clampf(transpose, 0, 60.0); | performance_state.tonic = 12.0 + clampf(transpose, 0, 60.0); | ||||
performance_state.fm = clampf(48.0 * 3.3*quarticBipolar(params[FREQUENCY_MOD_PARAM]) * getf(inputs[FREQUENCY_MOD_INPUT], 1.0)/5.0, -48.0, 48.0); | |||||
performance_state.fm = clampf(48.0 * 3.3*quarticBipolar(params[FREQUENCY_MOD_PARAM].value) * inputs[FREQUENCY_MOD_INPUT].normalize(1.0)/5.0, -48.0, 48.0); | |||||
performance_state.internal_exciter = !inputs[IN_INPUT]; | |||||
performance_state.internal_strum = !inputs[STRUM_INPUT]; | |||||
performance_state.internal_note = !inputs[PITCH_INPUT]; | |||||
performance_state.internal_exciter = !inputs[IN_INPUT].active; | |||||
performance_state.internal_strum = !inputs[STRUM_INPUT].active; | |||||
performance_state.internal_note = !inputs[PITCH_INPUT].active; | |||||
// TODO | // TODO | ||||
// "Normalized to a step detector on the V/OCT input and a transient detector on the IN input." | // "Normalized to a step detector on the V/OCT input and a transient detector on the IN input." | ||||
@@ -218,14 +214,14 @@ void Rings::step() { | |||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | Frame<2> outputFrame = outputBuffer.shift(); | ||||
// "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | // "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | ||||
if (outputs[ODD_OUTPUT] && outputs[EVEN_OUTPUT]) { | |||||
setf(outputs[ODD_OUTPUT], clampf(outputFrame.samples[0], -1.0, 1.0)*5.0); | |||||
setf(outputs[EVEN_OUTPUT], clampf(outputFrame.samples[1], -1.0, 1.0)*5.0); | |||||
if (outputs[ODD_OUTPUT].active && outputs[EVEN_OUTPUT].active) { | |||||
outputs[ODD_OUTPUT].value = clampf(outputFrame.samples[0], -1.0, 1.0)*5.0; | |||||
outputs[EVEN_OUTPUT].value = clampf(outputFrame.samples[1], -1.0, 1.0)*5.0; | |||||
} | } | ||||
else { | else { | ||||
float v = clampf(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | float v = clampf(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | ||||
setf(outputs[ODD_OUTPUT], v); | |||||
setf(outputs[EVEN_OUTPUT], v); | |||||
outputs[ODD_OUTPUT].value = v; | |||||
outputs[EVEN_OUTPUT].value = v; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -27,26 +27,20 @@ struct Shades : Module { | |||||
float lights[3] = {}; | float lights[3] = {}; | ||||
Shades(); | |||||
Shades() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Shades::Shades() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
static float getChannelOutput(const float *in, float gain, float mode) { | |||||
float out = getf(in, 5.0); | |||||
if ((int)roundf(mode) == 1) { | |||||
static float getChannelOutput(Input &in, Param &gain, Param &mode) { | |||||
float out = in.normalize(5.0); | |||||
if ((int)roundf(mode.value) == 1) { | |||||
// attenuverter | // attenuverter | ||||
out *= 2.0*gain - 1.0; | |||||
out *= 2.0*gain.value - 1.0; | |||||
} | } | ||||
else { | else { | ||||
// attenuator | // attenuator | ||||
out *= gain; | |||||
out *= gain.value; | |||||
} | } | ||||
return out; | return out; | ||||
} | } | ||||
@@ -55,22 +49,22 @@ void Shades::step() { | |||||
float out = 0.0; | float out = 0.0; | ||||
out += getChannelOutput(inputs[IN1_INPUT], params[GAIN1_PARAM], params[MODE1_PARAM]); | out += getChannelOutput(inputs[IN1_INPUT], params[GAIN1_PARAM], params[MODE1_PARAM]); | ||||
lights[0] = out / 5.0; | lights[0] = out / 5.0; | ||||
if (outputs[OUT1_OUTPUT]) { | |||||
*outputs[OUT1_OUTPUT] = out; | |||||
if (outputs[OUT1_OUTPUT].active) { | |||||
outputs[OUT1_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN2_INPUT], params[GAIN2_PARAM], params[MODE2_PARAM]); | out += getChannelOutput(inputs[IN2_INPUT], params[GAIN2_PARAM], params[MODE2_PARAM]); | ||||
lights[1] = out / 5.0; | lights[1] = out / 5.0; | ||||
if (outputs[OUT2_OUTPUT]) { | |||||
*outputs[OUT2_OUTPUT] = out; | |||||
if (outputs[OUT2_OUTPUT].active) { | |||||
outputs[OUT2_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN3_INPUT], params[GAIN3_PARAM], params[MODE3_PARAM]); | out += getChannelOutput(inputs[IN3_INPUT], params[GAIN3_PARAM], params[MODE3_PARAM]); | ||||
lights[2] = out / 5.0; | lights[2] = out / 5.0; | ||||
if (outputs[OUT3_OUTPUT]) { | |||||
*outputs[OUT3_OUTPUT] = out; | |||||
if (outputs[OUT3_OUTPUT].active) { | |||||
outputs[OUT3_OUTPUT].value = out; | |||||
} | } | ||||
} | } | ||||
@@ -83,11 +83,7 @@ struct Sheep : Module { | |||||
}; | }; | ||||
Sheep::Sheep() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Sheep::Sheep() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&generator, 0, sizeof(generator)); | memset(&generator, 0, sizeof(generator)); | ||||
generator.Init(); | generator.Init(); | ||||
generator.set_sync(false); | generator.set_sync(false); | ||||
@@ -96,14 +92,14 @@ Sheep::Sheep() { | |||||
void Sheep::step() { | void Sheep::step() { | ||||
tides::GeneratorMode mode = generator.mode(); | tides::GeneratorMode mode = generator.mode(); | ||||
if (modeTrigger.process(params[BANK_PARAM])) { | |||||
if (modeTrigger.process(params[BANK_PARAM].value)) { | |||||
mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | ||||
generator.set_mode(mode); | generator.set_mode(mode); | ||||
} | } | ||||
lights[0] = (float)mode; | lights[0] = (float)mode; | ||||
tides::GeneratorRange range = generator.range(); | tides::GeneratorRange range = generator.range(); | ||||
if (rangeTrigger.process(params[RANGE_PARAM])) { | |||||
if (rangeTrigger.process(params[RANGE_PARAM].value)) { | |||||
range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | ||||
generator.set_range(range); | generator.set_range(range); | ||||
} | } | ||||
@@ -114,18 +110,18 @@ void Sheep::step() { | |||||
frame = 0; | frame = 0; | ||||
// Pitch | // Pitch | ||||
float pitch = params[FREQUENCY_PARAM]; | |||||
pitch += 12.0 * getf(inputs[PITCH_INPUT]); | |||||
pitch += params[FM_PARAM] * getf(inputs[FM_INPUT], 0.1) / 5.0; | |||||
float pitch = params[FREQUENCY_PARAM].value; | |||||
pitch += 12.0 * inputs[PITCH_INPUT].value; | |||||
pitch += params[FM_PARAM].value * inputs[FM_INPUT].normalize(0.1) / 5.0; | |||||
pitch += 60.0; | pitch += 60.0; | ||||
// Scale to the global sample rate | // Scale to the global sample rate | ||||
pitch += log2f(48000.0 / gSampleRate) * 12.0; | pitch += log2f(48000.0 / gSampleRate) * 12.0; | ||||
generator.set_pitch(clampf(pitch * 0x80, -0x8000, 0x7fff)); | generator.set_pitch(clampf(pitch * 0x80, -0x8000, 0x7fff)); | ||||
// Slope, smoothness, pitch | // Slope, smoothness, pitch | ||||
int16_t shape = clampf(params[ROW_PARAM] + getf(inputs[ROW_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t slope = clampf(params[COLUMN_PARAM] + getf(inputs[COLUMN_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t smoothness = clampf(params[SMOOTHNESS_PARAM] + getf(inputs[SMOOTHNESS_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t shape = clampf(params[ROW_PARAM].value + inputs[ROW_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t slope = clampf(params[COLUMN_PARAM].value + inputs[COLUMN_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t smoothness = clampf(params[SMOOTHNESS_PARAM].value + inputs[SMOOTHNESS_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
generator.set_shape(shape); | generator.set_shape(shape); | ||||
generator.set_slope(slope); | generator.set_slope(slope); | ||||
generator.set_smoothness(smoothness); | generator.set_smoothness(smoothness); | ||||
@@ -133,23 +129,23 @@ void Sheep::step() { | |||||
// Sync | // Sync | ||||
// Slight deviation from spec here. | // Slight deviation from spec here. | ||||
// Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | // Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | ||||
generator.set_sync(inputs[BANK_INPUT]); | |||||
generator.set_sync(inputs[BANK_INPUT].active); | |||||
// Generator | // Generator | ||||
generator.Process(); | generator.Process(); | ||||
} | } | ||||
// Level | // Level | ||||
uint16_t level = clampf(getf(inputs[LEVEL_INPUT], 8.0) / 8.0, 0.0, 1.0) * 0xffff; | |||||
uint16_t level = clampf(inputs[LEVEL_INPUT].normalize(8.0) / 8.0, 0.0, 1.0) * 0xffff; | |||||
if (level < 32) | if (level < 32) | ||||
level = 0; | level = 0; | ||||
uint8_t gate = 0; | uint8_t gate = 0; | ||||
if (getf(inputs[FREEZE_INPUT]) >= 0.7) | |||||
if (inputs[FREEZE_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_FREEZE; | gate |= tides::CONTROL_FREEZE; | ||||
if (getf(inputs[SYNC_INPUT]) >= 0.7) | |||||
if (inputs[SYNC_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_GATE; | gate |= tides::CONTROL_GATE; | ||||
if (getf(inputs[BANK_INPUT]) >= 0.7) | |||||
if (inputs[BANK_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_CLOCK; | gate |= tides::CONTROL_CLOCK; | ||||
if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | ||||
gate |= tides::CONTROL_GATE_RISING; | gate |= tides::CONTROL_GATE_RISING; | ||||
@@ -168,10 +164,10 @@ void Sheep::step() { | |||||
float unif = rescalef(uni, 0, 0xffff, 0.0, 8.0); | float unif = rescalef(uni, 0, 0xffff, 0.0, 8.0); | ||||
float bif = rescalef(bi, -0x8000, 0x7fff, -5.0, 5.0); | float bif = rescalef(bi, -0x8000, 0x7fff, -5.0, 5.0); | ||||
setf(outputs[BIT_OUTPUT], sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0); | |||||
setf(outputs[SUB_OUTPUT], sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0); | |||||
setf(outputs[UNI_OUTPUT], unif); | |||||
setf(outputs[BI_OUTPUT], bif); | |||||
outputs[BIT_OUTPUT].value = sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0; | |||||
outputs[SUB_OUTPUT].value = sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0; | |||||
outputs[UNI_OUTPUT].value = unif; | |||||
outputs[BI_OUTPUT].value = bif; | |||||
lights[1] = (sample.flags & tides::FLAG_END_OF_ATTACK ? -unif : unif) / 8.0; | lights[1] = (sample.flags & tides::FLAG_END_OF_ATTACK ? -unif : unif) / 8.0; | ||||
} | } | ||||
@@ -31,17 +31,11 @@ struct Streams : Module { | |||||
NUM_OUTPUTS | NUM_OUTPUTS | ||||
}; | }; | ||||
Streams(); | |||||
Streams() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Streams::Streams() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
void Streams::step() { | void Streams::step() { | ||||
} | } | ||||
@@ -81,11 +81,7 @@ struct Tides : Module { | |||||
}; | }; | ||||
Tides::Tides() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Tides::Tides() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&generator, 0, sizeof(generator)); | memset(&generator, 0, sizeof(generator)); | ||||
generator.Init(); | generator.Init(); | ||||
generator.set_sync(false); | generator.set_sync(false); | ||||
@@ -94,14 +90,14 @@ Tides::Tides() { | |||||
void Tides::step() { | void Tides::step() { | ||||
tides::GeneratorMode mode = generator.mode(); | tides::GeneratorMode mode = generator.mode(); | ||||
if (modeTrigger.process(params[MODE_PARAM])) { | |||||
if (modeTrigger.process(params[MODE_PARAM].value)) { | |||||
mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | ||||
generator.set_mode(mode); | generator.set_mode(mode); | ||||
} | } | ||||
lights[0] = (float)mode; | lights[0] = (float)mode; | ||||
tides::GeneratorRange range = generator.range(); | tides::GeneratorRange range = generator.range(); | ||||
if (rangeTrigger.process(params[RANGE_PARAM])) { | |||||
if (rangeTrigger.process(params[RANGE_PARAM].value)) { | |||||
range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | ||||
generator.set_range(range); | generator.set_range(range); | ||||
} | } | ||||
@@ -112,18 +108,18 @@ void Tides::step() { | |||||
frame = 0; | frame = 0; | ||||
// Pitch | // Pitch | ||||
float pitch = params[FREQUENCY_PARAM]; | |||||
pitch += 12.0 * getf(inputs[PITCH_INPUT]); | |||||
pitch += params[FM_PARAM] * getf(inputs[FM_INPUT], 0.1) / 5.0; | |||||
float pitch = params[FREQUENCY_PARAM].value; | |||||
pitch += 12.0 * inputs[PITCH_INPUT].value; | |||||
pitch += params[FM_PARAM].value * inputs[FM_INPUT].normalize(0.1) / 5.0; | |||||
pitch += 60.0; | pitch += 60.0; | ||||
// Scale to the global sample rate | // Scale to the global sample rate | ||||
pitch += log2f(48000.0 / gSampleRate) * 12.0; | pitch += log2f(48000.0 / gSampleRate) * 12.0; | ||||
generator.set_pitch(clampf(pitch * 0x80, -0x8000, 0x7fff)); | generator.set_pitch(clampf(pitch * 0x80, -0x8000, 0x7fff)); | ||||
// Slope, smoothness, pitch | // Slope, smoothness, pitch | ||||
int16_t shape = clampf(params[SHAPE_PARAM] + getf(inputs[SHAPE_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t slope = clampf(params[SLOPE_PARAM] + getf(inputs[SLOPE_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t smoothness = clampf(params[SMOOTHNESS_PARAM] + getf(inputs[SMOOTHNESS_INPUT]) / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t shape = clampf(params[SHAPE_PARAM].value + inputs[SHAPE_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t slope = clampf(params[SLOPE_PARAM].value + inputs[SLOPE_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
int16_t smoothness = clampf(params[SMOOTHNESS_PARAM].value + inputs[SMOOTHNESS_INPUT].value / 5.0, -1.0, 1.0) * 0x7fff; | |||||
generator.set_shape(shape); | generator.set_shape(shape); | ||||
generator.set_slope(slope); | generator.set_slope(slope); | ||||
generator.set_smoothness(smoothness); | generator.set_smoothness(smoothness); | ||||
@@ -131,23 +127,23 @@ void Tides::step() { | |||||
// Sync | // Sync | ||||
// Slight deviation from spec here. | // Slight deviation from spec here. | ||||
// Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | // Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | ||||
generator.set_sync(inputs[CLOCK_INPUT]); | |||||
generator.set_sync(inputs[CLOCK_INPUT].active); | |||||
// Generator | // Generator | ||||
generator.Process(); | generator.Process(); | ||||
} | } | ||||
// Level | // Level | ||||
uint16_t level = clampf(getf(inputs[LEVEL_INPUT], 8.0) / 8.0, 0.0, 1.0) * 0xffff; | |||||
uint16_t level = clampf(inputs[LEVEL_INPUT].normalize(8.0) / 8.0, 0.0, 1.0) * 0xffff; | |||||
if (level < 32) | if (level < 32) | ||||
level = 0; | level = 0; | ||||
uint8_t gate = 0; | uint8_t gate = 0; | ||||
if (getf(inputs[FREEZE_INPUT]) >= 0.7) | |||||
if (inputs[FREEZE_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_FREEZE; | gate |= tides::CONTROL_FREEZE; | ||||
if (getf(inputs[TRIG_INPUT]) >= 0.7) | |||||
if (inputs[TRIG_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_GATE; | gate |= tides::CONTROL_GATE; | ||||
if (getf(inputs[CLOCK_INPUT]) >= 0.7) | |||||
if (inputs[CLOCK_INPUT].value >= 0.7) | |||||
gate |= tides::CONTROL_CLOCK; | gate |= tides::CONTROL_CLOCK; | ||||
if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | ||||
gate |= tides::CONTROL_GATE_RISING; | gate |= tides::CONTROL_GATE_RISING; | ||||
@@ -166,10 +162,10 @@ void Tides::step() { | |||||
float unif = rescalef(uni, 0, 0xffff, 0.0, 8.0); | float unif = rescalef(uni, 0, 0xffff, 0.0, 8.0); | ||||
float bif = rescalef(bi, -0x8000, 0x7fff, -5.0, 5.0); | float bif = rescalef(bi, -0x8000, 0x7fff, -5.0, 5.0); | ||||
setf(outputs[HIGH_OUTPUT], sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0); | |||||
setf(outputs[LOW_OUTPUT], sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0); | |||||
setf(outputs[UNI_OUTPUT], unif); | |||||
setf(outputs[BI_OUTPUT], bif); | |||||
outputs[HIGH_OUTPUT].value = sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0; | |||||
outputs[LOW_OUTPUT].value = sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0; | |||||
outputs[UNI_OUTPUT].value = unif; | |||||
outputs[BI_OUTPUT].value = bif; | |||||
lights[1] = (sample.flags & tides::FLAG_END_OF_ATTACK ? -unif : unif) / 8.0; | lights[1] = (sample.flags & tides::FLAG_END_OF_ATTACK ? -unif : unif) / 8.0; | ||||
} | } | ||||
@@ -35,60 +35,54 @@ struct Veils : Module { | |||||
float lights[4] = {}; | float lights[4] = {}; | ||||
Veils(); | |||||
Veils() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} | |||||
void step(); | void step(); | ||||
}; | }; | ||||
Veils::Veils() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
} | |||||
static float getChannelOutput(float *in, float gain, float *cv, float response) { | |||||
float out = getf(in) * gain; | |||||
static float processChannel(Input &in, Param &gain, Input &cv, Param &response) { | |||||
float out = in.value * gain.value; | |||||
if (out == 0.0) | if (out == 0.0) | ||||
return 0.0; | return 0.0; | ||||
if (cv) { | |||||
float linear = fmaxf(getf(cv) / 5.0, 0.0); | |||||
if (cv.active) { | |||||
float linear = fmaxf(cv.value / 5.0, 0.0); | |||||
if (linear == 0.0) | if (linear == 0.0) | ||||
return 0.0; | return 0.0; | ||||
const float ex = 200.0; | const float ex = 200.0; | ||||
float exponential = rescalef(powf(ex, linear), 1.0, ex, 0.0, 1.0); | float exponential = rescalef(powf(ex, linear), 1.0, ex, 0.0, 1.0); | ||||
out *= crossf(exponential, linear, response); | |||||
out *= crossf(exponential, linear, response.value); | |||||
} | } | ||||
return out; | return out; | ||||
} | } | ||||
void Veils::step() { | void Veils::step() { | ||||
float out = 0.0; | float out = 0.0; | ||||
out += getChannelOutput(inputs[IN1_INPUT], params[GAIN1_PARAM], inputs[CV1_INPUT], params[RESPONSE1_PARAM]); | |||||
out += processChannel(inputs[IN1_INPUT], params[GAIN1_PARAM], inputs[CV1_INPUT], params[RESPONSE1_PARAM]); | |||||
lights[0] = out; | lights[0] = out; | ||||
if (outputs[OUT1_OUTPUT]) { | |||||
*outputs[OUT1_OUTPUT] = out; | |||||
if (outputs[OUT1_OUTPUT].active) { | |||||
outputs[OUT1_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN2_INPUT], params[GAIN2_PARAM], inputs[CV2_INPUT], params[RESPONSE2_PARAM]); | |||||
out += processChannel(inputs[IN2_INPUT], params[GAIN2_PARAM], inputs[CV2_INPUT], params[RESPONSE2_PARAM]); | |||||
lights[1] = out; | lights[1] = out; | ||||
if (outputs[OUT2_OUTPUT]) { | |||||
*outputs[OUT2_OUTPUT] = out; | |||||
if (outputs[OUT2_OUTPUT].active) { | |||||
outputs[OUT2_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN3_INPUT], params[GAIN3_PARAM], inputs[CV3_INPUT], params[RESPONSE3_PARAM]); | |||||
out += processChannel(inputs[IN3_INPUT], params[GAIN3_PARAM], inputs[CV3_INPUT], params[RESPONSE3_PARAM]); | |||||
lights[2] = out; | lights[2] = out; | ||||
if (outputs[OUT3_OUTPUT]) { | |||||
*outputs[OUT3_OUTPUT] = out; | |||||
if (outputs[OUT3_OUTPUT].active) { | |||||
outputs[OUT3_OUTPUT].value = out; | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
out += getChannelOutput(inputs[IN4_INPUT], params[GAIN4_PARAM], inputs[CV4_INPUT], params[RESPONSE4_PARAM]); | |||||
out += processChannel(inputs[IN4_INPUT], params[GAIN4_PARAM], inputs[CV4_INPUT], params[RESPONSE4_PARAM]); | |||||
lights[3] = out; | lights[3] = out; | ||||
if (outputs[OUT4_OUTPUT]) { | |||||
*outputs[OUT4_OUTPUT] = out; | |||||
if (outputs[OUT4_OUTPUT].active) { | |||||
outputs[OUT4_OUTPUT].value = out; | |||||
} | } | ||||
} | } | ||||
@@ -64,11 +64,7 @@ struct Warps : Module { | |||||
}; | }; | ||||
Warps::Warps() { | |||||
params.resize(NUM_PARAMS); | |||||
inputs.resize(NUM_INPUTS); | |||||
outputs.resize(NUM_OUTPUTS); | |||||
Warps::Warps() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&modulator, 0, sizeof(modulator)); | memset(&modulator, 0, sizeof(modulator)); | ||||
modulator.Init(96000.0f); | modulator.Init(96000.0f); | ||||
@@ -78,7 +74,7 @@ Warps::Warps() { | |||||
void Warps::step() { | void Warps::step() { | ||||
// State trigger | // State trigger | ||||
warps::Parameters *p = modulator.mutable_parameters(); | warps::Parameters *p = modulator.mutable_parameters(); | ||||
if (stateTrigger.process(params[STATE_PARAM])) { | |||||
if (stateTrigger.process(params[STATE_PARAM].value)) { | |||||
p->carrier_shape = (p->carrier_shape + 1) % 4; | p->carrier_shape = (p->carrier_shape + 1) % 4; | ||||
} | } | ||||
lights[0] = p->carrier_shape; | lights[0] = p->carrier_shape; | ||||
@@ -87,25 +83,25 @@ void Warps::step() { | |||||
if (++frame >= 60) { | if (++frame >= 60) { | ||||
frame = 0; | frame = 0; | ||||
p->channel_drive[0] = clampf(params[LEVEL1_PARAM] + getf(inputs[LEVEL1_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->channel_drive[1] = clampf(params[LEVEL2_PARAM] + getf(inputs[LEVEL2_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->modulation_algorithm = clampf(params[ALGORITHM_PARAM] / 8.0 + getf(inputs[ALGORITHM_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->channel_drive[0] = clampf(params[LEVEL1_PARAM].value + inputs[LEVEL1_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->channel_drive[1] = clampf(params[LEVEL2_PARAM].value + inputs[LEVEL2_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->modulation_algorithm = clampf(params[ALGORITHM_PARAM].value / 8.0 + inputs[ALGORITHM_INPUT].value / 5.0, 0.0, 1.0); | |||||
lights[1] = p->modulation_algorithm * 8.0; | lights[1] = p->modulation_algorithm * 8.0; | ||||
p->modulation_parameter = clampf(params[TIMBRE_PARAM] + getf(inputs[TIMBRE_INPUT]) / 5.0, 0.0, 1.0); | |||||
p->modulation_parameter = clampf(params[TIMBRE_PARAM].value + inputs[TIMBRE_INPUT].value / 5.0, 0.0, 1.0); | |||||
p->frequency_shift_pot = params[ALGORITHM_PARAM] / 8.0; | |||||
p->frequency_shift_cv = clampf(getf(inputs[ALGORITHM_INPUT]) / 5.0, -1.0, 1.0); | |||||
p->frequency_shift_pot = params[ALGORITHM_PARAM].value / 8.0; | |||||
p->frequency_shift_cv = clampf(inputs[ALGORITHM_INPUT].value / 5.0, -1.0, 1.0); | |||||
p->phase_shift = p->modulation_algorithm; | p->phase_shift = p->modulation_algorithm; | ||||
p->note = 60.0 * params[LEVEL1_PARAM] + 12.0 * getf(inputs[LEVEL1_INPUT], 2.0) + 12.0; | |||||
p->note = 60.0 * params[LEVEL1_PARAM].value + 12.0 * inputs[LEVEL1_INPUT].normalize(2.0) + 12.0; | |||||
p->note += log2f(96000.0 / gSampleRate) * 12.0; | p->note += log2f(96000.0 / gSampleRate) * 12.0; | ||||
modulator.Process(inputFrames, outputFrames, 60); | modulator.Process(inputFrames, outputFrames, 60); | ||||
} | } | ||||
inputFrames[frame].l = clampf(getf(inputs[CARRIER_INPUT]) / 16.0 * 0x8000, -0x8000, 0x7fff); | |||||
inputFrames[frame].r = clampf(getf(inputs[MODULATOR_INPUT]) / 16.0 * 0x8000, -0x8000, 0x7fff); | |||||
setf(outputs[MODULATOR_OUTPUT], (float)outputFrames[frame].l / 0x8000 * 5.0); | |||||
setf(outputs[AUX_OUTPUT], (float)outputFrames[frame].r / 0x8000 * 5.0); | |||||
inputFrames[frame].l = clampf(inputs[CARRIER_INPUT].value / 16.0 * 0x8000, -0x8000, 0x7fff); | |||||
inputFrames[frame].r = clampf(inputs[MODULATOR_INPUT].value / 16.0 * 0x8000, -0x8000, 0x7fff); | |||||
outputs[MODULATOR_OUTPUT].value = (float)outputFrames[frame].l / 0x8000 * 5.0; | |||||
outputs[AUX_OUTPUT].value = (float)outputFrames[frame].r / 0x8000 * 5.0; | |||||
} | } | ||||