* fixed bug with Muxlicer outputClockFollowsPlayModetags/v2.1.0
@@ -1,5 +1,8 @@ | |||||
# Change Log | # Change Log | ||||
## v2.0.0 (unreleased) | |||||
* update to Rack 2 API (added tooltips, bypass, removed boilerplate etc) | |||||
## v1.2.0 (unreleased) | ## v1.2.0 (unreleased) | ||||
* Released new modules: Muxlicer, Mex, Morphader, VC ADSR, Sampling Modulator, ST Mix | * Released new modules: Muxlicer, Mex, Morphader, VC ADSR, Sampling Modulator, ST Mix | ||||
@@ -47,6 +47,18 @@ struct EvenVCO : Module { | |||||
configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | ||||
configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); | configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); | ||||
configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); | configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); | ||||
configInput(PITCH1_INPUT, "Pitch 1"); | |||||
configInput(PITCH2_INPUT, "Pitch 2"); | |||||
configInput(FM_INPUT, "FM"); | |||||
configInput(SYNC_INPUT, "Sync (not implemented)"); | |||||
configInput(PWM_INPUT, "Pulse Width Modulation"); | |||||
configOutput(TRI_OUTPUT, "Triangle"); | |||||
configOutput(SINE_OUTPUT, "Sine"); | |||||
configOutput(EVEN_OUTPUT, "Even"); | |||||
configOutput(SAW_OUTPUT, "Sawtooth"); | |||||
configOutput(SQUARE_OUTPUT, "Square"); | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
@@ -194,17 +194,7 @@ struct HexmixVCAWidget : ModuleWidget { | |||||
assert(module); | assert(module); | ||||
menu->addChild(new MenuSeparator()); | menu->addChild(new MenuSeparator()); | ||||
struct MixMenuItem : MenuItem { | |||||
HexmixVCA* module; | |||||
void onAction(const event::Action& e) override { | |||||
module->finalRowIsMix ^= true; | |||||
} | |||||
}; | |||||
MixMenuItem* mixItem = createMenuItem<MixMenuItem>("Final row is mix", CHECKMARK(module->finalRowIsMix)); | |||||
mixItem->module = module; | |||||
menu->addChild(mixItem); | |||||
menu->addChild(createBoolPtrMenuItem("Final row is mix", &module->finalRowIsMix)); | |||||
} | } | ||||
}; | }; | ||||
@@ -49,7 +49,7 @@ struct Kickall : Module { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
// TODO: review this mapping, using displayBase multiplier seems more normal | // TODO: review this mapping, using displayBase multiplier seems more normal | ||||
configParam(TUNE_PARAM, FREQ_A0, FREQ_B2, 0.5 * (FREQ_A0 + FREQ_B2), "Tune", "Hz"); | configParam(TUNE_PARAM, FREQ_A0, FREQ_B2, 0.5 * (FREQ_A0 + FREQ_B2), "Tune", "Hz"); | ||||
configParam(TRIGG_BUTTON_PARAM, 0.f, 1.f, 0.f, "Manual trigger"); | |||||
configButton(TRIGG_BUTTON_PARAM, "Manual trigger"); | |||||
configParam(SHAPE_PARAM, 0.f, 1.f, 0.f, "Wave shape"); | configParam(SHAPE_PARAM, 0.f, 1.f, 0.f, "Wave shape"); | ||||
configParam(DECAY_PARAM, 0.f, 1.f, 0.01f, "VCA Envelope decay time"); | configParam(DECAY_PARAM, 0.f, 1.f, 0.01f, "VCA Envelope decay time"); | ||||
configParam(TIME_PARAM, 0.f, 1.0f, 0.f, "Pitch envelope decay time"); | configParam(TIME_PARAM, 0.f, 1.0f, 0.f, "Pitch envelope decay time"); | ||||
@@ -61,6 +61,15 @@ struct Kickall : Module { | |||||
pitch.attackTime = 0.00165; | pitch.attackTime = 0.00165; | ||||
pitch.decayShape = 3.0; | pitch.decayShape = 3.0; | ||||
configInput(TRIGG_INPUT, "Trigger"); | |||||
configInput(VOLUME_INPUT, "Gain"); | |||||
configInput(TUNE_INPUT, "Tune (V/Oct)"); | |||||
configInput(SHAPE_INPUT, "Shape CV"); | |||||
configInput(DECAY_INPUT, "Decay CV"); | |||||
configOutput(OUT_OUTPUT, "Kick"); | |||||
configLight(ENV_LIGHT, "Volume envelope"); | |||||
// calculate up/downsampling rates | // calculate up/downsampling rates | ||||
onSampleRateChange(); | onSampleRateChange(); | ||||
} | } | ||||
@@ -28,23 +28,11 @@ struct Mex : Module { | |||||
dsp::SchmittTrigger gateInTrigger; | dsp::SchmittTrigger gateInTrigger; | ||||
struct GateSwitchParamQuantity : ParamQuantity { | |||||
std::string getDisplayValueString() override { | |||||
switch ((StepState) ParamQuantity::getValue()) { | |||||
case GATE_IN_MODE: return "Gate in/Clock Out"; | |||||
case MUTE_MODE: return "Muted"; | |||||
case MUXLICER_MODE: return "All Gates"; | |||||
default: return ""; | |||||
} | |||||
} | |||||
}; | |||||
Mex() { | Mex() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
for (int i = 0; i < 8; ++i) { | for (int i = 0; i < 8; ++i) { | ||||
configParam<GateSwitchParamQuantity>(STEP_PARAM + i, 0.f, 2.f, 0.f, string::f("Step %d", i + 1)); | |||||
configSwitch(STEP_PARAM + i, 0.f, 2.f, 0.f, string::f("Step %d", i + 1), {"Gate in/Clock Out", "Muted", "All Gates"}); | |||||
} | } | ||||
} | } | ||||
@@ -35,6 +35,9 @@ struct Mixer : Module { | |||||
configParam(CH2_PARAM, 0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100); | configParam(CH2_PARAM, 0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100); | ||||
configParam(CH3_PARAM, 0.0, 1.0, 0.0, "Ch 3 level", "%", 0, 100); | configParam(CH3_PARAM, 0.0, 1.0, 0.0, "Ch 3 level", "%", 0, 100); | ||||
configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | ||||
configOutput(OUT1_OUTPUT, "Main"); | |||||
configOutput(OUT2_OUTPUT, "Inverted"); | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
@@ -88,29 +88,22 @@ struct Morphader : Module { | |||||
constexpr static float slewMin = 2.0 / 15.f; | constexpr static float slewMin = 2.0 / 15.f; | ||||
constexpr static float slewMax = 2.0 / 0.01f; | constexpr static float slewMax = 2.0 / 0.01f; | ||||
struct AudioCVModeParam : ParamQuantity { | |||||
std::string getDisplayValueString() override { | |||||
switch (static_cast<CrossfadeMode>(getValue())) { | |||||
case AUDIO_MODE: return "Audio"; | |||||
case CV_MODE: return "CV"; | |||||
default: assert(false); | |||||
} | |||||
} | |||||
}; | |||||
Morphader() { | Morphader() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(CV_PARAM, 0.f, 1.f, 1.f, "CV"); | |||||
configParam(CV_PARAM, 0.f, 1.f, 1.f, "CV attenuator"); | |||||
for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | ||||
configParam(A_LEVEL + i, 0.f, 1.f, 0.f, "A level " + std::to_string(i + 1)); | |||||
configParam(A_LEVEL + i, 0.f, 1.f, 0.f, string::f("A level %d", i + 1)); | |||||
configInput(A_INPUT + i, string::f("A%d", i + 1)); | |||||
} | } | ||||
for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | ||||
configParam(B_LEVEL + i, 0.f, 1.f, 0.f, "B level " + std::to_string(i + 1)); | |||||
configParam(B_LEVEL + i, 0.f, 1.f, 0.f, string::f("B level %d", i + 1)); | |||||
configInput(B_INPUT + i, string::f("B%d", i + 1)); | |||||
} | } | ||||
for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | for (int i = 0; i < NUM_MIXER_CHANNELS; i++) { | ||||
configParam<AudioCVModeParam>(MODE + i, AUDIO_MODE, CV_MODE, AUDIO_MODE, "Mode " + std::to_string(i + 1)); | |||||
configSwitch(MODE + i, AUDIO_MODE, CV_MODE, AUDIO_MODE, string::f("Mode %d", i + 1), {"Audio", "CV"}); | |||||
configInput(CV_INPUT + i, string::f("CV channel %d", i + 1)); | |||||
} | } | ||||
configParam(FADER_LAG_PARAM, 2.0f / slewMax, 2.0f / slewMin, 2.0f / slewMax, "Fader lag", "s"); | configParam(FADER_LAG_PARAM, 2.0f / slewMax, 2.0f / slewMin, 2.0f / slewMax, "Fader lag", "s"); | ||||
@@ -905,14 +905,6 @@ struct MuxlicerWidget : ModuleWidget { | |||||
} | } | ||||
}; | }; | ||||
struct OutputClockStopStartItem : MenuItem { | |||||
Muxlicer* module; | |||||
void onAction(const event::Action& e) override { | |||||
module->outputClockFollowsPlayMode ^= true; | |||||
module->updateParamFromMainClockMultDiv(); | |||||
} | |||||
}; | |||||
struct TapTempoItem : MenuItem { | struct TapTempoItem : MenuItem { | ||||
Muxlicer* module; | Muxlicer* module; | ||||
void onAction(const event::Action& e) override { | void onAction(const event::Action& e) override { | ||||
@@ -930,7 +922,6 @@ struct MuxlicerWidget : ModuleWidget { | |||||
if (module->usingExternalClock) { | if (module->usingExternalClock) { | ||||
menu->addChild(createMenuLabel<MenuLabel>("Using external clock")); | menu->addChild(createMenuLabel<MenuLabel>("Using external clock")); | ||||
} | } | ||||
else { | else { | ||||
TapTempoItem* tapTempoItem = createMenuItem<TapTempoItem>("Tap to set internal tempo..."); | TapTempoItem* tapTempoItem = createMenuItem<TapTempoItem>("Tap to set internal tempo..."); | ||||
@@ -962,10 +953,7 @@ struct MuxlicerWidget : ModuleWidget { | |||||
menu->addChild(createMenuLabel<MenuLabel>("All In Normalled Value (disabled)")); | menu->addChild(createMenuLabel<MenuLabel>("All In Normalled Value (disabled)")); | ||||
} | } | ||||
OutputClockStopStartItem* outputClockStopStartItem = | |||||
createMenuItem<OutputClockStopStartItem>("Output clock follows play/stop", CHECKMARK(module->quadraticGatesOnly)); | |||||
outputClockStopStartItem->module = module; | |||||
menu->addChild(outputClockStopStartItem); | |||||
menu->addChild(createBoolPtrMenuItem("Output clock follows play/stop", &module->outputClockFollowsPlayMode)); | |||||
menu->addChild(new MenuSeparator()); | menu->addChild(new MenuSeparator()); | ||||
menu->addChild(createMenuLabel<MenuLabel>("Input/Output mode")); | menu->addChild(createMenuLabel<MenuLabel>("Input/Output mode")); | ||||
@@ -44,12 +44,19 @@ struct Percall : Module { | |||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
configParam(VOL_PARAMS + i, 0.f, 1.f, 1.f, string::f("Channel %d level", i + 1), "%", 0, 100); | configParam(VOL_PARAMS + i, 0.f, 1.f, 1.f, string::f("Channel %d level", i + 1), "%", 0, 100); | ||||
configParam(DECAY_PARAMS + i, 0.f, 1.f, 0.f, string::f("Channel %d decay time", i + 1)); | configParam(DECAY_PARAMS + i, 0.f, 1.f, 0.f, string::f("Channel %d decay time", i + 1)); | ||||
configInput(CH_INPUTS + i, string::f("Channel %d", i + 1)); | |||||
configInput(TRIG_INPUTS + i, string::f("Channel %d trigger", i + 1)); | |||||
configInput(CV_INPUTS + i, string::f("Channel %d CV", i + 1)); | |||||
configOutput(ENV_OUTPUTS + i, string::f("Channel %d envelope", i + 1)); | |||||
envs[i].attackTime = attackTime; | envs[i].attackTime = attackTime; | ||||
envs[i].attackShape = 0.5f; | envs[i].attackShape = 0.5f; | ||||
envs[i].decayShape = 2.0f; | envs[i].decayShape = 2.0f; | ||||
} | } | ||||
for (int i = 0; i < 2; i++) { | |||||
configInput(STRENGTH_INPUT, string::f("Overall gain (also affects Env Outs)")); | |||||
for (int i = 0; i < 2; i++) { | |||||
configParam(CHOKE_PARAMS + i, 0.f, 1.f, 0.f, string::f("Choke %d to %d", 2 * i + 1, 2 * i + 2)); | configParam(CHOKE_PARAMS + i, 0.f, 1.f, 0.f, string::f("Choke %d to %d", 2 * i + 1, 2 * i + 2)); | ||||
} | } | ||||
@@ -85,19 +85,44 @@ struct Rampage : Module { | |||||
Rampage() { | Rampage() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(RANGE_A_PARAM, 0.0, 2.0, 0.0, "Ch 1 range"); | |||||
configSwitch(RANGE_A_PARAM, 0.0, 2.0, 0.0, "Ch 1 range", {"Medium", "Fast", "Slow"}); | |||||
configParam(SHAPE_A_PARAM, -1.0, 1.0, 0.0, "Ch 1 shape"); | configParam(SHAPE_A_PARAM, -1.0, 1.0, 0.0, "Ch 1 shape"); | ||||
configParam(TRIGG_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 trigger"); | |||||
configButton(TRIGG_A_PARAM, "Ch 1 trigger"); | |||||
configParam(RISE_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 rise time"); | configParam(RISE_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 rise time"); | ||||
configParam(FALL_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 fall time"); | configParam(FALL_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 fall time"); | ||||
configParam(CYCLE_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 cycle"); | |||||
configParam(RANGE_B_PARAM, 0.0, 2.0, 0.0, "Ch 2 range"); | |||||
configSwitch(CYCLE_A_PARAM, 0.0, 1.0, 0.0, "Ch 1 cycle", {"Off", "On"}); | |||||
configSwitch(RANGE_B_PARAM, 0.0, 2.0, 0.0, "Ch 2 range", {"Medium", "Fast", "Slow"}); | |||||
configParam(SHAPE_B_PARAM, -1.0, 1.0, 0.0, "Ch 2 shape"); | configParam(SHAPE_B_PARAM, -1.0, 1.0, 0.0, "Ch 2 shape"); | ||||
configParam(TRIGG_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 trigger"); | |||||
configButton(TRIGG_B_PARAM, "Ch 2 trigger"); | |||||
configParam(RISE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 rise time"); | configParam(RISE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 rise time"); | ||||
configParam(FALL_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 fall time"); | configParam(FALL_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 fall time"); | ||||
configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); | |||||
configSwitch(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle", {"Off", "On"}); | |||||
configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); | configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); | ||||
configInput(IN_A_INPUT, "A"); | |||||
configInput(IN_B_INPUT, "B"); | |||||
configInput(TRIGG_A_INPUT, "Trigger A"); | |||||
configInput(TRIGG_B_INPUT, "Trigger B"); | |||||
configInput(RISE_CV_A_INPUT, "Rise CV A"); | |||||
configInput(RISE_CV_B_INPUT, "Rise CV B"); | |||||
configInput(FALL_CV_A_INPUT, "Fall CV A"); | |||||
configInput(FALL_CV_B_INPUT, "Fall CV B"); | |||||
configInput(EXP_CV_A_INPUT, "Exponetial CV A"); | |||||
configInput(EXP_CV_B_INPUT, "Exponetial CV B"); | |||||
configInput(CYCLE_A_INPUT, "Cycle A"); | |||||
configInput(CYCLE_B_INPUT, "Cycle B"); | |||||
configOutput(RISING_A_OUTPUT, "Rising A"); | |||||
configOutput(RISING_B_OUTPUT, "Rising B"); | |||||
configOutput(FALLING_A_OUTPUT, "Falling A"); | |||||
configOutput(FALLING_B_OUTPUT, "Falling B"); | |||||
configOutput(EOC_A_OUTPUT, "End of cycle A"); | |||||
configOutput(EOC_B_OUTPUT, "End of cycle B"); | |||||
configOutput(OUT_A_OUTPUT, "A"); | |||||
configOutput(OUT_B_OUTPUT, "B"); | |||||
configOutput(COMPARATOR_OUTPUT, "B > A"); | |||||
configOutput(MIN_OUTPUT, "Minimum of A and B"); | |||||
configOutput(MAX_OUTPUT, "Maximum of A and B"); | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
@@ -32,7 +32,13 @@ struct STMix : Module { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
for (int i = 0; i < numMixerChannels; ++i) { | for (int i = 0; i < numMixerChannels; ++i) { | ||||
configParam(GAIN_PARAM + i, 0.f, 1.f, 0.f, string::f("Gain %d", i + 1)); | configParam(GAIN_PARAM + i, 0.f, 1.f, 0.f, string::f("Gain %d", i + 1)); | ||||
configInput(LEFT_INPUT + i, string::f("Channel %d left", i + 1)); | |||||
configInput(RIGHT_INPUT + i, string::f("Channel %d right", i + 1)); | |||||
} | } | ||||
configInput(LEFT_INPUT + numMixerChannels, "Channel left (aux)"); | |||||
configInput(RIGHT_INPUT + numMixerChannels, "Channel right (aux)"); | |||||
configOutput(LEFT_OUTPUT, "Left"); | |||||
configOutput(RIGHT_OUTPUT, "Right"); | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||
@@ -41,38 +41,6 @@ struct SamplingModulator : Module { | |||||
CLOCK_INTERNAL | CLOCK_INTERNAL | ||||
}; | }; | ||||
struct ClockTypeParam : ParamQuantity { | |||||
std::string getDisplayValueString() override { | |||||
if (module != nullptr && paramId == INT_EXT_PARAM) { | |||||
return (module->params[INT_EXT_PARAM].getValue() == CLOCK_EXTERNAL) ? "External" : "Internal"; | |||||
} | |||||
else { | |||||
return ""; | |||||
} | |||||
} | |||||
}; | |||||
struct StepTypeParam : ParamQuantity { | |||||
std::string getDisplayValueString() override { | |||||
if (module != nullptr && STEP_PARAM <= paramId && STEP_PARAM < STEP_PARAM_LAST) { | |||||
StepState stepState = (StepState) module->params[paramId].getValue(); | |||||
if (stepState == STATE_RESET) { | |||||
return "Reset"; | |||||
} | |||||
else if (stepState == STATE_OFF) { | |||||
return "Off"; | |||||
} | |||||
else { | |||||
return "On"; | |||||
} | |||||
} | |||||
else { | |||||
return ""; | |||||
} | |||||
} | |||||
}; | |||||
int numEffectiveSteps = numSteps; | int numEffectiveSteps = numSteps; | ||||
int currentStep = 0; | int currentStep = 0; | ||||
StepState stepStates[numSteps]; | StepState stepStates[numSteps]; | ||||
@@ -94,10 +62,10 @@ struct SamplingModulator : Module { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(RATE_PARAM, 0.0f, 1.f, 0.f, "Rate"); | configParam(RATE_PARAM, 0.0f, 1.f, 0.f, "Rate"); | ||||
configParam(FINE_PARAM, 0.f, 1.f, 0.f, "Fine tune"); | configParam(FINE_PARAM, 0.f, 1.f, 0.f, "Fine tune"); | ||||
configParam<ClockTypeParam>(INT_EXT_PARAM, 0.f, 1.f, CLOCK_INTERNAL, "Clock"); | |||||
configSwitch(INT_EXT_PARAM, 0.f, 1.f, CLOCK_INTERNAL, "Clock", {"External", "Internal"}); | |||||
for (int i = 0; i < numSteps; i++) { | for (int i = 0; i < numSteps; i++) { | ||||
configParam<StepTypeParam>(STEP_PARAM + i, 0.f, 2.f, STATE_ON, "Step " + std::to_string(i + 1)); | |||||
configSwitch(STEP_PARAM + i, 0.f, 2.f, STATE_ON, string::f("Step %d", i + 1), {"Reset", "Off", "On"}); | |||||
} | } | ||||
} | } | ||||
@@ -287,22 +255,12 @@ struct SamplingModulatorWidget : ModuleWidget { | |||||
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(23.722, 94.617)), module, SamplingModulator::STEP_LIGHT + 7)); | addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(23.722, 94.617)), module, SamplingModulator::STEP_LIGHT + 7)); | ||||
} | } | ||||
struct DCMenuItem : MenuItem { | |||||
SamplingModulator* module; | |||||
void onAction(const event::Action& e) override { | |||||
module->removeDC ^= true; | |||||
} | |||||
}; | |||||
void appendContextMenu(Menu* menu) override { | void appendContextMenu(Menu* menu) override { | ||||
SamplingModulator* module = dynamic_cast<SamplingModulator*>(this->module); | SamplingModulator* module = dynamic_cast<SamplingModulator*>(this->module); | ||||
assert(module); | assert(module); | ||||
menu->addChild(new MenuSeparator()); | menu->addChild(new MenuSeparator()); | ||||
DCMenuItem* dcItem = createMenuItem<DCMenuItem>("Remove DC Offset", CHECKMARK(module->removeDC)); | |||||
dcItem->module = module; | |||||
menu->addChild(dcItem); | |||||
menu->addChild(createBoolPtrMenuItem("Remove DC Offset", &module->removeDC)); | |||||
} | } | ||||
}; | }; | ||||
@@ -28,6 +28,9 @@ struct SlewLimiter : Module { | |||||
configParam(RISE_PARAM, 0.0, 1.0, 0.0, "Rise time"); | configParam(RISE_PARAM, 0.0, 1.0, 0.0, "Rise time"); | ||||
configParam(FALL_PARAM, 0.0, 1.0, 0.0, "Fall time"); | configParam(FALL_PARAM, 0.0, 1.0, 0.0, "Fall time"); | ||||
configBypass(IN_INPUT, OUT_OUTPUT); | configBypass(IN_INPUT, OUT_OUTPUT); | ||||
configInput(RISE_INPUT, "Rise CV"); | |||||
configInput(FALL_INPUT, "Fall CV"); | |||||
} | } | ||||
void process(const ProcessArgs& args) override { | void process(const ProcessArgs& args) override { | ||||