From 093ecdbb94700ecd212195303efc066e28ae26ba Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 9 Aug 2017 10:47:13 -0700 Subject: [PATCH] Add param randomization, changed mapf to rescalef, other refactors --- Makefile | 2 +- include/app.hpp | 1 + include/components.hpp | 12 +++++-- include/dsp.hpp | 62 +++++++++++++++++++++++++++++-------- include/gui.hpp | 1 + include/math.hpp | 11 ++++++- include/rack.hpp | 2 +- include/util.hpp | 18 +++++++++++ src/app/ModuleWidget.cpp | 18 +++++++++++ src/app/SVGKnob.cpp | 2 +- src/app/SVGSlider.cpp | 2 +- src/app/SVGSwitch.cpp | 2 +- src/app/SpriteKnob.cpp | 2 +- src/dsp.cpp | 40 ------------------------ src/gui.cpp | 8 ++--- src/widgets/ProgressBar.cpp | 2 +- src/widgets/Slider.cpp | 2 +- 17 files changed, 119 insertions(+), 68 deletions(-) diff --git a/Makefile b/Makefile index 32311f9e..88b21f7d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ARCH ?= lin -FLAGS = -g -Wall -O3 -msse -mfpmath=sse -ffast-math -fno-finite-math-only \ +FLAGS = -g -Wall -O2 -msse -mfpmath=sse -ffast-math -fno-finite-math-only \ -I./ext -I./include CXXFLAGS = -fno-exceptions diff --git a/include/app.hpp b/include/app.hpp index 74b74dd3..646bc7e9 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -41,6 +41,7 @@ struct ModuleWidget : OpaqueWidget { void fromJson(json_t *root); void disconnectPorts(); void resetParams(); + void randomizeParams(); void draw(NVGcontext *vg); diff --git a/include/components.hpp b/include/components.hpp index f3b6171b..ab4312ae 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -518,6 +518,14 @@ struct TL1105 : SVGSwitch, MomentarySwitch { } }; +struct LEDButton : SVGSwitch, MomentarySwitch { + LEDButton() { + addFrame(SVG::load("res/ComponentLibrary/LEDButton.svg")); + sw->wrap(); + box.size = sw->box.size; + } +}; + struct BefacoSwitch : SVGSwitch, ToggleSwitch { BefacoSwitch() { addFrame(SVG::load("res/ComponentLibrary/BefacoSwitch_0.svg")); @@ -560,8 +568,8 @@ struct ScrewBlack : SVGScrew { struct LightPanel : Panel { LightPanel() { - // backgroundColor = nvgRGB(0xe8, 0xe8, 0xe8); - backgroundColor = nvgRGB(0xf4, 0xf4, 0xf4); + // backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); + backgroundColor = nvgRGB(0xf0, 0xf0, 0xf0); borderColor = nvgRGB(0xac, 0xac, 0xac); } }; diff --git a/include/dsp.hpp b/include/dsp.hpp index 25c6d9af..7a805787 100644 --- a/include/dsp.hpp +++ b/include/dsp.hpp @@ -76,9 +76,43 @@ struct SimpleFFT { typedef void (*stepCallback)(float x, const float y[], float dydt[]); /** Solve an ODE system using the 1st order Euler method */ -void stepEuler(stepCallback f, float x, float dx, float y[], int len); +inline void stepEuler(stepCallback f, float x, float dx, float y[], int len) { + float k[len]; + + f(x, y, k); + for (int i = 0; i < len; i++) { + y[i] += dx * k[i]; + } +} /** Solve an ODE system using the 4th order Runge-Kutta method */ -void stepRK4(stepCallback f, float x, float dx, float y[], int len); +inline void stepRK4(stepCallback f, float x, float dx, float y[], int len) { + float k1[len]; + float k2[len]; + float k3[len]; + float k4[len]; + float yi[len]; + + f(x, y, k1); + + for (int i = 0; i < len; i++) { + yi[i] = y[i] + k1[i] * dx / 2.0; + } + f(x + dx / 2.0, yi, k2); + + for (int i = 0; i < len; i++) { + yi[i] = y[i] + k2[i] * dx / 2.0; + } + f(x + dx / 2.0, yi, k3); + + for (int i = 0; i < len; i++) { + yi[i] = y[i] + k3[i] * dx; + } + f(x + dx, yi, k4); + + for (int i = 0; i < len; i++) { + y[i] += dx * (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]) / 6.0; + } +} /** A simple cyclic buffer. @@ -423,8 +457,8 @@ struct SlewLimiter { struct SchmittTrigger { - // false is low, true is high - bool state = false; + /** 0 unknown, 1 low, 2 high */ + int state = 0; float low = 0.0; float high = 1.0; void setThresholds(float low, float high) { @@ -433,17 +467,19 @@ struct SchmittTrigger { } /** Returns true if triggered */ bool process(float in) { - if (state) { - if (in < low) - state = false; + bool triggered = false; + if (in >= high) { + if (state == 1) + triggered = true; + state = 2; } - else { - if (in >= high) { - state = true; - return true; - } + else if (in <= low) { + state = 1; } - return false; + return triggered; + } + void reset() { + state = 0; } }; diff --git a/include/gui.hpp b/include/gui.hpp index 6e26909c..0d31c3a5 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -15,5 +15,6 @@ const char *guiSaveDialog(const char *filters, const char *filename); const char *guiOpenDialog(const char *filters, const char *filename); extern NVGcontext *gVg; +extern std::shared_ptr gGuiFont; } // namespace rack diff --git a/include/math.hpp b/include/math.hpp index 87ee573d..ca83a664 100644 --- a/include/math.hpp +++ b/include/math.hpp @@ -69,7 +69,7 @@ inline float chopf(float x, float eps) { return -eps < x && x < eps ? 0.0 : x; } -inline float mapf(float x, float xMin, float xMax, float yMin, float yMax) { +inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) { return yMin + (x - xMin) / (xMax - xMin) * (yMax - yMin); } @@ -130,6 +130,15 @@ inline float interpf(const float *p, float x) { return crossf(p[xi], p[xi+1], xf); } +/** Complex multiply c = a * b +It is of course acceptable to reuse arguments +i.e. cmultf(&ar, &ai, ar, ai, br, bi) +*/ +inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) { + *cr = ar * br - ai * bi; + *ci = ar * bi + ai * br; +} + //////////////////// // 2D float vector //////////////////// diff --git a/include/rack.hpp b/include/rack.hpp index 6fa7786b..ffee63b1 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -1,7 +1,7 @@ #pragma once -#include "math.hpp" #include "util.hpp" +#include "math.hpp" #include "plugin.hpp" #include "engine.hpp" #include "gui.hpp" diff --git a/include/util.hpp b/include/util.hpp index 20872765..a4c4d8e4 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -11,6 +11,24 @@ #include +/** Surrounds raw text with quotes +Example: + printf("Hello " STRINGIFY(world)) +will expand to + printf("Hello " "world") +and of course the C++ lexer/parser will then concatenate the string literals +*/ +#define STRINGIFY(x) #x +/** Converts a macro to a string literal +Example: + #define NAME "world" + printf("Hello " TOSTRING(NAME)) +will expand to + printf("Hello " "world") +*/ +#define TOSTRING(x) STRINGIFY(x) + + namespace rack { diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 148362fa..93ac7e0d 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -104,6 +104,12 @@ void ModuleWidget::resetParams() { } } +void ModuleWidget::randomizeParams() { + for (ParamWidget *param : params) { + param->setValue(rescalef(randomf(), 0.0, 1.0, param->minValue, param->maxValue)); + } +} + void ModuleWidget::draw(NVGcontext *vg) { nvgScissor(vg, 0, 0, box.size.x, box.size.y); @@ -160,6 +166,13 @@ struct ResetParamsMenuItem : MenuItem { } }; +struct RandomizeParamsMenuItem : MenuItem { + ModuleWidget *moduleWidget; + void onAction() { + moduleWidget->randomizeParams(); + } +}; + struct CloneModuleMenuItem : MenuItem { ModuleWidget *moduleWidget; void onAction() { @@ -197,6 +210,11 @@ void ModuleWidget::onMouseDown(int button) { resetItem->moduleWidget = this; menu->pushChild(resetItem); + RandomizeParamsMenuItem *randomizeParams = new RandomizeParamsMenuItem(); + randomizeParams->text = "Randomize"; + randomizeParams->moduleWidget = this; + menu->pushChild(randomizeParams); + DisconnectPortsMenuItem *disconnectItem = new DisconnectPortsMenuItem(); disconnectItem->text = "Disconnect cables"; disconnectItem->moduleWidget = this; diff --git a/src/app/SVGKnob.cpp b/src/app/SVGKnob.cpp index 61f31c8f..8ff7eb6b 100644 --- a/src/app/SVGKnob.cpp +++ b/src/app/SVGKnob.cpp @@ -24,7 +24,7 @@ void SVGKnob::setSVG(std::shared_ptr svg) { void SVGKnob::step() { // Re-transform TransformWidget if dirty if (dirty) { - float angle = mapf(value, minValue, maxValue, minAngle, maxAngle); + float angle = rescalef(value, minValue, maxValue, minAngle, maxAngle); tw->identity(); // Rotate SVG Vec center = sw->box.getCenter(); diff --git a/src/app/SVGSlider.cpp b/src/app/SVGSlider.cpp index 4821ec73..2bd40e8e 100644 --- a/src/app/SVGSlider.cpp +++ b/src/app/SVGSlider.cpp @@ -15,7 +15,7 @@ SVGSlider::SVGSlider() { void SVGSlider::step() { if (dirty) { // Update handle position - Vec handlePos = Vec(mapf(value, minValue, maxValue, minHandlePos.x, maxHandlePos.x), mapf(value, minValue, maxValue, minHandlePos.y, maxHandlePos.y)); + Vec handlePos = Vec(rescalef(value, minValue, maxValue, minHandlePos.x, maxHandlePos.x), rescalef(value, minValue, maxValue, minHandlePos.y, maxHandlePos.y)); handle->box.pos = handlePos; } FramebufferWidget::step(); diff --git a/src/app/SVGSwitch.cpp b/src/app/SVGSwitch.cpp index d55bfd93..86803e6a 100644 --- a/src/app/SVGSwitch.cpp +++ b/src/app/SVGSwitch.cpp @@ -24,7 +24,7 @@ void SVGSwitch::step() { } void SVGSwitch::onChange() { - int index = roundf(mapf(value, minValue, maxValue, 0, frames.size() - 1)); + int index = roundf(rescalef(value, minValue, maxValue, 0, frames.size() - 1)); if (0 <= index && index < (int)frames.size()) sw->svg = frames[index]; dirty = true; diff --git a/src/app/SpriteKnob.cpp b/src/app/SpriteKnob.cpp index 06e00739..0ab19025 100644 --- a/src/app/SpriteKnob.cpp +++ b/src/app/SpriteKnob.cpp @@ -4,7 +4,7 @@ namespace rack { void SpriteKnob::step() { - index = eucmodi((int) roundf(mapf(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); + index = eucmodi((int) roundf(rescalef(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); } } // namespace rack diff --git a/src/dsp.cpp b/src/dsp.cpp index 9b3fe0e7..8174e181 100644 --- a/src/dsp.cpp +++ b/src/dsp.cpp @@ -14,44 +14,4 @@ const float minblep_16_32[] = { }; - -void stepEuler(stepCallback f, float x, float dx, float y[], int len) { - float k[len]; - - f(x, y, k); - for (int i = 0; i < len; i++) { - y[i] += dx * k[i]; - } -} - -void stepRK4(stepCallback f, float x, float dx, float y[], int len) { - float k1[len]; - float k2[len]; - float k3[len]; - float k4[len]; - float yi[len]; - - f(x, y, k1); - - for (int i = 0; i < len; i++) { - yi[i] = y[i] + k1[i] * dx / 2.0; - } - f(x + dx / 2.0, yi, k2); - - for (int i = 0; i < len; i++) { - yi[i] = y[i] + k2[i] * dx / 2.0; - } - f(x + dx / 2.0, yi, k3); - - for (int i = 0; i < len; i++) { - yi[i] = y[i] + k3[i] * dx; - } - f(x + dx, yi, k4); - - for (int i = 0; i < len; i++) { - y[i] += dx * (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]) / 6.0; - } -} - - } // namespace rack diff --git a/src/gui.cpp b/src/gui.cpp index 3817ef01..74822456 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -25,7 +25,7 @@ extern "C" { namespace rack { static GLFWwindow *window = NULL; -static std::shared_ptr defaultFont; +std::shared_ptr gGuiFont; NVGcontext *gVg = NULL; @@ -232,13 +232,13 @@ void guiInit() { assert(gVg); // Set up Blendish - defaultFont = Font::load("res/DejaVuSans.ttf"); - bndSetFont(defaultFont->handle); + gGuiFont = Font::load("res/DejaVuSans.ttf"); + bndSetFont(gGuiFont->handle); // bndSetIconImage(loadImage("res/icons.png")); } void guiDestroy() { - defaultFont.reset(); + gGuiFont.reset(); nvgDeleteGL2(gVg); // nvgDeleteGL3(gVg); glfwDestroyWindow(window); diff --git a/src/widgets/ProgressBar.cpp b/src/widgets/ProgressBar.cpp index 8edb7ee9..862343d1 100644 --- a/src/widgets/ProgressBar.cpp +++ b/src/widgets/ProgressBar.cpp @@ -4,7 +4,7 @@ namespace rack { void ProgressBar::draw(NVGcontext *vg) { - float progress = mapf(value, minValue, maxValue, 0.0, 1.0); + float progress = rescalef(value, minValue, maxValue, 0.0, 1.0); bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, getText().c_str(), NULL); } diff --git a/src/widgets/Slider.cpp b/src/widgets/Slider.cpp index 9f46f755..9727eefd 100644 --- a/src/widgets/Slider.cpp +++ b/src/widgets/Slider.cpp @@ -7,7 +7,7 @@ namespace rack { #define SLIDER_SENSITIVITY 0.001 void Slider::draw(NVGcontext *vg) { - float progress = mapf(value, minValue, maxValue, 0.0, 1.0); + float progress = rescalef(value, minValue, maxValue, 0.0, 1.0); bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, getText().c_str(), NULL); }