| @@ -54,13 +54,13 @@ struct Braids : Module { | |||||
| configInput(COLOR_INPUT, "Color"); | configInput(COLOR_INPUT, "Color"); | ||||
| configOutput(OUT_OUTPUT, "Audio"); | configOutput(OUT_OUTPUT, "Audio"); | ||||
| memset(&osc, 0, sizeof(osc)); | |||||
| std::memset(&osc, 0, sizeof(osc)); | |||||
| osc.Init(); | osc.Init(); | ||||
| memset(&jitter_source, 0, sizeof(jitter_source)); | |||||
| std::memset(&jitter_source, 0, sizeof(jitter_source)); | |||||
| jitter_source.Init(); | jitter_source.Init(); | ||||
| memset(&ws, 0, sizeof(ws)); | |||||
| std::memset(&ws, 0, sizeof(ws)); | |||||
| ws.Init(0x0000); | ws.Init(0x0000); | ||||
| memset(&settings, 0, sizeof(settings)); | |||||
| std::memset(&settings, 0, sizeof(settings)); | |||||
| // List of supported settings | // List of supported settings | ||||
| settings.meta_modulation = 0; | settings.meta_modulation = 0; | ||||
| @@ -81,9 +81,9 @@ struct Braids : Module { | |||||
| float fm = params[FM_PARAM].getValue() * inputs[FM_INPUT].getVoltage(); | float fm = params[FM_PARAM].getValue() * inputs[FM_INPUT].getVoltage(); | ||||
| // Set shape | // 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) { | 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); | settings.shape = clamp(shape, 0, braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | ||||
| @@ -102,7 +102,7 @@ struct Braids : Module { | |||||
| if (!settings.meta_modulation) | if (!settings.meta_modulation) | ||||
| pitchV += fm; | pitchV += fm; | ||||
| if (lowCpu) | if (lowCpu) | ||||
| pitchV += log2f(96000.f * args.sampleTime); | |||||
| pitchV += std::log2(96000.f * args.sampleTime); | |||||
| int32_t pitch = (pitchV * 12.0 + 60) * 128; | int32_t pitch = (pitchV * 12.0 + 60) * 128; | ||||
| pitch += jitter_source.Render(settings.vco_drift); | pitch += jitter_source.Render(settings.vco_drift); | ||||
| pitch = clamp(pitch, 0, 16383); | pitch = clamp(pitch, 0, 16383); | ||||
| @@ -184,62 +184,73 @@ struct Braids : Module { | |||||
| lowCpu = json_boolean_value(lowCpuJ); | 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<ShapeInfo> 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 { | struct BraidsDisplay : TransparentWidget { | ||||
| Braids* module; | Braids* module; | ||||
| std::shared_ptr<Font> font; | std::shared_ptr<Font> font; | ||||
| @@ -271,35 +282,10 @@ struct BraidsDisplay : TransparentWidget { | |||||
| Vec textPos = Vec(11, 47); | Vec textPos = Vec(11, 47); | ||||
| NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); | NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); | ||||
| nvgFillColor(args.vg, nvgTransRGBA(textColor, 16)); | nvgFillColor(args.vg, nvgTransRGBA(textColor, 16)); | ||||
| // Background of all segments | |||||
| nvgText(args.vg, textPos.x, textPos.y, "~~~~", NULL); | nvgText(args.vg, textPos.x, textPos.y, "~~~~", NULL); | ||||
| nvgFillColor(args.vg, textColor); | 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); | setModule(module); | ||||
| setPanel(Svg::load(asset::plugin(pluginInstance, "res/Braids.svg"))); | 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<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
| addChild(createWidget<ScrewSilver>(Vec(210, 0))); | addChild(createWidget<ScrewSilver>(Vec(210, 0))); | ||||
| addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
| @@ -338,6 +316,12 @@ struct BraidsWidget : ModuleWidget { | |||||
| addInput(createInput<PJ301MPort>(Vec(122, 316), module, Braids::TIMBRE_INPUT)); | addInput(createInput<PJ301MPort>(Vec(122, 316), module, Braids::TIMBRE_INPUT)); | ||||
| addInput(createInput<PJ301MPort>(Vec(160, 316), module, Braids::COLOR_INPUT)); | addInput(createInput<PJ301MPort>(Vec(160, 316), module, Braids::COLOR_INPUT)); | ||||
| addOutput(createOutput<PJ301MPort>(Vec(205, 316), module, Braids::OUT_OUTPUT)); | addOutput(createOutput<PJ301MPort>(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 { | void appendContextMenu(Menu* menu) override { | ||||
| @@ -345,6 +329,15 @@ struct BraidsWidget : ModuleWidget { | |||||
| menu->addChild(new MenuSeparator); | menu->addChild(new MenuSeparator); | ||||
| std::vector<std::string> 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(createBoolPtrMenuItem("FM CV selects model (META)", &module->settings.meta_modulation)); | ||||
| menu->addChild(createBoolMenuItem("Pitch drift (DRFT)", | menu->addChild(createBoolMenuItem("Pitch drift (DRFT)", | ||||