Function bodies 1,902 total
strip_html function · python · L50-L54 (5 LOC)Manual/generate_help_data.py
def strip_html(text):
text = re.sub(r'<[^>]+>', '', text)
text = html_module.unescape(text)
text = re.sub(r'\s+', ' ', text)
return text.strip()extract_entries function · python · L57-L65 (9 LOC)Manual/generate_help_data.py
def extract_entries(html_str):
entries = []
pattern = r'<b>([^<]+)</b>\s*[:\uff1a]\s*((?:(?!</li>|</ul>|</p>|<h3).)*)'
for m in re.finditer(pattern, html_str, re.DOTALL):
name = m.group(1).strip()
desc = strip_html(m.group(2)).strip()
if desc and len(name) < 50:
entries.append((name, desc))
return entriesescape_cpp function · python · L68-L73 (6 LOC)Manual/generate_help_data.py
def escape_cpp(s):
s = s.replace('\\', '\\\\')
s = s.replace('"', '\\"')
s = s.replace('\n', '\\n')
s = s.replace('\t', '\\t')
return smain function · python · L76-L156 (81 LOC)Manual/generate_help_data.py
def main():
modules_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'modules')
output_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'src', 'ManualHelpData.hpp')
lines = []
lines.append('// Auto-generated by Manual/generate_help_data.py')
lines.append('// Do not edit manually')
lines.append('#pragma once')
lines.append('#include <string>')
lines.append('#include <map>')
lines.append('#include <vector>')
lines.append('#include <algorithm>')
lines.append('')
lines.append('struct HelpEntry {')
lines.append(' std::string en;')
lines.append(' std::string zh;')
lines.append(' std::string ja;')
lines.append(' const std::string& get(const std::string& lang) const {')
lines.append(' if (lang == "zh") return zh;')
lines.append(' if (lang == "ja") return ja;')
lines.append(' return en;')
lines.append(' }')
lines.append('};')
lines.appendraw method · cpp · L20-L37 (18 LOC)src/ADGenerator.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 · L41-L44 (4 LOC)src/ADGenerator.cpp
WhiteBackgroundBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L45-L55 (11 LOC)src/ADGenerator.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);
}Repobility · code-quality intelligence · https://repobility.com
UFOWidget method · cpp · L60-L63 (4 LOC)src/ADGenerator.cpp
UFOWidget(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L64-L107 (44 LOC)src/ADGenerator.cpp
void draw(const DrawArgs &args) override {
float centerX = box.size.x / 2.0f;
float centerY = box.size.y / 2.0f;
nvgSave(args.vg);
nvgTranslate(args.vg, centerX, centerY);
nvgRotate(args.vg, 15.0f * M_PI / 180.0f);
nvgTranslate(args.vg, -centerX, -centerY);
nvgStrokeColor(args.vg, nvgRGB(255, 255, 255));
nvgBeginPath(args.vg);
nvgEllipse(args.vg, centerX, centerY, 12.0f, 4.0f);
nvgStrokeWidth(args.vg, 0.8f);
nvgStroke(args.vg);
nvgBeginPath(args.vg);
nvgEllipse(args.vg, centerX, centerY - 2.0f, 6.0f, 3.0f);
nvgStrokeWidth(args.vg, 0.6f);
nvgStroke(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
for (int i = 0; i < 5; ++i) {
float angle = i * 2.0f * M_PI / 5.0f;
float lightX = centerX + 8.0f * cosf(angle);
float lightY = centerY + 2.0f * sinf(angle);
FluteWidget method · cpp · L111-L114 (4 LOC)src/ADGenerator.cpp
FluteWidget(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L115-L175 (61 LOC)src/ADGenerator.cpp
void draw(const DrawArgs &args) override {
float centerX = box.size.x / 2.0f;
float centerY = box.size.y / 2.0f;
nvgSave(args.vg);
nvgTranslate(args.vg, centerX, centerY);
nvgRotate(args.vg, -15.0f * M_PI / 180.0f);
nvgTranslate(args.vg, -centerX, -centerY);
nvgStrokeWidth(args.vg, 0.8f);
nvgStrokeColor(args.vg, nvgRGB(255, 255, 255));
nvgBeginPath(args.vg);
nvgRect(args.vg, centerX - 15, centerY - 1.5f, 30, 3);
nvgStroke(args.vg);
nvgBeginPath(args.vg);
nvgRect(args.vg, centerX - 18, centerY - 1, 3, 2);
nvgStroke(args.vg);
nvgStrokeWidth(args.vg, 0.5f);
float holePositions[] = {-10, -6, -2, 2, 6, 10};
for (int i = 0; i < 6; ++i) {
nvgBeginPath(args.vg);
nvgCircle(args.vg, centerX + holePositions[i], centerY, 0.8f);
nvgStroke(args.vg);
}
HouseWidget method · cpp · L179-L182 (4 LOC)src/ADGenerator.cpp
HouseWidget(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L183-L250 (68 LOC)src/ADGenerator.cpp
void draw(const DrawArgs &args) override {
float centerX = box.size.x / 2.0f;
float centerY = box.size.y / 2.0f;
nvgSave(args.vg);
nvgTranslate(args.vg, centerX, centerY);
nvgRotate(args.vg, -10.0f * M_PI / 180.0f);
nvgTranslate(args.vg, -centerX, -centerY);
nvgStrokeWidth(args.vg, 0.8f);
nvgStrokeColor(args.vg, nvgRGB(255, 255, 255));
nvgBeginPath(args.vg);
nvgRect(args.vg, centerX - 8, centerY, 16, 10);
nvgStroke(args.vg);
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, centerX - 10, centerY);
nvgLineTo(args.vg, centerX, centerY - 8);
nvgLineTo(args.vg, centerX + 10, centerY);
nvgClosePath(args.vg);
nvgStroke(args.vg);
nvgStrokeWidth(args.vg, 0.6f);
nvgBeginPath(args.vg);
nvgRect(args.vg, centerX - 2, centerY + 4, 4, 6);
nvgStroke(args.vg);
nvgBereset method · cpp · L310-L314 (5 LOC)src/ADGenerator.cpp
void reset() {
ic1eq = 0.0f;
ic2eq = 0.0f;
}process method · cpp · L315-L332 (18 LOC)src/ADGenerator.cpp
float process(float input, float cutoff, float sampleRate) {
float g = std::tan(M_PI * clamp(cutoff, 20.0f, sampleRate * 0.49f) / sampleRate);
float k = 1.0f; // Q = 1.0
float a1 = 1.0f / (1.0f + g * (g + k));
float a2 = g * a1;
float a3 = g * a2;
float v3 = input - ic2eq;
float v1 = a1 * ic1eq + a2 * v3;
float v2 = ic2eq + a2 * ic1eq + a3 * v3;
ic1eq = 2.0f * v1 - ic1eq;
ic2eq = 2.0f * v2 - ic2eq;
// bandpass = v1
return v1;
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
reset method · cpp · L364-L374 (11 LOC)src/ADGenerator.cpp
void reset() {
phase = IDLE;
triggerOutput = 0.0f;
followerOutput = 0.0f;
followerState = 0.0f;
phaseTime = 0.0f;
oldPhase = IDLE;
oldOutput = 0.0f;
oldPhaseTime = 0.0f;
}applyCurve method · cpp · L375-L392 (18 LOC)src/ADGenerator.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 · L393-L419 (27 LOC)src/ADGenerator.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);
processTriggerEnvelope method · cpp · L420-L460 (41 LOC)src/ADGenerator.cpp
float processTriggerEnvelope(float triggerVoltage, float sampleTime, float attack, float decay, float curve) {
bool isHighVoltage = (std::abs(triggerVoltage) > 9.5f);
if (phase == IDLE && isHighVoltage && trigger.process(triggerVoltage)) {
phase = ATTACK;
phaseTime = 0.0f;
}
switch (phase) {
case IDLE:
triggerOutput = 0.0f;
break;
case ATTACK:
phaseTime += sampleTime;
if (phaseTime >= attack) {
phase = DECAY;
phaseTime = 0.0f;
triggerOutput = 1.0f;
} else {
float t = phaseTime / attack;
triggerOutput = applyCurve(t, curve);
}
break;
processOldVersion method · cpp · L461-L511 (51 LOC)src/ADGenerator.cpp
float processOldVersion(float sampleTime, float triggerVoltage, float attack, float decay, float curveParam, float atkAll, float decAll) {
float atkOffset = atkAll * 0.5f;
float decOffset = decAll * 0.5f;
oldAttackTime = std::pow(10.0f, (attack - 0.5f) * 6.0f) + atkOffset;
oldDecayTime = std::pow(10.0f, (decay - 0.5f) * 6.0f) + decOffset;
oldAttackTime = std::max(0.001f, oldAttackTime);
oldDecayTime = std::max(0.001f, oldDecayTime);
oldCurve = curveParam;
if (oldPhase == IDLE && oldTrigger.process(triggerVoltage)) {
oldPhase = ATTACK;
oldPhaseTime = 0.0f;
}
switch (oldPhase) {
case IDLE:
oldOutput = 0.0f;
break;
case ATTACK:
oldPhaseTime += sampprocess method · cpp · L512-L532 (21 LOC)src/ADGenerator.cpp
float process(float sampleTime, float triggerVoltage, float attack, float decay, float curveParam, float atkAll, float decAll, bool useBPF) {
if (!useBPF) {
return processOldVersion(sampleTime, triggerVoltage, attack, decay, curveParam, atkAll, decAll);
} else {
float atkOffset = atkAll * 0.5f;
float decOffset = decAll * 0.5f;
attackTime = std::pow(10.0f, (attack - 0.5f) * 6.0f) + atkOffset;
decayTime = std::pow(10.0f, (decay - 0.5f) * 6.0f) + decOffset;
attackTime = std::max(0.001f, attackTime);
decayTime = std::max(0.001f, decayTime);
curve = curveParam;
float output = processEnvelopeFollower(triggerVoltage, sampleTime, attackTime, decayTime, curve);
return output * 10.0f;
}
}ADGenerator method · cpp · L536-L578 (43 LOC)src/ADGenerator.cpp
ADGenerator() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
configParam(ATK_ALL_PARAM, -1.0f, 1.0f, 0.0f, "Attack All");
configParam(DEC_ALL_PARAM, -1.0f, 1.0f, 0.0f, "Decay All");
configParam(AUTO_ROUTE_PARAM, 0.0f, 1.0f, 1.0f, "Auto Route");
// Track 1 預設值來自 .vcvm
configParam(TRACK1_ATTACK_PARAM, 0.0f, 1.0f, 0.0020000000949949026f, "Track 1 Attack", " s", 0.0f, 1.0f, std::pow(10.0f, -2.0f));
configParam(TRACK1_DECAY_PARAM, 0.0f, 1.0f, 0.30000001192092896f, "Track 1 Decay", " s", 0.0f, 1.0f, std::pow(10.0f, -2.0f));
configParam(TRACK1_CURVE_PARAM, -0.99f, 0.99f, -0.74844002723693848f, "Track 1 Curve");
configParam(TRACK1_BPF_ENABLE_PARAM, 0.0f, 1.0f, 0.0f, "Track 1 BPF Enable");
configParam(TRACK1_BPF_FREQ_PARAM, 20.0f, 8000.0f, 200.0f, "Track 1 BPF Frequency", " Hz");
configParam(TRACK1_BPF_GAIN_PARAM, 0.1f, 100.0f, 3.0f, "Track 1 BPF Gain", "x");
// Track 2 預設值來自 .vcvonReset method · cpp · L579-L585 (7 LOC)src/ADGenerator.cpp
void onReset() override {
for (int i = 0; i < 3; ++i) {
envelopes[i].reset();
bpfFilters[i].reset();
}
}Repobility · open methodology · https://repobility.com/research/
dataToJson method · cpp · L586-L612 (27 LOC)src/ADGenerator.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));
json_object_set_new(rootJ, "autoRouteEnabled", json_boolean(autoRouteEnabled));
json_t* bpfEnabledJ = json_array();
for (int i = 0; i < 3; ++i) {
json_array_append_new(bpfEnabledJ, json_boolean(bpfEnabled[i]));
}
json_object_set_new(rootJ, "bpfEnabled", bpfEnabledJ);
json_t* bpfCutoffsJ = json_array();
for (int i = 0; i < 3; ++i) {
json_array_append_new(bpfCutoffsJ, json_real(bpfCutoffs[i]));
}
json_object_set_new(rootJ, "bpfCutoffs", bpfCutoffsJ);
json_t* bpfGainsJ = json_array();
for (int i = 0; i < 3; ++i) {
json_array_append_new(bpfGainsJ, json_real(bpfGains[i]));
}
json_object_set_new(rootJdataFromJson method · cpp · L613-L658 (46 LOC)src/ADGenerator.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);
}
json_t* autoRouteJ = json_object_get(rootJ, "autoRouteEnabled");
if (autoRouteJ) {
autoRouteEnabled = json_boolean_value(autoRouteJ);
}
json_t* bpfEnabledJ = json_object_get(rootJ, "bpfEnabled");
if (bpfEnabledJ) {
for (int i = 0; i < 3; ++i) {
json_t* enabledJ = json_array_get(bpfEnabledJ, i);
if (enabledJ) {
bpfEnabled[i] = json_boolean_value(enabledJ);
}
}
}
json_t* bpfCutoffsJ = json_object_get(rootJ, "bpfCutoffs");
if (bpfCutoffsJ) {
fprocess method · cpp · L659-L714 (56 LOC)src/ADGenerator.cpp
void process(const ProcessArgs& args) override {
float sumOutput = 0.0f;
float atkAll = params[ATK_ALL_PARAM].getValue();
float decAll = params[DEC_ALL_PARAM].getValue();
autoRouteEnabled = params[AUTO_ROUTE_PARAM].getValue() > 0.5f;
for (int i = 0; i < 3; ++i) {
bpfEnabled[i] = params[TRACK1_BPF_ENABLE_PARAM + i * 6].getValue() > 0.5f;
bpfCutoffs[i] = params[TRACK1_BPF_FREQ_PARAM + i * 6].getValue();
bpfGains[i] = params[TRACK1_BPF_GAIN_PARAM + i * 6].getValue();
}
float inputSignals[3];
if (autoRouteEnabled) {
float input1Signal = inputs[TRACK1_TRIG_INPUT].getVoltage();
inputSignals[0] = input1Signal;
inputSignals[1] = input1Signal;
inputSignals[2] = input1Signal;
} else {
inputSignals[0] = inputs[TRACK1_TRIG_INPUT].getVoltage();
inputSignals[1] = inputs[TRACK2_TRIG_ADGeneratorWidget method · cpp · L719-L792 (74 LOC)src/ADGenerator.cpp
ADGeneratorWidget(ADGenerator* module) {
setModule(module);
panelThemeHelper.init(this, "8HP", 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), "ADGenerator", 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 UFOWidget(Vec(80, 285), Vec(40, 25)));
addChild(new FluteWidget(Vec(78, 125), Vec(40, 25)));
addChild(new HouseWidget(Vec(80, 205), Vec(40, 25)));
addChild(new EnhancedTextLabel(Vec(15, 30), Vec(30, 15), "ATK ALL", 8.f, nvgRGB(255, 255, 255), true));
addParam(createParamCentered<Trimpot>(Vec(30, 50), module, ADGenerator::ATK_ALL_PARAM));
addChild(new EnhancedTextLabel(Vec(50, 30), Vec(30, 15), "DEC ALL", 8.f, nvgRGB(255, 255, 255), true));
addParam(crstep method · cpp · L793-L800 (8 LOC)src/ADGenerator.cpp
void step() override {
ADGenerator* module = dynamic_cast<ADGenerator*>(this->module);
if (module) {
panelThemeHelper.step(module);
}
ModuleWidget::step();
}appendContextMenu method · cpp · L801-L807 (7 LOC)src/ADGenerator.cpp
void appendContextMenu(ui::Menu* menu) override {
ADGenerator* module = dynamic_cast<ADGenerator*>(this->module);
if (!module) return;
addPanelThemeMenu(menu, module);
}setParams method · cpp · L11-L25 (15 LOC)src/ALEXANDERPLATZ.cpp
void setParams(float sampleRate, float freq, float gainDb, float Q = 1.41f) {
float A = std::pow(10.f, gainDb / 40.f);
float w0 = 2.f * M_PI * freq / sampleRate;
float cosw0 = std::cos(w0);
float sinw0 = std::sin(w0);
float alpha = sinw0 / (2.f * Q);
float a0 = 1.f + alpha / A;
b0 = (1.f + alpha * A) / a0;
b1 = (-2.f * cosw0) / a0;
b2 = (1.f - alpha * A) / a0;
a1 = b1; // = -2*cos(w0) / a0
a2 = (1.f - alpha / A) / a0;
}process method · cpp · L26-L35 (10 LOC)src/ALEXANDERPLATZ.cpp
float process(float in) {
float out = b0 * in + b1 * z1 + b2 * z2 - a1 * z1 - a2 * z2;
// Direct Form II Transposed
float w = in - a1 * z1 - a2 * z2;
out = b0 * w + b1 * z1 + b2 * z2;
z2 = z1;
z1 = w;
return out;
}Powered by Repobility — scan your code at https://repobility.com
reset method · cpp · L36-L39 (4 LOC)src/ALEXANDERPLATZ.cpp
void reset() {
z1 = z2 = 0.f;
}AlexTitleBox method · cpp · L44-L47 (4 LOC)src/ALEXANDERPLATZ.cpp
AlexTitleBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L48-L58 (11 LOC)src/ALEXANDERPLATZ.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(0, 79, 124)); // #004F7C
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
nvgStrokeColor(args.vg, nvgRGBA(100, 100, 100, 255));
nvgStroke(args.vg);
}AlexWhiteBox method · cpp · L63-L66 (4 LOC)src/ALEXANDERPLATZ.cpp
AlexWhiteBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L67-L73 (7 LOC)src/ALEXANDERPLATZ.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);
}draw method · cpp · L92-L109 (18 LOC)src/ALEXANDERPLATZ.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);
}
}onDragStart method · cpp · L125-L131 (7 LOC)src/ALEXANDERPLATZ.cpp
void onDragStart(const event::DragStart& e) override {
pressTime = 0.f;
pressing = true;
exclusiveTriggered = false;
VCVLightLatch<TLight>::onDragStart(e);
}onDragEnd method · cpp · L132-L136 (5 LOC)src/ALEXANDERPLATZ.cpp
void onDragEnd(const event::DragEnd& e) override {
pressing = false;
VCVLightLatch<TLight>::onDragEnd(e);
}Repobility · code-quality intelligence · https://repobility.com
step method · cpp · L137-L193 (57 LOC)src/ALEXANDERPLATZ.cpp
void step() override {
VCVLightLatch<TLight>::step();
if (pressing) {
pressTime += APP->window->getLastFrameDuration();
// 達到閾值時立即觸發 exclusive solo
if (pressTime >= LONG_PRESS_TIME && !exclusiveTriggered) {
exclusiveTriggered = true;
Module* module = this->module;
if (module) {
// 取消同一模組中其他軌道的 solo
for (int t = 0; t < ALEX_TRACKS; t++) {
if (t != trackIndex) {
module->params[12 + t].setValue(0.f); // SOLO_PARAM + t
}
}
// 取消整個 chain 中其他模組的所有 solo
Module* mod = module->leftExpander.module;
while (mod) {
if (mod->model == modelU8) {
mod->params[3].setValue(0.f);
} else if (mod->model == modelALEXANDERPLATZ) {
ALEXANDERPLATZ method · cpp · L250-L278 (29 LOC)src/ALEXANDERPLATZ.cpp
ALEXANDERPLATZ() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
for (int t = 0; t < ALEX_TRACKS; t++) {
configParam(LEVEL_PARAM + t, 0.0f, 2.0f, 1.0f, string::f("Track %d Level", t + 1));
configParam(DUCK_PARAM + t, 0.0f, 1.0f, 0.0f, string::f("Track %d Duck", t + 1));
configSwitch(MUTE_PARAM + t, 0.0f, 1.0f, 0.0f, string::f("Track %d Mute", t + 1), {"Unmuted", "Muted"});
configSwitch(SOLO_PARAM + t, 0.0f, 1.0f, 0.0f, string::f("Track %d Solo", t + 1), {"Off", "Solo"});
getParamQuantity(SOLO_PARAM + t)->description = "Hold for exclusive";
configInput(LEFT_INPUT + t, string::f("Track %d Left", t + 1));
configInput(RIGHT_INPUT + t, string::f("Track %d Right", t + 1));
configInput(LEVEL_CV_INPUT + t, string::f("Track %d Level CV", t + 1));
configInput(DUCK_INPUT + t, string::f("Track %d Duck", t + 1));
configInput(MUTE_TRIG_INPUT + t, sdataToJson method · cpp · L279-L285 (7 LOC)src/ALEXANDERPLATZ.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 · L286-L292 (7 LOC)src/ALEXANDERPLATZ.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 · L293-L466 (174 LOC)src/ALEXANDERPLATZ.cpp
void process(const ProcessArgs& args) override {
int maxChannels = 1;
for (int t = 0; t < ALEX_TRACKS; t++) {
maxChannels = std::max(maxChannels, inputs[LEFT_INPUT + t].getChannels());
maxChannels = std::max(maxChannels, inputs[RIGHT_INPUT + t].getChannels());
}
maxChannels = std::max(maxChannels, inputs[CHAIN_LEFT_INPUT].getChannels());
maxChannels = std::max(maxChannels, inputs[CHAIN_RIGHT_INPUT].getChannels());
outputs[LEFT_OUTPUT].setChannels(maxChannels);
outputs[RIGHT_OUTPUT].setChannels(maxChannels);
// 跨模組 Solo 邏輯:檢查整個 chain 是否有任何軌道被 solo
bool chainHasSolo = false;
for (int t = 0; t < ALEX_TRACKS && !chainHasSolo; t++) {
if (params[SOLO_PARAM + t].getValue() > 0.5f) chainHasSolo = true;
}
// 往左追蹤(使用硬編碼索引:U8 SOLO=3, ALEX SOLO=12+t, SHINJUKU SOLO=24+t)
Module* mod = leftExpander.module;
while (mod && !chainHasSolo) {
draw method · cpp · L477-L511 (35 LOC)src/ALEXANDERPLATZ.cpp
void draw(const DrawArgs &args) override {
float level = -60.0f;
if (module) {
level = isLeft ? module->vuLevelL[track] : module->vuLevelR[track];
}
float normalizedLevel = clamp((level - MIN_DB) / (MAX_DB - MIN_DB), 0.0f, 1.0f);
float redThreshold = (0.0f - MIN_DB) / (MAX_DB - MIN_DB);
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGBA(40, 40, 40, 255));
nvgFill(args.vg);
if (normalizedLevel > 0.0f) {
float barWidth = box.size.x * normalizedLevel;
NVGpaint gradient = nvgLinearGradient(args.vg, 0, 0, box.size.x, 0,
nvgRGB(80, 180, 80), nvgRGB(255, 50, 50));
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, barWidth, box.size.y);
nvgFillPaint(args.vg, gradient);
nvgFill(args.vg);
if (normalizedLevel > redThreshold) {
float redAlexEQFader method · cpp · L520-L524 (5 LOC)src/ALEXANDERPLATZ.cpp
AlexEQFader() {
box.size = Vec(FADER_WIDTH, FADER_HEIGHT);
speed = 0.8f;
}draw method · cpp · L525-L601 (77 LOC)src/ALEXANDERPLATZ.cpp
void draw(const DrawArgs& args) override {
// 軌道背景(深色金屬質感)
float trackX = (box.size.x - TRACK_WIDTH) / 2.f;
nvgBeginPath(args.vg);
nvgRoundedRect(args.vg, trackX, 2, TRACK_WIDTH, box.size.y - 4, 1.5f);
// 深色漸層背景
NVGpaint trackBg = nvgLinearGradient(args.vg, trackX, 0, trackX + TRACK_WIDTH, 0,
nvgRGB(25, 30, 35), nvgRGB(45, 50, 55));
nvgFillPaint(args.vg, trackBg);
nvgFill(args.vg);
// 軌道內陷邊框
nvgBeginPath(args.vg);
nvgRoundedRect(args.vg, trackX, 2, TRACK_WIDTH, box.size.y - 4, 1.5f);
nvgStrokeColor(args.vg, nvgRGBA(0, 0, 0, 180));
nvgStrokeWidth(args.vg, 1.f);
nvgStroke(args.vg);
// 中心線(0dB 標記)
float centerY = box.size.y / 2.f;
nvgBeginPath(args.vg);
nvgMoveTo(args.vg, trackX - 1, centerY);
nvgLineTo(args.vg, trackX + TRACK_WIDTH + 1, centerY);
nvgStrokeColor(args.vg, nvgRGBA(100, 120, 140, 200));
nvgSIf a scraper extracted this row, it came from Repobility (https://repobility.com)
AlexEQLabel method · cpp · L607-L612 (6 LOC)src/ALEXANDERPLATZ.cpp
AlexEQLabel(Vec pos, const std::string& t) {
box.pos = pos;
box.size = Vec(18, 10);
text = t;
}draw method · cpp · L613-L620 (8 LOC)src/ALEXANDERPLATZ.cpp
void draw(const DrawArgs& args) override {
nvgFontSize(args.vg, 7.f);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
nvgFillColor(args.vg, nvgRGB(60, 70, 80));
nvgText(args.vg, box.size.x / 2.f, box.size.y / 2.f, text.c_str(), NULL);
}ALEXANDERPLATZWidget method · cpp · L630-L719 (90 LOC)src/ALEXANDERPLATZ.cpp
ALEXANDERPLATZWidget(ALEXANDERPLATZ* module) {
setModule(module);
panelThemeHelper.init(this, "16HP", module ? &module->panelContrast : nullptr);
box.size = Vec(16 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
// 標題區(深藍色 #004F7C)
addChild(new AlexTitleBox(Vec(0, 1), Vec(box.size.x, 18)));
addChild(new AlexTextLabel(Vec(0, 1), Vec(box.size.x, 20), "ALEXANDERPLATZ", 14.f, nvgRGB(255, 255, 255)));
addChild(new AlexTextLabel(Vec(0, 16), Vec(box.size.x, 20), "MADZINE", 10.f, nvgRGB(255, 200, 0)));
// 每軌寬度(4HP = 60.96px)
float trackWidth = 4 * RACK_GRID_WIDTH;
for (int t = 0; t < ALEX_TRACKS; t++) {
float trackX = t * trackWidth;
float centerX = trackX + trackWidth / 2;
// INPUT 標籤(按規範:標籤框 Y = 元件 Y - 24 = 59 - 24 = 35)
addChild(new AlexTextLabel(Vec(trackX, 35), Vec(trackWidth, 15), "INPUT", 8.f, nvgRGB(255, 255, 255)));
// L/R 輸入
addInputpage 1 / 39next ›