diff --git a/.gitmodules b/.gitmodules index 1968c884..1657af82 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "ext/nanosvg"] path = ext/nanosvg url = https://github.com/memononen/nanosvg.git +[submodule "ext/dr_libs"] + path = ext/dr_libs + url = https://github.com/mackron/dr_libs.git diff --git a/README.md b/README.md index 04ea0a5e..ebd60f58 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # Rack -Open source Eurorack-style modular DAW +Open source virtual Eurorack DAW ## Building @@ -21,3 +21,9 @@ Install dependencies Run `make ARCH=lin` or `make ARCH=win` or `make ARCH=mac` If the build breaks because you think I've missed a step, feel free to post an issue. + +## License + +Rack source code by Andrew Belt: BSD-3-Clause + +Component Library graphics by [Grayscale](http://grayscale.info/): [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/) diff --git a/ext/dr_libs b/ext/dr_libs new file mode 160000 index 00000000..6fb1f8a9 --- /dev/null +++ b/ext/dr_libs @@ -0,0 +1 @@ +Subproject commit 6fb1f8a9f8bb3198e05ee52aa38f177c499c1bef diff --git a/include/components.hpp b/include/components.hpp index f3cecf24..1fa8ed01 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -440,8 +440,8 @@ struct SilverScrew : Screw { struct LightPanel : Panel { LightPanel() { - backgroundColor = nvgRGB(0xe8, 0xe8, 0xe8); - borderColor = nvgRGB(0xa1, 0xa1, 0xa1); + backgroundColor = nvgRGB(0xf2, 0xf2, 0xf2); + borderColor = nvgRGB(0xb8, 0xb8, 0xb8); } }; diff --git a/include/dsp.hpp b/include/dsp.hpp index 8e9569f8..1e57a9e4 100644 --- a/include/dsp.hpp +++ b/include/dsp.hpp @@ -5,6 +5,7 @@ #include #include #include "math.hpp" +#include "../ext/dr_libs/dr_wav.h" namespace rack { @@ -320,4 +321,23 @@ struct RCFilter { }; +struct PeakFilter { + float state = 0.0; + float c = 0.0; + + /** Rate is lambda / sampleRate */ + void setRate(float r) { + c = 1.0 - r; + } + void process(float x) { + if (x > state) + state = x; + state *= c; + } + float peak() { + return state; + } +}; + + } // namespace rack diff --git a/include/gui.hpp b/include/gui.hpp index b25488da..6e26909c 100644 --- a/include/gui.hpp +++ b/include/gui.hpp @@ -8,6 +8,7 @@ namespace rack { void guiInit(); void guiDestroy(); void guiRun(); +bool guiIsKeyPressed(int key); void guiCursorLock(); void guiCursorUnlock(); const char *guiSaveDialog(const char *filters, const char *filename); diff --git a/include/math.hpp b/include/math.hpp index d2f3336a..ae14bfec 100644 --- a/include/math.hpp +++ b/include/math.hpp @@ -44,6 +44,11 @@ inline bool ispow2(int n) { // float functions //////////////////// +/** Returns 1.0 for positive numbers and -1.0 for negative numbers (including positive/negative zero) */ +inline float sgnf(float x) { + return copysignf(1.0, x); +} + inline float radtodeg(float x) { return x * (180.0 / M_PI); } diff --git a/include/widgets.hpp b/include/widgets.hpp index e6ed277d..3dc40941 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -191,6 +191,10 @@ Events are not passed to the underlying scene. struct FramebufferWidget : virtual Widget { /** Set this to true to re-render the scene to the framebuffer in the next step() */ bool dirty = true; + /** A margin in pixels around the scene in the framebuffer + This prevents cutting the rendered SVG off on the box edges. + */ + int margin = 0; /** The root object in the framebuffer scene The FramebufferWidget owns the pointer */ diff --git a/src/app.cpp b/src/app.cpp index 1651a6c1..8434cd36 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -4,7 +4,7 @@ namespace rack { std::string gApplicationName = "VCV Rack"; -std::string gApplicationVersion = "v0.1.1 alpha"; +std::string gApplicationVersion = "v0.2.0 alpha"; RackWidget *gRackWidget = NULL; diff --git a/src/app/Knob.cpp b/src/app/Knob.cpp index 5a6297b8..76c6414d 100644 --- a/src/app/Knob.cpp +++ b/src/app/Knob.cpp @@ -1,5 +1,7 @@ #include "app.hpp" #include "gui.hpp" +// For GLFW_KEY_LEFT_CONTROL, etc. +#include namespace rack { @@ -12,6 +14,9 @@ void Knob::onDragStart() { } void Knob::onDragMove(Vec mouseRel) { + // Drag slower if Ctrl is held + if (guiIsKeyPressed(GLFW_KEY_LEFT_CONTROL) || guiIsKeyPressed(GLFW_KEY_RIGHT_CONTROL)) + mouseRel = mouseRel.mult(0.1); setValue(value - KNOB_SENSITIVITY * (maxValue - minValue) * mouseRel.y); } diff --git a/src/app/SVGKnob.cpp b/src/app/SVGKnob.cpp index 24790030..494b23ba 100644 --- a/src/app/SVGKnob.cpp +++ b/src/app/SVGKnob.cpp @@ -5,6 +5,8 @@ namespace rack { SVGKnob::SVGKnob() { + margin = 1; + tw = new TransformWidget(); setScene(tw); @@ -44,7 +46,7 @@ void SVGKnob::draw(NVGcontext *vg) { nvgRect(vg, -margin, -margin, box.size.x + 2*margin, box.size.y + 2*margin); nvgFillColor(vg, nvgRGBAf(0.0, 0.0, 0.0, 0.25)); Vec c = box.size.div(2.0); - float radius = c.x - 1; + float radius = c.x; NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, 0.25); NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0); NVGpaint paint = nvgRadialGradient(vg, c.x, c.y + 1, radius, radius + 3, icol, ocol); diff --git a/src/dsp.cpp b/src/dsp.cpp index 80b0d5c7..8174e181 100644 --- a/src/dsp.cpp +++ b/src/dsp.cpp @@ -1,6 +1,10 @@ #include "dsp.hpp" +#define DR_WAV_IMPLEMENTATION +#include "../ext/dr_libs/dr_wav.h" + + namespace rack { diff --git a/src/gui.cpp b/src/gui.cpp index 30782bf0..094157f0 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -79,19 +79,11 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) { Vec mouseRel = mousePos.minus(gMousePos); gMousePos = mousePos; - bool locked = glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; - // onMouseMove Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel); if (gDraggedWidget) { // onDragMove - // Drag slower if Ctrl is held - if (locked) { - bool ctrl = glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS; - if (ctrl) - mouseRel = mouseRel.mult(0.1); - } gDraggedWidget->onDragMove(mouseRel); if (hovered != gDragHoveredWidget) { @@ -272,6 +264,10 @@ void guiRun() { } } +bool guiIsKeyPressed(int key) { + return glfwGetKey(window, key) == GLFW_PRESS; +} + void guiCursorLock() { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } diff --git a/src/widgets/FramebufferWidget.cpp b/src/widgets/FramebufferWidget.cpp index 1c7691a6..2bbc8042 100644 --- a/src/widgets/FramebufferWidget.cpp +++ b/src/widgets/FramebufferWidget.cpp @@ -32,11 +32,6 @@ FramebufferWidget::~FramebufferWidget() { delete internal; } -/** A margin in pixels around the scene in the framebuffer -This prevents cutting the rendered SVG off on the box edges. -*/ -static const int margin = 1; - void FramebufferWidget::step() { if (!scene) return;