diff --git a/src/Braids.cpp b/src/Braids.cpp index d9ca816..95edd69 100644 --- a/src/Braids.cpp +++ b/src/Braids.cpp @@ -54,13 +54,13 @@ struct Braids : Module { configInput(COLOR_INPUT, "Color"); configOutput(OUT_OUTPUT, "Audio"); - memset(&osc, 0, sizeof(osc)); + std::memset(&osc, 0, sizeof(osc)); osc.Init(); - memset(&jitter_source, 0, sizeof(jitter_source)); + std::memset(&jitter_source, 0, sizeof(jitter_source)); jitter_source.Init(); - memset(&ws, 0, sizeof(ws)); + std::memset(&ws, 0, sizeof(ws)); ws.Init(0x0000); - memset(&settings, 0, sizeof(settings)); + std::memset(&settings, 0, sizeof(settings)); // List of supported settings settings.meta_modulation = 0; @@ -81,9 +81,9 @@ struct Braids : Module { float fm = params[FM_PARAM].getValue() * inputs[FM_INPUT].getVoltage(); // Set shape - int shape = roundf(params[SHAPE_PARAM].getValue() * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); + int shape = std::round(params[SHAPE_PARAM].getValue() * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); if (settings.meta_modulation) { - shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); + shape += std::round(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); } settings.shape = clamp(shape, 0, braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); @@ -102,7 +102,7 @@ struct Braids : Module { if (!settings.meta_modulation) pitchV += fm; if (lowCpu) - pitchV += log2f(96000.f * args.sampleTime); + pitchV += std::log2(96000.f * args.sampleTime); int32_t pitch = (pitchV * 12.0 + 60) * 128; pitch += jitter_source.Render(settings.vco_drift); pitch = clamp(pitch, 0, 16383); @@ -184,62 +184,73 @@ struct Braids : Module { lowCpu = json_boolean_value(lowCpuJ); } } + + int getShapeParam() { + return std::round(params[SHAPE_PARAM].getValue() * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); + } + void setShapeParam(int shape) { + params[SHAPE_PARAM].setValue(shape / (float) braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); + } }; +struct ShapeInfo { + std::string code; + std::string label; +}; -static const char* algo_values[] = { - "CSAW", - "/\\-_", - "//-_", - "FOLD", - "uuuu", - "SUB-", - "SUB/", - "SYN-", - "SYN/", - "//x3", - "-_x3", - "/\\x3", - "SIx3", - "RING", - "////", - "//uu", - "TOY*", - "ZLPF", - "ZPKF", - "ZBPF", - "ZHPF", - "VOSM", - "VOWL", - "VFOF", - "HARM", - "FM ", - "FBFM", - "WTFM", - "PLUK", - "BOWD", - "BLOW", - "FLUT", - "BELL", - "DRUM", - "KICK", - "CYMB", - "SNAR", - "WTBL", - "WMAP", - "WLIN", - "WTx4", - "NOIS", - "TWNQ", - "CLKN", - "CLOU", - "PRTC", - "QPSK", - " ", +static const std::vector SHAPE_INFOS = { + {"CSAW", "Quirky sawtooth"}, + {"/\\-_", "Triangle to saw"}, + {"//-_", "Sawtooth wave with dephasing"}, + {"FOLD", "Wavefolded sine/triangle"}, + {"uuuu", "Buzz"}, + {"SUB-", "Square sub"}, + {"SUB/", "Saw sub"}, + {"SYN-", "Square sync"}, + {"SYN/", "Saw sync"}, + {"//x3", "Triple saw"}, + {"-_x3", "Triple square"}, + {"/\\x3", "Triple triangle"}, + {"SIx3", "Triple sine"}, + {"RING", "Triple ring mod"}, + {"////", "Saw swarm"}, + {"//uu", "Saw comb"}, + {"TOY*", "Circuit-bent toy"}, + {"ZLPF", "Low-pass filtered waveform"}, + {"ZPKF", "Peak filtered waveform"}, + {"ZBPF", "Band-pass filtered waveform"}, + {"ZHPF", "High-pass filtered waveform"}, + {"VOSM", "VOSIM formant"}, + {"VOWL", "Speech synthesis"}, + {"VFOF", "FOF speech synthesis"}, + {"HARM", "12 sine harmonics"}, + {"FM ", "2-operator phase-modulation"}, + {"FBFM", "2-operator phase-modulation with feedback"}, + {"WTFM", "2-operator phase-modulation with chaotic feedback"}, + {"PLUK", "Plucked string"}, + {"BOWD", "Bowed string"}, + {"BLOW", "Blown reed"}, + {"FLUT", "Flute"}, + {"BELL", "Bell"}, + {"DRUM", "Drum"}, + {"KICK", "Kick drum circuit simulation"}, + {"CYMB", "Cymbal"}, + {"SNAR", "Snare"}, + {"WTBL", "Wavetable"}, + {"WMAP", "2D wavetable"}, + {"WLIN", "1D wavetable"}, + {"WTx4", "4-voice paraphonic 1D wavetable"}, + {"NOIS", "Filtered noise"}, + {"TWNQ", "Twin peaks noise"}, + {"CLKN", "Clocked noise"}, + {"CLOU", "Granular cloud"}, + {"PRTC", "Particle noise"}, + {"QPSK", "Digital modulation"}, }; + struct BraidsDisplay : TransparentWidget { Braids* module; std::shared_ptr font; @@ -271,35 +282,10 @@ struct BraidsDisplay : TransparentWidget { Vec textPos = Vec(11, 47); NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); nvgFillColor(args.vg, nvgTransRGBA(textColor, 16)); + // Background of all segments nvgText(args.vg, textPos.x, textPos.y, "~~~~", NULL); nvgFillColor(args.vg, textColor); - nvgText(args.vg, textPos.x, textPos.y, algo_values[shape], NULL); - } -}; - - -struct BraidsSettingItem : MenuItem { - uint8_t* setting = NULL; - uint8_t offValue = 0; - uint8_t onValue = 1; - void onAction(const event::Action& e) override { - // Toggle setting - *setting = (*setting == onValue) ? offValue : onValue; - } - void step() override { - rightText = (*setting == onValue) ? "✔" : ""; - MenuItem::step(); - } -}; - -struct BraidsLowCpuItem : MenuItem { - Braids* braids; - void onAction(const event::Action& e) override { - braids->lowCpu = !braids->lowCpu; - } - void step() override { - rightText = (braids->lowCpu) ? "✔" : ""; - MenuItem::step(); + nvgText(args.vg, textPos.x, textPos.y, SHAPE_INFOS[shape].code.c_str(), NULL); } }; @@ -309,14 +295,6 @@ struct BraidsWidget : ModuleWidget { setModule(module); setPanel(Svg::load(asset::plugin(pluginInstance, "res/Braids.svg"))); - { - BraidsDisplay* display = new BraidsDisplay(); - display->box.pos = Vec(14, 53); - display->box.size = Vec(148, 56); - display->module = module; - addChild(display); - } - addChild(createWidget(Vec(15, 0))); addChild(createWidget(Vec(210, 0))); addChild(createWidget(Vec(15, 365))); @@ -338,6 +316,12 @@ struct BraidsWidget : ModuleWidget { addInput(createInput(Vec(122, 316), module, Braids::TIMBRE_INPUT)); addInput(createInput(Vec(160, 316), module, Braids::COLOR_INPUT)); addOutput(createOutput(Vec(205, 316), module, Braids::OUT_OUTPUT)); + + BraidsDisplay* display = new BraidsDisplay(); + display->box.pos = Vec(14, 53); + display->box.size = Vec(148, 56); + display->module = module; + addChild(display); } void appendContextMenu(Menu* menu) override { @@ -345,6 +329,15 @@ struct BraidsWidget : ModuleWidget { menu->addChild(new MenuSeparator); + std::vector shapeLabels; + for (const ShapeInfo& s : SHAPE_INFOS) { + shapeLabels.push_back(s.label + " (" + s.code + ")"); + } + menu->addChild(createIndexSubmenuItem("Model", shapeLabels, + [=]() {return module->getShapeParam();}, + [=](int i) {module->setShapeParam(i);} + )); + menu->addChild(createBoolPtrMenuItem("FM CV selects model (META)", &module->settings.meta_modulation)); menu->addChild(createBoolMenuItem("Pitch drift (DRFT)",