Function bodies 1,902 total
appendContextMenu method · cpp · L720-L726 (7 LOC)src/Drummmmmmer.cpp
void appendContextMenu(Menu* menu) override {
Drummmmmmer* module = dynamic_cast<Drummmmmmer*>(this->module);
if (!module) return;
addPanelThemeMenu(menu, module);
}draw method · cpp · L732-L784 (53 LOC)src/Drummmmmmer.cpp
void WDDynamicRoleTitle::draw(const DrawArgs &args) {
NVGcolor color = nvgRGB(255, 255, 255);
// Determine display text
std::string displayText = text;
if (module) {
color = STYLE_COLORS[module->currentStyle];
if (roleIndex >= 0 && roleIndex < 4) {
int voiceIdx = roleIndex * 2 + module->lastTriggeredVoice[roleIndex];
displayText = DRUMMER_PRESETS[module->currentStyle].voices[voiceIdx].name;
}
}
float cx = box.size.x / 2.f;
nvgFontSize(args.vg, fontSize);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
// Check if name contains a space (split into two lines if so)
std::string line1, line2;
size_t spacePos = displayText.find(' ');
bool twoLines = (spacePos != std::string::npos);
if (twoLines) {
line1 = displayText.substr(0, spacePos);
line2 = displayText.substr(spacePos + 1);
} else {
lindraw method · cpp · L24-L41 (18 LOC)src/EllenRipley.cpp
void draw(const DrawArgs &args) override {
nvgFontSize(args.vg, fontSize);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
if (bold) {
// 使用描邊模擬粗體效果
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, 0.3f);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
} else {
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
}
}WhiteBackgroundBox method · cpp · L45-L48 (4 LOC)src/EllenRipley.cpp
WhiteBackgroundBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L49-L59 (11 LOC)src/EllenRipley.cpp
void draw(const DrawArgs &args) override {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
nvgStrokeColor(args.vg, nvgRGBA(200, 200, 200, 255));
nvgStroke(args.vg);
}reset method · cpp · L69-L74 (6 LOC)src/EllenRipley.cpp
void reset() {
x = 0.1f;
y = 0.1f;
z = 0.1f;
}process method · cpp · L75-L94 (20 LOC)src/EllenRipley.cpp
float process(float rate) {
float dt = rate * 0.001f;
float dx = 7.5f * (y - x);
float dy = x * (30.9f - z) - y;
float dz = x * y - 1.02f * z;
x += dx * dt;
y += dy * dt;
z += dz * dt;
// Prevent numerical explosion
if (std::isnan(x) || std::isnan(y) || std::isnan(z) ||
std::abs(x) > 100.0f || std::abs(y) > 100.0f || std::abs(z) > 100.0f) {
reset();
}
return clamp(x * 0.1f, -1.0f, 1.0f);
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
reset method · cpp · L141-L164 (24 LOC)src/EllenRipley.cpp
void reset() {
for (int i = 0; i < COMB_1_SIZE; i++) combBuffer1[i] = 0.0f;
for (int i = 0; i < COMB_2_SIZE; i++) combBuffer2[i] = 0.0f;
for (int i = 0; i < COMB_3_SIZE; i++) combBuffer3[i] = 0.0f;
for (int i = 0; i < COMB_4_SIZE; i++) combBuffer4[i] = 0.0f;
for (int i = 0; i < COMB_5_SIZE; i++) combBuffer5[i] = 0.0f;
for (int i = 0; i < COMB_6_SIZE; i++) combBuffer6[i] = 0.0f;
for (int i = 0; i < COMB_7_SIZE; i++) combBuffer7[i] = 0.0f;
for (int i = 0; i < COMB_8_SIZE; i++) combBuffer8[i] = 0.0f;
for (int i = 0; i < ALLPASS_1_SIZE; i++) allpassBuffer1[i] = 0.0f;
for (int i = 0; i < ALLPASS_2_SIZE; i++) allpassBuffer2[i] = 0.0f;
for (int i = 0; i < ALLPASS_3_SIZE; i++) allpassBuffer3[i] = 0.0f;
for (int i = 0; i < ALLPASS_4_SIZE; i++) allpassBuffer4[i] = 0.0f;
combIndex1 = combIndex2 = combIndex3 = combIndex4 = 0;
combIndex5 = combIndex6 = combIndexprocessComb method · cpp · L165-L177 (13 LOC)src/EllenRipley.cpp
float processComb(float input, float* buffer, int size, int& index, float feedback, float& lp, float damping) {
float output = buffer[index];
// Apply lowpass filter to feedback signal
lp = lp + (output - lp) * damping;
// Write input + filtered feedback
buffer[index] = input + lp * feedback;
index = (index + 1) % size;
return output;
}processAllpass method · cpp · L178-L185 (8 LOC)src/EllenRipley.cpp
float processAllpass(float input, float* buffer, int size, int& index, float gain) {
float delayed = buffer[index];
float output = -input * gain + delayed;
buffer[index] = input + delayed * gain;
index = (index + 1) % size;
return output;
}process method · cpp · L186-L279 (94 LOC)src/EllenRipley.cpp
float process(float inputL, float inputR, float grainDensity,
float roomSize, float damping, float decay, bool isLeftChannel,
bool chaosEnabled, float chaosOutput, float sampleRate) {
// Use proper stereo input instead of mixing to mono
float input = isLeftChannel ? inputL : inputR;
// Calculate feedback based on decay - much wider range for 10+ second tails
float feedback = 0.5f + decay * 0.485f; // 0.5 to 0.985 (near infinite at max)
if (chaosEnabled) {
feedback += chaosOutput * 0.5f; // Enhanced chaos effect 10x from 0.05f
feedback = clamp(feedback, 0.0f, 0.995f);
}
// Damping: low value = more damping (darker), high value = less damping (brighter)
float dampingCoeff = 0.05f + damping * 0.9f;
// Room size affects delay buffer read positions dramatically
float roomScale = 0.3f + roomSize * 1.4f; // 0.3reset method · cpp · L301-L312 (12 LOC)src/EllenRipley.cpp
void reset() {
for (int i = 0; i < GRAIN_BUFFER_SIZE; i++) {
grainBuffer[i] = 0.0f;
}
grainWriteIndex = 0;
for (int i = 0; i < MAX_GRAINS; i++) {
grains[i].active = false;
}
phase = 0.0f;
}process method · cpp · L313-L409 (97 LOC)src/EllenRipley.cpp
float process(float input, float grainSize, float density, float position,
bool chaosEnabled, float chaosOutput, float sampleRate) {
grainBuffer[grainWriteIndex] = input;
grainWriteIndex = (grainWriteIndex + 1) % GRAIN_BUFFER_SIZE;
float grainSizeMs = grainSize * 99.0f + 1.0f;
float grainSamples = (grainSizeMs / 1000.0f) * sampleRate;
float densityValue = density;
if (chaosEnabled) {
densityValue += chaosOutput * 0.3f;
}
densityValue = clamp(densityValue, 0.0f, 1.0f);
float triggerRate = densityValue * 50.0f + 1.0f;
phase += triggerRate / sampleRate;
if (phase >= 1.0f) {
phase -= 1.0f;
for (int i = 0; i < MAX_GRAINS; i++) {
if (!grains[i].active) {
grains[i].active = true;
grains[i].size = grainSamples;
gEllenRipley method · cpp · L491-L545 (55 LOC)src/EllenRipley.cpp
EllenRipley() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(DELAY_TIME_L_PARAM, 0.001f, 2.0f, 0.25f, "Delay Time L", " s");
configParam(DELAY_TIME_R_PARAM, 0.001f, 2.0f, 0.25f, "Delay Time R", " s");
configParam(DELAY_FEEDBACK_PARAM, 0.0f, 0.95f, 0.3f, "Feedback", "%", 0.f, 100.f);
configParam(DELAY_CHAOS_PARAM, 0.0f, 1.0f, 0.0f, "Delay Chaos");
configParam(WET_DRY_PARAM, 0.0f, 1.0f, 0.0f, "Delay Wet/Dry", "%", 0.f, 100.f);
configParam(CHAOS_RATE_PARAM, 0.0f, 1.0f, 0.01f, "Chaos Rate");
configParam(GRAIN_SIZE_PARAM, 0.0f, 1.0f, 0.3f, "Grain Size");
configParam(GRAIN_DENSITY_PARAM, 0.0f, 1.0f, 0.4f, "Grain Density/Glitch");
configParam(GRAIN_POSITION_PARAM, 0.0f, 1.0f, 0.5f, "Grain Position/Chaos");
configParam(GRAIN_CHAOS_PARAM, 0.0f, 1.0f, 0.0f, "Grain Chaos");
configParam(GRAIN_WET_DRY_PARAM, 0.0f, 1.0f, 0.0f, "Gratch Wet/Dry", "%", 0.f, 100.f);
onReset method · cpp · L546-L560 (15 LOC)src/EllenRipley.cpp
void onReset() override {
for (int c = 0; c < MAX_POLY; c++) {
chaosGen[c].reset();
leftGrainProcessor[c].reset();
rightGrainProcessor[c].reset();
leftReverbProcessor[c].reset();
rightReverbProcessor[c].reset();
for (int i = 0; i < DELAY_BUFFER_SIZE; i++) {
leftDelayBuffer[c][i] = 0.0f;
rightDelayBuffer[c][i] = 0.0f;
}
delayWriteIndex[c] = 0;
}
}Repobility · open methodology · https://repobility.com/research/
dataToJson method · cpp · L561-L567 (7 LOC)src/EllenRipley.cpp
json_t* dataToJson() override {
json_t* rootJ = json_object();
json_object_set_new(rootJ, "panelTheme", json_integer(panelTheme));
json_object_set_new(rootJ, "panelContrast", json_real(panelContrast));
return rootJ;
}dataFromJson method · cpp · L568-L578 (11 LOC)src/EllenRipley.cpp
void dataFromJson(json_t* rootJ) override {
json_t* themeJ = json_object_get(rootJ, "panelTheme");
if (themeJ) {
panelTheme = json_integer_value(themeJ);
}
json_t* contrastJ = json_object_get(rootJ, "panelContrast");
if (contrastJ) {
panelContrast = json_real_value(contrastJ);
}
}process method · cpp · L579-L813 (235 LOC)src/EllenRipley.cpp
void process(const ProcessArgs& args) override {
// Defensive checks
if (args.sampleRate <= 0) return;
if (!std::isfinite(args.sampleTime)) return;
// Get polyphonic channel count
int leftChannels = inputs[LEFT_AUDIO_INPUT].getChannels();
int rightChannels = inputs[RIGHT_AUDIO_INPUT].getChannels();
int channels = std::max({1, leftChannels, rightChannels});
// Set output channels
outputs[LEFT_AUDIO_OUTPUT].setChannels(channels);
outputs[RIGHT_AUDIO_OUTPUT].setChannels(channels);
outputs[CHAOS_CV_OUTPUT].setChannels(channels);
delayChaosMod = params[DELAY_CHAOS_PARAM].getValue() > 0.5f;
grainChaosMod = params[GRAIN_CHAOS_PARAM].getValue() > 0.5f;
reverbChaosMod = params[REVERB_CHAOS_PARAM].getValue() > 0.5f;
// Set lights (monophonic)
lights[DELAY_CHAOS_LIGHT].setBrightness(delayChaosMod ? 1.0f : 0.0f);
lights[GRAIN_CHAOS_LIGHT].setBrightnesprocessBypass method · cpp · L814-L835 (22 LOC)src/EllenRipley.cpp
void processBypass(const ProcessArgs& args) override {
int leftChannels = inputs[LEFT_AUDIO_INPUT].getChannels();
int rightChannels = inputs[RIGHT_AUDIO_INPUT].getChannels();
int channels = std::max({1, leftChannels, rightChannels});
outputs[LEFT_AUDIO_OUTPUT].setChannels(channels);
outputs[RIGHT_AUDIO_OUTPUT].setChannels(channels);
for (int c = 0; c < channels; c++) {
float leftInput = (c < leftChannels) ? inputs[LEFT_AUDIO_INPUT].getPolyVoltage(c) : 0.0f;
float rightInput = 0.0f;
if (inputs[RIGHT_AUDIO_INPUT].isConnected()) {
rightInput = (c < rightChannels) ? inputs[RIGHT_AUDIO_INPUT].getPolyVoltage(c) : 0.0f;
} else {
rightInput = leftInput;
}
outputs[LEFT_AUDIO_OUTPUT].setVoltage(leftInput, c);
outputs[RIGHT_AUDIO_OUTPUT].setVoltage(rightInput, c);
}
}EllenRipleyWidget method · cpp · L849-L974 (126 LOC)src/EllenRipley.cpp
EllenRipleyWidget(EllenRipley* module) {
setModule(module);
panelThemeHelper.init(this, "12HP", module ? &module->panelContrast : nullptr);
box.size = Vec(8 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
addChild(new EnhancedTextLabel(Vec(0, 1), Vec(box.size.x, 20), "Ellen Ripley", 14.f, nvgRGB(255, 200, 0), true));
addChild(new EnhancedTextLabel(Vec(0, 13), Vec(box.size.x, 20), "MADZINE", 10.f, nvgRGB(255, 200, 0), false));
addChild(new EnhancedTextLabel(Vec(0, 30), Vec(box.size.x, 15), "DELAY"));
float delayY = 46;
float x = 1;
addChild(new EnhancedTextLabel(Vec(x, delayY), Vec(25, 10), "TIME L"));
delayTimeLKnob = createParamCentered<StandardBlackKnob26>(Vec(x + 12, delayY + 22), module, EllenRipley::DELAY_TIME_L_PARAM);
addParam(delayTimeLKnob);
addInput(createInputCentered<PJ301MPort>(Vec(x + 12, delayY + 47), module, EllenRipley::DELAY_TIME_L_CV_INPUT));
x += 31;
step method · cpp · L975-L1001 (27 LOC)src/EllenRipley.cpp
void step() override {
EllenRipley* module = dynamic_cast<EllenRipley*>(this->module);
if (module) {
panelThemeHelper.step(module);
// 更新 CV 調變顯示
auto updateKnob = [&](StandardBlackKnob26* knob, int inputId, float cvMod) {
if (knob) {
bool connected = module->inputs[inputId].isConnected();
knob->setModulationEnabled(connected);
if (connected) knob->setModulation(cvMod);
}
};
updateKnob(delayTimeLKnob, EllenRipley::DELAY_TIME_L_CV_INPUT, module->delayTimeLCvMod);
updateKnob(delayTimeRKnob, EllenRipley::DELAY_TIME_R_CV_INPUT, module->delayTimeRCvMod);
updateKnob(delayFeedbackKnob, EllenRipley::DELAY_FEEDBACK_CV_INPUT, module->delayFeedbackCvMod);
updateKnob(grainSizeKnob, EllenRipley::GRAIN_SIZE_CV_INPUT, module->grainSizeCvMod);
updateKnob(grainDensityKnob, EllenRipleappendContextMenu method · cpp · L1002-L1008 (7 LOC)src/EllenRipley.cpp
void appendContextMenu(ui::Menu* menu) override {
EllenRipley* module = dynamic_cast<EllenRipley*>(this->module);
if (!module) return;
addPanelThemeMenu(menu, module);
}draw method · cpp · L22-L39 (18 LOC)src/EnvVCA6.cpp
void draw(const DrawArgs &args) override {
nvgFontSize(args.vg, fontSize);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
if (bold) {
// 使用描邊模擬粗體效果
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, 0.3f);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
} else {
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
}
}All rows scored by the Repobility analyzer (https://repobility.com)
WhiteBackgroundBox method · cpp · L44-L47 (4 LOC)src/EnvVCA6.cpp
WhiteBackgroundBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L48-L58 (11 LOC)src/EnvVCA6.cpp
void draw(const DrawArgs &args) override {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
nvgStrokeColor(args.vg, nvgRGBA(200, 200, 200, 255));
nvgStroke(args.vg);
}reset method · cpp · L84-L91 (8 LOC)src/EnvVCA6.cpp
void reset() {
phase = IDLE;
triggerOutput = 0.0f;
followerOutput = 0.0f;
phaseTime = 0.0f;
followerState = 0.0f;
}applyCurve method · cpp · L92-L109 (18 LOC)src/EnvVCA6.cpp
float applyCurve(float x, float curvature) {
x = clamp(x, 0.0f, 1.0f);
if (curvature == 0.0f) {
return x;
}
float k = curvature;
float abs_x = std::abs(x);
float denominator = k - 2.0f * k * abs_x + 1.0f;
if (std::abs(denominator) < 1e-6f) {
return x;
}
return (x - k * x) / denominator;
}processEnvelopeFollower method · cpp · L110-L136 (27 LOC)src/EnvVCA6.cpp
float processEnvelopeFollower(float triggerVoltage, float sampleTime, float attackTime, float releaseTime, float curve) {
attackCoeff = 1.0f - std::exp(-sampleTime / std::max(0.0005f, attackTime * 0.1f));
releaseCoeff = 1.0f - std::exp(-sampleTime / std::max(0.001f, releaseTime * 0.5f));
attackCoeff = clamp(attackCoeff, 0.0f, 1.0f);
releaseCoeff = clamp(releaseCoeff, 0.0f, 1.0f);
float rectified = std::abs(triggerVoltage) / 10.0f;
rectified = clamp(rectified, 0.0f, 1.0f);
float targetCoeff;
if (rectified > followerState) {
float progress = attackCoeff;
targetCoeff = applyCurve(progress, curve);
} else {
float progress = releaseCoeff;
targetCoeff = applyCurve(progress, curve);
}
targetCoeff = clamp(targetCoeff, 0.0f, 1.0f);
followerState += (rectified - followerState) * targetCoeff;
followerState = clamp(followerState, 0.0f, 1.processTriggerEnvelope method · cpp · L137-L199 (63 LOC)src/EnvVCA6.cpp
float processTriggerEnvelope(float triggerVoltage, float sampleTime, float attack, float decay, float curve) {
bool currentGateHigh = triggerVoltage > 1.0f;
// Trigger on rising edge (SchmittTrigger uses 0.1V low / 2.0V high thresholds)
if (trigger.process(triggerVoltage)) {
phase = ATTACK;
phaseTime = 0.0f;
}
// In AHR mode, detect gate release to start release phase
if (ahrMode && gateHigh && !currentGateHigh && phase == HOLD) {
phase = DECAY; // Start release phase
phaseTime = 0.0f;
}
gateHigh = currentGateHigh;
switch (phase) {
case IDLE:
triggerOutput = 0.0f;
break;
case ATTACK:
phaseTime += sampleTime;
if (phaseTime >= attack) {
if (ahrMode) {
phase = HOLD; // Go to hold phase in AHR mode
triggerOuprocess method · cpp · L200-L212 (13 LOC)src/EnvVCA6.cpp
float process(float sampleTime, float triggerVoltage, float attack, float decay) {
float attackTime = std::pow(10.0f, (attack - 0.5f) * 6.0f);
float decayTime = std::pow(10.0f, (decay - 0.5f) * 6.0f);
attackTime = std::max(0.001f, attackTime);
decayTime = std::max(0.001f, decayTime);
// Only use trigger envelope - gate voltage amplitude should NOT affect envelope output
float triggerEnv = processTriggerEnvelope(triggerVoltage, sampleTime, attackTime, decayTime, curve);
return triggerEnv;
}EnvVCA6 method · cpp · L349-L392 (44 LOC)src/EnvVCA6.cpp
EnvVCA6() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
// Configure parameters for all 6 channels (6 params per channel)
for (int i = 0; i < 6; i++) {
configParam(CH1_ATTACK_PARAM + i * 6, 0.f, 1.f, 0.1f, string::f("Ch %d Attack", i + 1));
configParam(CH1_RELEASE_PARAM + i * 6, 0.f, 1.f, 0.5f, string::f("Ch %d Release", i + 1));
configParam(CH1_OUT_VOL_PARAM + i * 6, 0.f, 1.f, 0.8f, string::f("Ch %d Out Volume", i + 1));
configParam(CH1_GATE_TRIG_PARAM + i * 6, 0.f, 1.f, 0.f, string::f("Ch %d Manual Gate (Momentary)", i + 1));
if (i < 5) { // Only CH1-5 have sum buttons
configParam(CH1_SUM_LATCH_PARAM + i * 6, 0.f, 1.f, 0.f, string::f("Ch %d Sum to Ch6", i + 1));
} else { // CH6 sum button is disabled/hidden
configParam(CH1_SUM_LATCH_PARAM + i * 6, 0.f, 1.f, 0.f, "Disabled");
}
configParam(CH1_ENV_MODE_PARAM + i * 6,Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
dataToJson method · cpp · L393-L399 (7 LOC)src/EnvVCA6.cpp
json_t* dataToJson() override {
json_t* rootJ = json_object();
json_object_set_new(rootJ, "panelTheme", json_integer(panelTheme));
json_object_set_new(rootJ, "panelContrast", json_real(panelContrast));
return rootJ;
}dataFromJson method · cpp · L400-L410 (11 LOC)src/EnvVCA6.cpp
void dataFromJson(json_t* rootJ) override {
json_t* themeJ = json_object_get(rootJ, "panelTheme");
if (themeJ) {
panelTheme = json_integer_value(themeJ);
}
json_t* contrastJ = json_object_get(rootJ, "panelContrast");
if (contrastJ) {
panelContrast = json_real_value(contrastJ);
}
}process method · cpp · L411-L549 (139 LOC)src/EnvVCA6.cpp
void process(const ProcessArgs& args) override {
for (int i = 0; i < 6; i++) {
// Get parameters for this channel (6 params per channel)
float attackParam = params[CH1_ATTACK_PARAM + i * 6].getValue();
float releaseParam = params[CH1_RELEASE_PARAM + i * 6].getValue();
float outVolParam = params[CH1_OUT_VOL_PARAM + i * 6].getValue();
bool manualGatePressed = params[CH1_GATE_TRIG_PARAM + i * 6].getValue() > 0.5f;
bool sumLatchPressed = params[CH1_SUM_LATCH_PARAM + i * 6].getValue() > 0.5f;
bool ahrMode = params[CH1_ENV_MODE_PARAM + i * 6].getValue() > 0.5f;
// Set envelope mode
envelopes[i].ahrMode = ahrMode;
// Get inputs
float inL = inputs[CH1_IN_L_INPUT + i * 4].getVoltage();
float inR = inputs[CH1_IN_R_INPUT + i * 4].getVoltage();
float gateIn = inputs[CH1_GATE_INPUT + i * 4].getVoltage();
float volCtrl EnvVCA6ClickableLight method · cpp · L555-L558 (4 LOC)src/EnvVCA6.cpp
EnvVCA6ClickableLight() {
box.size = Vec(10, 10);
}draw method · cpp · L559-L578 (20 LOC)src/EnvVCA6.cpp
void draw(const DrawArgs& args) override {
float brightness = 0.f;
if (module) {
brightness = module->params[paramId].getValue();
}
// Draw light
nvgBeginPath(args.vg);
nvgCircle(args.vg, box.size.x / 2, box.size.y / 2, 4);
nvgFillColor(args.vg, nvgRGB(brightness * 255, brightness * 133, brightness * 133));
nvgFill(args.vg);
// Draw border
nvgBeginPath(args.vg);
nvgCircle(args.vg, box.size.x / 2, box.size.y / 2, 4);
nvgStrokeColor(args.vg, nvgRGB(100, 100, 100));
nvgStrokeWidth(args.vg, 1.0);
nvgStroke(args.vg);
}onButton method · cpp · L579-L598 (20 LOC)src/EnvVCA6.cpp
void onButton(const event::Button& e) override {
if (e.button == GLFW_MOUSE_BUTTON_LEFT && module) {
if (e.action == GLFW_PRESS) {
// For manual gate: momentary press (paramId % 6 == 3 for CH1_GATE_TRIG_PARAM)
if (paramId % 6 == 3) { // Manual gate params
module->params[paramId].setValue(1.f);
} else { // For AHR mode and sum latch: toggle
float currentValue = module->params[paramId].getValue();
module->params[paramId].setValue(currentValue > 0.5f ? 0.f : 1.f);
}
} else if (e.action == GLFW_RELEASE) {
// For manual gate: release
if (paramId % 6 == 3) {
module->params[paramId].setValue(0.f);
}
}
}
OpaqueWidget::onButton(e);
}EnvVCA6Widget method · cpp · L603-L680 (78 LOC)src/EnvVCA6.cpp
EnvVCA6Widget(EnvVCA6* module) {
setModule(module);
panelThemeHelper.init(this, "12HP", module ? &module->panelContrast : nullptr);
box.size = Vec(12 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
// Add module name and brand labels
addChild(new EnhancedTextLabel(Vec(0, 1), Vec(box.size.x, 20), "E n v V C A 6", 14.f, nvgRGB(255, 200, 0), true));
addChild(new EnhancedTextLabel(Vec(0, 13), Vec(box.size.x, 20), "MADZINE", 10.f, nvgRGB(255, 200, 0), false));
addChild(new EnhancedTextLabel(Vec(0, 27), Vec(box.size.x, 12), "Collaborated with offthesky", 10.f, nvgRGB(255, 255, 255), false));
// White background for bottom section
addChild(new WhiteBackgroundBox(Vec(0, 330), Vec(box.size.x, 50)));
// Layout parameters for 6 channels
float channelHeight = 48.f; // Height per channel (增加間距)
float startY = 53.f; // Starting Y position (往下移動)
for (int i = 0; i < 6; i++) {
step method · cpp · L681-L688 (8 LOC)src/EnvVCA6.cpp
void step() override {
EnvVCA6* module = dynamic_cast<EnvVCA6*>(this->module);
if (module) {
panelThemeHelper.step(module);
}
ModuleWidget::step();
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
appendContextMenu method · cpp · L689-L730 (42 LOC)src/EnvVCA6.cpp
void appendContextMenu(ui::Menu* menu) override {
EnvVCA6* module = dynamic_cast<EnvVCA6*>(this->module);
if (!module) return;
menu->addChild(new MenuSeparator);
// Gate output mode selection
menu->addChild(createMenuLabel("Gate Output Mode"));
struct GateModeItem : MenuItem {
EnvVCA6* module;
int mode; // 0 = full cycle, 1 = end trigger, 2 = start+end
void onAction(const event::Action& e) override {
module->params[EnvVCA6::GATE_MODE_PARAM].setValue((float)mode);
}
void step() override {
int currentMode = (int)module->params[EnvVCA6::GATE_MODE_PARAM].getValue();
rightText = (currentMode == mode) ? "✓" : "";
MenuItem::step();
}
};
GateModeItem* fullCycleItem = createMenuItem<GateModeItem>("Full Cycle Gate", "Gate high during entire envelope");
fullCycleItem->module = moduonAction method · cpp · L702-L705 (4 LOC)src/EnvVCA6.cpp
void onAction(const event::Action& e) override {
module->params[EnvVCA6::GATE_MODE_PARAM].setValue((float)mode);
}step method · cpp · L706-L711 (6 LOC)src/EnvVCA6.cpp
void step() override {
int currentMode = (int)module->params[EnvVCA6::GATE_MODE_PARAM].getValue();
rightText = (currentMode == mode) ? "✓" : "";
MenuItem::step();
}draw method · cpp · L23-L40 (18 LOC)src/EuclideanRhythm.cpp
void draw(const DrawArgs &args) override {
nvgFontSize(args.vg, fontSize);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
if (bold) {
// 使用描邊模擬粗體效果
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, 0.3f);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
} else {
nvgFillColor(args.vg, color);
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
}
}WhiteBackgroundBox method · cpp · L44-L47 (4 LOC)src/EuclideanRhythm.cpp
WhiteBackgroundBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L48-L58 (11 LOC)src/EuclideanRhythm.cpp
void draw(const DrawArgs &args) override {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
nvgStrokeColor(args.vg, nvgRGBA(200, 200, 200, 255));
nvgStroke(args.vg);
}getDisplayValueString method · cpp · L66-L75 (10 LOC)src/EuclideanRhythm.cpp
std::string getDisplayValueString() override {
int value = (int)std::round(getValue());
if (value > 0) {
return string::f("%dx", value + 1);
} else if (value < 0) {
return string::f("1/%dx", -value + 1);
} else {
return "1x";
}
}generateEuclideanRhythm function · cpp · L77-L93 (17 LOC)src/EuclideanRhythm.cpp
std::vector<bool> generateEuclideanRhythm(int length, int fill, int shift) {
std::vector<bool> pattern(length, false);
if (fill == 0 || length == 0) return pattern;
if (fill > length) fill = length;
shift = shift % length;
if (shift < 0) shift += length;
for (int i = 0; i < fill; ++i) {
int index = (int)std::floor((float)i * length / fill);
pattern[index] = true;
}
std::rotate(pattern.begin(), pattern.begin() + shift, pattern.end());
return pattern;
}Repobility · open methodology · https://repobility.com/research/
reset method · cpp · L196-L206 (11 LOC)src/EuclideanRhythm.cpp
void reset() {
dividedProgressSeconds = 0.0f;
dividerCount = 0;
shouldStep = false;
prevMultipliedGate = false;
currentStep = 0;
pattern.clear();
gateState = false;
cycleCompleted = false;
}updateDivMult method · cpp · L207-L220 (14 LOC)src/EuclideanRhythm.cpp
void updateDivMult(int divMultParam) {
divMultValue = divMultParam;
if (divMultValue > 0) {
division = 1;
multiplication = divMultValue + 1;
} else if (divMultValue < 0) {
division = -divMultValue + 1;
multiplication = 1;
} else {
division = 1;
multiplication = 1;
}
}processClockDivMult method · cpp · L221-L256 (36 LOC)src/EuclideanRhythm.cpp
bool processClockDivMult(bool globalClock, float globalClockSeconds, float sampleTime) {
dividedClockSeconds = globalClockSeconds * (float)division;
multipliedClockSeconds = dividedClockSeconds / (float)multiplication;
gateSeconds = std::max(0.001f, multipliedClockSeconds * 0.5f);
if (globalClock) {
if (dividerCount < 1) {
dividedProgressSeconds = 0.0f;
} else {
dividedProgressSeconds += sampleTime;
}
++dividerCount;
if (dividerCount >= division) {
dividerCount = 0;
}
} else {
dividedProgressSeconds += sampleTime;
}
shouldStep = false;
if (dividedProgressSeconds < dividedClockSeconds) {
float multipliedProgressSeconds = dividedProgressSeconds / multipliedClockSecon