Function bodies 1,902 total
step method · cpp · L720-L806 (87 LOC)src/ALEXANDERPLATZ.cpp
void step() override {
ALEXANDERPLATZ* module = dynamic_cast<ALEXANDERPLATZ*>(this->module);
if (module) {
panelThemeHelper.step(module);
// Level 旋鈕 CV 調變顯示
for (int t = 0; t < ALEX_TRACKS; t++) {
if (levelKnobs[t]) {
bool cvConnected = module->inputs[ALEXANDERPLATZ::LEVEL_CV_INPUT + t].isConnected();
levelKnobs[t]->setModulationEnabled(cvConnected);
if (cvConnected) {
levelKnobs[t]->setModulation(module->levelCvModulation[t]);
}
}
}
// Chain 自動接線(模組移開後保持連接,用戶可手動刪除)
// 先驗證現有的自動 cable(被手動刪除時清除 ID)
if (autoChainLeftCableId >= 0 && !APP->engine->getCable(autoChainLeftCableId)) {
autoChainLeftCableId = -1;
}
if (autoChainRightCableId >= 0 && !APP->engine->getCable(autoChainRightCableId)) {
autoCappendContextMenu method · cpp · L807-L812 (6 LOC)src/ALEXANDERPLATZ.cpp
void appendContextMenu(ui::Menu* menu) override {
ALEXANDERPLATZ* module = dynamic_cast<ALEXANDERPLATZ*>(this->module);
if (!module) return;
addPanelThemeMenu(menu, module);
}DECAPyramid method · cpp · L81-L120 (40 LOC)src/DECAPyramid.cpp
DECAPyramid() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
for (int i = 0; i < 8; i++) {
configParam(X_PARAM_1 + i * 7, -1.f, 1.f, -1.f, "Track " + std::to_string(i + 1) + " X Position", "", 0.f, 1.f);
configParam(Y_PARAM_1 + i * 7, -1.f, 1.f, -1.f, "Track " + std::to_string(i + 1) + " Y Position", "", 0.f, 1.f);
configParam(Z_PARAM_1 + i * 7, -1.f, 1.f, -1.f, "Track " + std::to_string(i + 1) + " Z Position", "", 0.f, 1.f);
configParam(LEVEL_PARAM_1 + i * 7, 0.f, 1.f, 0.7f, "Track " + std::to_string(i + 1) + " Level", "%", 0.f, 100.f);
configParam(FILTER_PARAM_1 + i * 7, -1.f, 1.f, 0.f, "Track " + std::to_string(i + 1) + " Filter");
configParam(SENDA_PARAM_1 + i * 7, 0.f, 1.f, 0.f, "Track " + std::to_string(i + 1) + " Send A", "%", 0.f, 100.f);
configParam(SENDB_PARAM_1 + i * 7, 0.f, 1.f, 0.f, "Track " + std::to_string(i + 1) + " Send B", "%", 0.f, 100.f);
distance3D method · cpp · L121-L127 (7 LOC)src/DECAPyramid.cpp
float distance3D(float x1, float y1, float z1, float x2, float y2, float z2) {
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
return std::sqrt(dx*dx + dy*dy + dz*dz);
}calculateVBAP method · cpp · L128-L175 (48 LOC)src/DECAPyramid.cpp
void calculateVBAP(float sourceX, float sourceY, float sourceZ, float gains[8]) {
for (int i = 0; i < 8; i++) {
float distance = distance3D(sourceX, sourceY, sourceZ,
speakers[i].x, speakers[i].y, speakers[i].z);
distance = std::max(distance, 0.001f);
float gain = 1.0f / (1.0f + distance + distance * distance * 2.0f);
float fadeOut = 1.0f;
if (sourceX <= -0.8f && speakers[i].x > 0) {
fadeOut *= std::max(0.0f, (sourceX + 1.0f) / 0.2f);
}
if (sourceX >= 0.8f && speakers[i].x < 0) {
fadeOut *= std::max(0.0f, (1.0f - sourceX) / 0.2f);
}
if (sourceY <= -0.8f && speakers[i].y > 0) {
fadeOut *= std::max(0.0f, (sourceY + 1.0f) / 0.2f);
}
if (sourceY >= 0.8f && speakers[i].y < 0) {
fadeOprocess method · cpp · L176-L370 (195 LOC)src/DECAPyramid.cpp
void process(const ProcessArgs& args) override {
float sendAOut = 0.0f;
float sendBOut = 0.0f;
float returnAL = inputs[RETURN_AL_INPUT].getVoltage();
float returnAR = inputs[RETURN_AR_INPUT].getVoltage();
float returnBL = inputs[RETURN_BL_INPUT].getVoltage();
float returnBR = inputs[RETURN_BR_INPUT].getVoltage();
float rtnALevel = params[RTN_A_LEVEL_PARAM].getValue();
float rtnAFilter = params[RTN_A_FILTER_PARAM].getValue();
float rtnBLevel = params[RTN_B_LEVEL_PARAM].getValue();
float rtnBFilter = params[RTN_B_FILTER_PARAM].getValue();
float filterSmooth = 0.005f;
smoothedRtnAFilter += (rtnAFilter - smoothedRtnAFilter) * filterSmooth;
smoothedRtnBFilter += (rtnBFilter - smoothedRtnBFilter) * filterSmooth;
if (smoothedRtnAFilter < -0.001f) {
if (lastRtnAFilterMode != -1) {
rtnAFilter1.reset();
dataToJson method · cpp · L371-L377 (7 LOC)src/DECAPyramid.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;
}Source: Repobility analyzer · https://repobility.com
dataFromJson method · cpp · L378-L384 (7 LOC)src/DECAPyramid.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);
}draw method · cpp · L402-L419 (18 LOC)src/DECAPyramid.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);
}
}OutlinedTextLabel method · cpp · L428-L437 (10 LOC)src/DECAPyramid.cpp
OutlinedTextLabel(Vec pos, Vec size, std::string text, float fontSize,
NVGcolor color, float outlineWidth = 2.f) {
box.pos = pos;
box.size = size;
this->text = text;
this->fontSize = fontSize;
this->color = color;
this->outlineWidth = outlineWidth;
}draw method · cpp · L438-L460 (23 LOC)src/DECAPyramid.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);
float cx = box.size.x / 2.f;
float cy = box.size.y / 2.f;
// 繪製黑色外框(多次偏移繪製)
nvgFillColor(args.vg, nvgRGB(0, 0, 0));
for (float dx = -outlineWidth; dx <= outlineWidth; dx += 1.f) {
for (float dy = -outlineWidth; dy <= outlineWidth; dy += 1.f) {
if (dx != 0 || dy != 0) {
nvgText(args.vg, cx + dx, cy + dy, text.c_str(), NULL);
}
}
}
// 繪製主要顏色文字
nvgFillColor(args.vg, color);
nvgText(args.vg, cx, cy, text.c_str(), NULL);
}WhiteBackgroundBox method · cpp · L464-L467 (4 LOC)src/DECAPyramid.cpp
WhiteBackgroundBox(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L468-L478 (11 LOC)src/DECAPyramid.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);
}VolumeMeterWidget method · cpp · L486-L490 (5 LOC)src/DECAPyramid.cpp
VolumeMeterWidget() {
box.size = Vec(6, 200);
preLevel = false;
}draw method · cpp · L491-L548 (58 LOC)src/DECAPyramid.cpp
void draw(const DrawArgs& args) override {
if (!module) return;
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(20, 20, 20));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 1.0f);
nvgStrokeColor(args.vg, nvgRGB(100, 100, 100));
nvgStroke(args.vg);
float level;
if (preLevel) {
level = module->vuMeterPre[trackIndex].v;
} else {
level = module->vuMeterPost[trackIndex].v;
}
level = level / 5.0f;
level = clamp(level, 0.f, 1.2f);
float meterHeight = level * box.size.y;
if (meterHeight > 0) {
float greenHeight = std::min(meterHeight, box.size.y * 0.8f);
float yellowHeight = std::min(meterHeight - greenHeight, box.size.y * 0.15f);
float redHeight = meterHeight - greenHeight - yellowHeight;
Repobility (the analyzer behind this table) · https://repobility.com
DECAPyramidMasterDisplay method · cpp · L554-L557 (4 LOC)src/DECAPyramid.cpp
DECAPyramidMasterDisplay() {
box.size = Vec(100, 100);
}project3D method · cpp · L558-L566 (9 LOC)src/DECAPyramid.cpp
Vec project3D(float x, float y, float z) {
float iso_x = (x - z) * cos(30.0f * M_PI / 180.0f);
float iso_y = (x + z) * sin(30.0f * M_PI / 180.0f) - y;
float scale = box.size.x * 0.375f;
return Vec(box.size.x/2 + iso_x * scale,
box.size.y/2 + iso_y * scale);
}drawSpeakerCube method · cpp · L567-L611 (45 LOC)src/DECAPyramid.cpp
void drawSpeakerCube(const DrawArgs& args) {
if (!module) return;
nvgStrokeWidth(args.vg, 0.5f);
nvgStrokeColor(args.vg, nvgRGBA(255, 255, 255, 100));
for (int i = 0; i < 8; i++) {
Vec pos = project3D(module->speakers[i].x * 0.5f,
module->speakers[i].y * 0.5f,
module->speakers[i].z * 0.5f);
nvgBeginPath(args.vg);
nvgCircle(args.vg, pos.x, pos.y, 3.0f);
nvgStroke(args.vg);
nvgFontSize(args.vg, 8.0f);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
std::string speakerNum = std::to_string(i + 1);
nvgText(args.vg, pos.x, pos.y, speakerNum.c_str(), NULL);
}
Vec corners[8];
fdrawAllAudioSources method · cpp · L612-L656 (45 LOC)src/DECAPyramid.cpp
void drawAllAudioSources(const DrawArgs& args) {
if (!module) return;
NVGcolor trackColors[8] = {
nvgRGB(10, 149, 149), // Track 1: 深青色 +10
nvgRGB(89, 121, 153), // Track 2: 石墨藍 +10
nvgRGB(112, 61, 163), // Track 3: 雅緻紫 +10
nvgRGB(194, 144, 21), // Track 4: 深金黃 +10
nvgRGB(117, 152, 45), // Track 5: 橄欖綠 +10
nvgRGB(10, 117, 73), // Track 6: 深翠綠 +10
nvgRGB(124, 57, 65), // Track 7: 深酒紅 +10
nvgRGB(152, 135, 200) // Track 8: 深紫灰 +10
};
for (int trackIndex = 0; trackIndex < 8; trackIndex++) {
float x = module->params[DECAPyramid::X_PARAM_1 + trackIndex * 7].getValue();
float y = module->params[DECAPyramid::Y_PARAM_1 + trackIndex * 7].getValue();
float z = module->params[DECAPyramid::Z_PARAM_1 + trackIndex * 7].getValue();
if (module->inputs[DECAPyramid::X_CV_INPdrawBackground method · cpp · L657-L669 (13 LOC)src/DECAPyramid.cpp
void drawBackground(const DrawArgs& args) {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(20, 20, 20));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 0.5f);
nvgStrokeColor(args.vg, nvgRGB(100, 100, 100));
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgStroke(args.vg);
}drawLayer method · cpp · L670-L677 (8 LOC)src/DECAPyramid.cpp
void drawLayer(const DrawArgs& args, int layer) override {
if (layer != 1) return;
drawBackground(args);
drawSpeakerCube(args);
drawAllAudioSources(args);
}DECAPyramid3DDisplay method · cpp · L684-L687 (4 LOC)src/DECAPyramid.cpp
DECAPyramid3DDisplay() {
box.size = Vec(60, 50);
}project3D method · cpp · L688-L696 (9 LOC)src/DECAPyramid.cpp
Vec project3D(float x, float y, float z) {
float iso_x = (x - z) * cos(30.0f * M_PI / 180.0f);
float iso_y = (x + z) * sin(30.0f * M_PI / 180.0f) - y;
float scale = box.size.x * 0.375f;
return Vec(box.size.x/2 + iso_x * scale,
box.size.y/2 + iso_y * scale);
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
drawSpeakerCube method · cpp · L697-L741 (45 LOC)src/DECAPyramid.cpp
void drawSpeakerCube(const DrawArgs& args) {
if (!module) return;
nvgStrokeWidth(args.vg, 0.5f);
nvgStrokeColor(args.vg, nvgRGBA(255, 255, 255, 100));
for (int i = 0; i < 8; i++) {
Vec pos = project3D(module->speakers[i].x * 0.5f,
module->speakers[i].y * 0.5f,
module->speakers[i].z * 0.5f);
nvgBeginPath(args.vg);
nvgCircle(args.vg, pos.x, pos.y, 1.5f);
nvgStroke(args.vg);
nvgFontSize(args.vg, 6.0f);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
std::string speakerNum = std::to_string(i + 1);
nvgText(args.vg, pos.x, pos.y, speakerNum.c_str(), NULL);
}
Vec corners[8];
fdrawAudioSource method · cpp · L742-L784 (43 LOC)src/DECAPyramid.cpp
void drawAudioSource(const DrawArgs& args) {
if (!module) return;
float x = module->params[DECAPyramid::X_PARAM_1 + trackIndex * 7].getValue();
float y = module->params[DECAPyramid::Y_PARAM_1 + trackIndex * 7].getValue();
float z = module->params[DECAPyramid::Z_PARAM_1 + trackIndex * 7].getValue();
if (module->inputs[DECAPyramid::X_CV_INPUT_1 + trackIndex * 4].isConnected()) {
x += module->inputs[DECAPyramid::X_CV_INPUT_1 + trackIndex * 4].getVoltage() * 0.2f;
x = clamp(x, -1.f, 1.f);
}
if (module->inputs[DECAPyramid::Y_CV_INPUT_1 + trackIndex * 4].isConnected()) {
y += module->inputs[DECAPyramid::Y_CV_INPUT_1 + trackIndex * 4].getVoltage() * 0.2f;
y = clamp(y, -1.f, 1.f);
}
if (module->inputs[DECAPyramid::Z_CV_INPUT_1 + trackIndex * 4].isConnected()) {
z += module->inputs[DECAPyramid::Z_CV_INPUT_1 + trackIndex * 4].getVoltage() drawBackground method · cpp · L785-L797 (13 LOC)src/DECAPyramid.cpp
void drawBackground(const DrawArgs& args) {
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgFillColor(args.vg, nvgRGB(20, 20, 20));
nvgFill(args.vg);
nvgStrokeWidth(args.vg, 0.5f);
nvgStrokeColor(args.vg, nvgRGB(100, 100, 100));
nvgBeginPath(args.vg);
nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
nvgStroke(args.vg);
}drawLayer method · cpp · L798-L805 (8 LOC)src/DECAPyramid.cpp
void drawLayer(const DrawArgs& args, int layer) override {
if (layer != 1) return;
drawBackground(args);
drawSpeakerCube(args);
drawAudioSource(args);
}DECAPyramidWidget method · cpp · L812-L996 (185 LOC)src/DECAPyramid.cpp
DECAPyramidWidget(DECAPyramid* module) {
setModule(module);
panelThemeHelper.init(this, "40HP", module ? &module->panelContrast : nullptr);
box.size = Vec(40 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
addChild(new TechnoEnhancedTextLabel(Vec(480, 1), Vec(120, 20), "DECAPYRAMID", 14.f, nvgRGB(255, 200, 0), true));
addChild(new TechnoEnhancedTextLabel(Vec(480, 13), Vec(120, 20), "MADZINE", 10.f, nvgRGB(255, 200, 0), false));
float trackY[] = {35, 85, 145, 205};
// X/Y/Z 大型背景裝飾標籤 - 在旋鈕之前添加,讓旋鈕渲染在上層
// 帶黑色外框,類似 259m 風格
addChild(new OutlinedTextLabel(Vec(7, 80), Vec(50, 10), "X", 80.f, nvgRGB(160, 160, 160), 2.f));
addChild(new OutlinedTextLabel(Vec(7, 145), Vec(50, 10), "Y", 80.f, nvgRGB(160, 160, 160), 2.f));
addChild(new OutlinedTextLabel(Vec(7, 215), Vec(50, 10), "Z", 80.f, nvgRGB(160, 160, 160), 2.f));
std::string trackLabels[] = {"T", "X", "Y", "Z"};
int trackParams[] = step method · cpp · L997-L1020 (24 LOC)src/DECAPyramid.cpp
void step() override {
DECAPyramid* module = getModule<DECAPyramid>();
if (module) {
panelThemeHelper.step(module);
// CV 調變顯示更新
for (int track = 0; track < 8; track++) {
for (int axis = 0; axis < 3; axis++) {
StandardBlackKnob26* knob = xyzKnobs[track][axis];
if (knob) {
// axis: 0=X, 1=Y, 2=Z
int inputId = DECAPyramid::X_CV_INPUT_1 + axis + track * 4;
bool connected = module->inputs[inputId].isConnected();
knob->setModulationEnabled(connected);
if (connected) {
knob->setModulation(module->cvMod[track][axis]);
}
}
}
}
}
ModuleWidget::step();
}appendContextMenu method · cpp · L1021-L1030 (10 LOC)src/DECAPyramid.cpp
void appendContextMenu(Menu* menu) override {
DECAPyramid* module = getModule<DECAPyramid>();
if (!module) return;
menu->addChild(new MenuSeparator);
menu->addChild(createBoolPtrMenuItem("Send Pre-Level", "", &module->sendPreLevel));
addPanelThemeMenu(menu, module);
}DrummerSynth class · cpp · L21-L51 (31 LOC)src/Drummmmmmer.cpp
class DrummerSynth {
private:
MinimalVoice voices[8];
float sampleRate = 44100.0f;
public:
void setSampleRate(float sr) {
sampleRate = sr;
for (int i = 0; i < 8; i++) voices[i].setSampleRate(sr);
}
void setVoiceParams(int voice, SynthMode mode, float freq, float decay, float sweep = 0.f, float bend = 1.f) {
if (voice < 0 || voice > 7) return;
voices[voice].setMode(mode);
voices[voice].setFreq(freq);
voices[voice].setDecay(decay);
voices[voice].setSweep(sweep);
voices[voice].setBend(bend);
}
void triggerVoice(int voice, float velocity = 1.0f) {
if (voice < 0 || voice > 7) return;
voices[voice].trigger(velocity);
}
float processVoice(int voice) {
if (voice < 0 || voice > 7) return 0.0f;
return voices[voice].process();
}
};Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
setSampleRate method · cpp · L26-L31 (6 LOC)src/Drummmmmmer.cpp
public:
void setSampleRate(float sr) {
sampleRate = sr;
for (int i = 0; i < 8; i++) voices[i].setSampleRate(sr);
}setVoiceParams method · cpp · L32-L40 (9 LOC)src/Drummmmmmer.cpp
void setVoiceParams(int voice, SynthMode mode, float freq, float decay, float sweep = 0.f, float bend = 1.f) {
if (voice < 0 || voice > 7) return;
voices[voice].setMode(mode);
voices[voice].setFreq(freq);
voices[voice].setDecay(decay);
voices[voice].setSweep(sweep);
voices[voice].setBend(bend);
}triggerVoice method · cpp · L41-L45 (5 LOC)src/Drummmmmmer.cpp
void triggerVoice(int voice, float velocity = 1.0f) {
if (voice < 0 || voice > 7) return;
voices[voice].trigger(velocity);
}processVoice method · cpp · L46-L50 (5 LOC)src/Drummmmmmer.cpp
float processVoice(int voice) {
if (voice < 0 || voice > 7) return 0.0f;
return voices[voice].process();
}applyDrummerPreset function · cpp · L171-L180 (10 LOC)src/Drummmmmmer.cpp
inline void applyDrummerPreset(DrummerSynth& synth, int styleIndex) {
if (styleIndex < 0 || styleIndex > 9) return;
const DrummerStylePreset& preset = DRUMMER_PRESETS[styleIndex];
for (int i = 0; i < 8; i++) {
synth.setVoiceParams(i, preset.voices[i].mode,
preset.voices[i].freq, preset.voices[i].decay,
preset.voices[i].sweep, preset.voices[i].bend);
}
}getDisplayValueString method · cpp · L189-L195 (7 LOC)src/Drummmmmmer.cpp
std::string getDisplayValueString() override {
int index = static_cast<int>(getValue());
if (index >= 0 && index < 10) {
return WD_STYLE_NAMES[index];
}
return ParamQuantity::getDisplayValueString();
}Drummmmmmer method · cpp · L277-L322 (46 LOC)src/Drummmmmmer.cpp
Drummmmmmer() {
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
// Global parameters
configParam<WDStyleParamQuantity>(STYLE_PARAM, 0.f, 9.f, 0.f, "Style");
getParamQuantity(STYLE_PARAM)->snapEnabled = true;
configParam(SPREAD_PARAM, 0.f, 1.f, 0.5f, "Stereo Spread", "%", 0.f, 100.f);
configParam(VOICE_PARAM, 0.f, 1.f, 0.f, "Voice Variation", "%", 0.f, 100.f);
// Per-voice parameters
const char* voiceNames[4] = {"Timeline", "Foundation", "Groove", "Lead"};
for (int i = 0; i < 4; i++) {
// FREQ: -1 to +1 (±1 octave adjustment)
configParam(FREQ_PARAM_TL + i, -1.f, 1.f, 0.f,
std::string(voiceNames[i]) + " Freq", " oct");
// DECAY: 0.2 to 2.0 (multiplier)
configParam(DECAY_PARAM_TL + i, 0.2f, 2.f, 1.f,
std::string(voiceNames[i]) + " Decay", "x");
}
// Inputs
configInput(STYLE_CV_INPUTonSampleRateChange method · cpp · L323-L326 (4 LOC)src/Drummmmmmer.cpp
void onSampleRateChange() override {
drumSynth.setSampleRate(APP->engine->getSampleRate());
}Source: Repobility analyzer · https://repobility.com
process method · cpp · L327-L438 (112 LOC)src/Drummmmmmer.cpp
void process(const ProcessArgs& args) override {
// Update sample rate
drumSynth.setSampleRate(args.sampleRate);
// Read style parameter with CV
float styleValue = params[STYLE_PARAM].getValue();
if (inputs[STYLE_CV_INPUT].isConnected()) {
float cv = inputs[STYLE_CV_INPUT].getVoltage();
styleValue += cv;
styleCvMod = clamp(cv / 10.0f, -1.0f, 1.0f);
} else {
styleCvMod = 0.0f;
}
int newStyle = clamp((int)std::round(styleValue), 0, 9);
// Apply style preset if changed
if (newStyle != currentStyle) {
currentStyle = newStyle;
applyDrummerPreset(drumSynth, currentStyle);
}
// Get base preset for parameter modulation (8 voices)
const DrummerStylePreset& preset = DRUMMER_PRESETS[currentStyle];
// Voice variation probability
float voiceProb = params[VOICE_PARAM].getValue();
// Process eadataToJson method · cpp · L439-L445 (7 LOC)src/Drummmmmmer.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 · L446-L453 (8 LOC)src/Drummmmmmer.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_number_value(contrastJ);
}draw method · cpp · L489-L507 (19 LOC)src/Drummmmmmer.cpp
void draw(const DrawArgs &args) override {
nvgFontSize(args.vg, fontSize);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, align);
float tx = (align & NVG_ALIGN_LEFT) ? 0.f : box.size.x / 2.f;
if (bold) {
nvgFillColor(args.vg, color);
nvgText(args.vg, tx, box.size.y / 2.f, text.c_str(), NULL);
nvgStrokeColor(args.vg, color);
nvgStrokeWidth(args.vg, 0.3f);
nvgText(args.vg, tx, box.size.y / 2.f, text.c_str(), NULL);
} else {
nvgFillColor(args.vg, color);
nvgText(args.vg, tx, box.size.y / 2.f, text.c_str(), NULL);
}
}WDDynamicRoleTitle method · cpp · L520-L527 (8 LOC)src/Drummmmmmer.cpp
WDDynamicRoleTitle(Vec pos, Vec size, std::string text, float fontSize = 6.5f, bool bold = true) {
box.pos = pos;
box.size = size;
this->text = text;
this->fontSize = fontSize;
this->bold = bold;
}DrummmmmmerWhitePanel method · cpp · L534-L537 (4 LOC)src/Drummmmmmer.cpp
DrummmmmmerWhitePanel(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}draw method · cpp · L538-L544 (7 LOC)src/Drummmmmmer.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);
}StyleDisplay method · cpp · L550-L554 (5 LOC)src/Drummmmmmer.cpp
StyleDisplay(Vec pos, Vec size) {
box.pos = pos;
box.size = size;
}Repobility (the analyzer behind this table) · https://repobility.com
draw method · cpp · L555-L581 (27 LOC)src/Drummmmmmer.cpp
void draw(const DrawArgs &args) override {
std::string styleName = "West African";
NVGcolor color = STYLE_COLORS[0];
if (module) {
styleName = WD_STYLE_NAMES[module->currentStyle];
color = STYLE_COLORS[module->currentStyle];
}
nvgFontSize(args.vg, 11.f);
nvgFontFaceId(args.vg, APP->window->uiFont->handle);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
float cx = box.size.x / 2.f;
float cy = box.size.y / 2.f;
// Colored glow (style color)
nvgFontBlur(args.vg, 3.0f);
nvgFillColor(args.vg, color);
nvgText(args.vg, cx, cy, styleName.c_str(), NULL);
nvgText(args.vg, cx, cy, styleName.c_str(), NULL);
// White text (always readable)
nvgFontBlur(args.vg, 0.f);
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
nvgText(args.vg, cx, cy, styleName.c_str(), NULL);
}DrummmmmmerWidget method · cpp · L589-L693 (105 LOC)src/Drummmmmmer.cpp
DrummmmmmerWidget(Drummmmmmer* module) {
setModule(module);
panelHelper.init(this, "8HP", module ? &module->panelContrast : nullptr);
box.size = Vec(8 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
// ========== TITLE AREA (Y=0-26) ==========
addChild(new DrummmmmmerTextLabel(Vec(0, 1), Vec(box.size.x, 20), "Drummmmmmer", 14.f, nvgRGB(255, 200, 0), true));
addChild(new DrummmmmmerTextLabel(Vec(0, 13), Vec(box.size.x, 20), "MADZINE", 10.f, nvgRGB(255, 200, 0), false));
// ========== WHITE BOTTOM PANEL (Y=330-380) ==========
addChild(new DrummmmmmerWhitePanel(Vec(0, 330), Vec(box.size.x, 50)));
// ========== PHASE 1: ALL PORTS AND KNOBS (z-order bottom) ==========
// --- GLOBAL CONTROLS: STYLE knob (left) + StyleDisplay (center) + CV port (right), same row ---
// STYLE knob (TechnoSnapKnob30, 30px) X=18, Y=56
styleKnob = createParamCentered<TechnoSnapKnob30>(Vec(18.f, 56.f), module, Drummmmmmstep method · cpp · L694-L719 (26 LOC)src/Drummmmmmer.cpp
void step() override {
Drummmmmmer* m = dynamic_cast<Drummmmmmer*>(module);
if (m) {
panelHelper.step(m);
if (styleKnob) {
bool connected = m->inputs[Drummmmmmer::STYLE_CV_INPUT].isConnected();
styleKnob->setModulationEnabled(connected);
if (connected) styleKnob->setModulation(m->styleCvMod);
}
for (int v = 0; v < 4; v++) {
if (freqKnobs[v]) {
bool connected = m->inputs[Drummmmmmer::FREQ_CV_INPUT_TL + v].isConnected();
freqKnobs[v]->setModulationEnabled(connected);
if (connected) freqKnobs[v]->setModulation(m->freqCvMod[v]);
}
if (decayKnobs[v]) {
bool connected = m->inputs[Drummmmmmer::DECAY_CV_INPUT_TL + v].isConnected();
decayKnobs[v]->setModulationEnabled(connected);
if (connected) decayKnobs[v]->setM