@@ -34,10 +34,10 @@ struct SVGPanel; | |||||
// module | // module | ||||
//////////////////// | //////////////////// | ||||
// A 1HPx3U module should be 15x380. Thus the width of a module should be a factor of 15. | |||||
#define RACK_GRID_WIDTH 15 | |||||
#define RACK_GRID_HEIGHT 380 | |||||
static const Vec RACK_GRID_SIZE = Vec(15, 380); | |||||
// A 1HPx3U module should be 15x380 pixels. Thus the width of a module should be a factor of 15. | |||||
static const float RACK_GRID_WIDTH = 15; | |||||
static const float RACK_GRID_HEIGHT = 380; | |||||
static const Vec RACK_GRID_SIZE = Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); | |||||
struct ModuleWidget : OpaqueWidget { | struct ModuleWidget : OpaqueWidget { | ||||
@@ -1,6 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -0,0 +1,46 @@ | |||||
#pragma once | |||||
#include <cmath> | |||||
namespace rack { | |||||
inline float sinc(float x) { | |||||
if (x == 0.f) | |||||
return 1.f; | |||||
x *= M_PI; | |||||
return sinf(x) / x; | |||||
} | |||||
inline float quadraticBipolar(float x) { | |||||
float x2 = x*x; | |||||
return (x >= 0.f) ? x2 : -x2; | |||||
} | |||||
inline float cubic(float x) { | |||||
return x*x*x; | |||||
} | |||||
inline float quarticBipolar(float x) { | |||||
float y = x*x*x*x; | |||||
return (x >= 0.f) ? y : -y; | |||||
} | |||||
inline float quintic(float x) { | |||||
// optimal with --fast-math | |||||
return x*x*x*x*x; | |||||
} | |||||
inline float sqrtBipolar(float x) { | |||||
return (x >= 0.f) ? sqrtf(x) : -sqrtf(-x); | |||||
} | |||||
/** This is pretty much a scaled sinh */ | |||||
inline float exponentialBipolar(float b, float x) { | |||||
const float a = b - 1.f / b; | |||||
return (powf(b, x) - powf(b, -x)) / a; | |||||
} | |||||
} // namespace rack |
@@ -1,6 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <string.h> | #include <string.h> | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <list> | #include <list> | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include "util.hpp" | #include "util.hpp" | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
#include "asset.hpp" | #include "asset.hpp" | ||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "engine.hpp" | #include "engine.hpp" | ||||
@@ -8,7 +8,7 @@ | |||||
namespace rack { | namespace rack { | ||||
//////////////////// | //////////////////// | ||||
// integer functions | |||||
// basic integer functions (suffixed with "i") | |||||
//////////////////// | //////////////////// | ||||
inline int mini(int a, int b) { | inline int mini(int a, int b) { | ||||
@@ -19,22 +19,28 @@ inline int maxi(int a, int b) { | |||||
return a > b ? a : b; | return a > b ? a : b; | ||||
} | } | ||||
/** Limits a value between a minimum and maximum */ | |||||
/** Limits a value between a minimum and maximum | |||||
*/ | |||||
inline int clampi(int x, int min, int max) { | inline int clampi(int x, int min, int max) { | ||||
return x > max ? max : x < min ? min : x; | |||||
if (min <= max) | |||||
return maxi(mini(x, max), min); | |||||
else | |||||
return maxi(mini(x, min), max); | |||||
} | } | ||||
inline int absi(int a) { | inline int absi(int a) { | ||||
return a >= 0 ? a : -a; | |||||
return (a >= 0) ? a : -a; | |||||
} | } | ||||
// Euclidean modulus, always returns 0 <= mod < base for positive base | |||||
// Assumes this architecture's division is non-Euclidean | |||||
/** Euclidean modulus, always returns 0 <= mod < base for positive base. | |||||
*/ | |||||
inline int eucmodi(int a, int base) { | inline int eucmodi(int a, int base) { | ||||
int mod = a % base; | int mod = a % base; | ||||
return mod < 0 ? mod + base : mod; | |||||
return (mod >= 0) ? mod + base : mod; | |||||
} | } | ||||
/** Returns floor(log_2(n)), or 0 if n == 1. | |||||
*/ | |||||
inline int log2i(int n) { | inline int log2i(int n) { | ||||
int i = 0; | int i = 0; | ||||
while (n >>= 1) { | while (n >>= 1) { | ||||
@@ -48,21 +54,21 @@ inline bool ispow2i(int n) { | |||||
} | } | ||||
//////////////////// | //////////////////// | ||||
// float functions | |||||
// basic float functions (suffixed with "f") | |||||
//////////////////// | //////////////////// | ||||
inline float absf(float x) { | inline float absf(float x) { | ||||
return (x < 0.f) ? -x : x; | return (x < 0.f) ? -x : x; | ||||
} | } | ||||
/** Returns 1.0 for positive numbers and -1.0 for negative numbers (including positive/negative zero) */ | |||||
/** Returns 1.f for positive numbers and -1.f for negative numbers (including positive/negative zero) */ | |||||
inline float sgnf(float x) { | inline float sgnf(float x) { | ||||
return copysignf(1.f, x); | return copysignf(1.f, x); | ||||
} | } | ||||
inline float eucmodf(float a, float base) { | inline float eucmodf(float a, float base) { | ||||
float mod = fmodf(a, base); | float mod = fmodf(a, base); | ||||
return (mod < 0.f) ? mod + base : mod; | |||||
return (mod < 0.f) ? mod : mod + base; | |||||
} | } | ||||
inline float nearf(float a, float b, float epsilon = 1e-6) { | inline float nearf(float a, float b, float epsilon = 1e-6) { | ||||
@@ -81,7 +87,7 @@ inline float clampf(float x, float min, float max) { | |||||
/** If the magnitude of x if less than eps, return 0 */ | /** If the magnitude of x if less than eps, return 0 */ | ||||
inline float chopf(float x, float eps) { | inline float chopf(float x, float eps) { | ||||
return -eps < x && x < eps ? 0.0 : x; | |||||
return (-eps < x && x < eps) ? 0.f : x; | |||||
} | } | ||||
inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) { | inline float rescalef(float x, float xMin, float xMax, float yMin, float yMax) { | ||||
@@ -92,41 +98,6 @@ inline float crossf(float a, float b, float frac) { | |||||
return a + frac * (b - a); | return a + frac * (b - a); | ||||
} | } | ||||
inline float quadraticBipolar(float x) { | |||||
float x2 = x*x; | |||||
return x >= 0.0 ? x2 : -x2; | |||||
} | |||||
inline float cubic(float x) { | |||||
return x*x*x; | |||||
} | |||||
inline float quarticBipolar(float x) { | |||||
return x >= 0.0 ? x*x*x*x : -x*x*x*x; | |||||
} | |||||
inline float quintic(float x) { | |||||
// optimal with --fast-math | |||||
return x*x*x*x*x; | |||||
} | |||||
inline float sqrtBipolar(float x) { | |||||
return x >= 0.0 ? sqrtf(x) : -sqrtf(-x); | |||||
} | |||||
/** This is pretty much a scaled sinh */ | |||||
inline float exponentialBipolar(float b, float x) { | |||||
const float a = b - 1.0 / b; | |||||
return (powf(b, x) - powf(b, -x)) / a; | |||||
} | |||||
inline float sincf(float x) { | |||||
if (x == 0.0) | |||||
return 1.0; | |||||
x *= M_PI; | |||||
return sinf(x) / x; | |||||
} | |||||
/** Linearly interpolate an array `p` with index `x` | /** Linearly interpolate an array `p` with index `x` | ||||
Assumes that the array at `p` is of length at least floor(x)+1. | Assumes that the array at `p` is of length at least floor(x)+1. | ||||
*/ | */ | ||||
@@ -146,7 +117,7 @@ inline void cmultf(float *cr, float *ci, float ar, float ai, float br, float bi) | |||||
} | } | ||||
//////////////////// | //////////////////// | ||||
// 2D float vector | |||||
// 2D vector and rectangle | |||||
//////////////////// | //////////////////// | ||||
struct Rect; | struct Rect; | ||||
@@ -154,7 +125,7 @@ struct Rect; | |||||
struct Vec { | struct Vec { | ||||
float x, y; | float x, y; | ||||
Vec() : x(0.0), y(0.0) {} | |||||
Vec() : x(0.f), y(0.f) {} | |||||
Vec(float x, float y) : x(x), y(y) {} | Vec(float x, float y) : x(x), y(y) {} | ||||
Vec neg() { | Vec neg() { | ||||
@@ -203,7 +174,7 @@ struct Vec { | |||||
return x == b.x && y == b.y; | return x == b.x && y == b.y; | ||||
} | } | ||||
bool isZero() { | bool isZero() { | ||||
return x == 0.0 && y == 0.0; | |||||
return x == 0.f && y == 0.f; | |||||
} | } | ||||
bool isFinite() { | bool isFinite() { | ||||
return std::isfinite(x) && std::isfinite(y); | return std::isfinite(x) && std::isfinite(y); | ||||
@@ -241,13 +212,13 @@ struct Rect { | |||||
return pos.isEqual(r.pos) && size.isEqual(r.size); | return pos.isEqual(r.pos) && size.isEqual(r.size); | ||||
} | } | ||||
Vec getCenter() { | Vec getCenter() { | ||||
return pos.plus(size.mult(0.5)); | |||||
return pos.plus(size.mult(0.5f)); | |||||
} | } | ||||
Vec getTopRight() { | Vec getTopRight() { | ||||
return pos.plus(Vec(size.x, 0.0)); | |||||
return pos.plus(Vec(size.x, 0.f)); | |||||
} | } | ||||
Vec getBottomLeft() { | Vec getBottomLeft() { | ||||
return pos.plus(Vec(0.0, size.y)); | |||||
return pos.plus(Vec(0.f, size.y)); | |||||
} | } | ||||
Vec getBottomRight() { | Vec getBottomRight() { | ||||
return pos.plus(size); | return pos.plus(size); |
@@ -64,46 +64,6 @@ T *construct(F f, V v, Args... args) { | |||||
} | } | ||||
//////////////////// | |||||
// RNG | |||||
//////////////////// | |||||
/** Seeds the RNG with the current time */ | |||||
void randomInit(); | |||||
uint32_t randomu32(); | |||||
uint64_t randomu64(); | |||||
/** Returns a uniform random float in the interval [0.0, 1.0) */ | |||||
float randomf(); | |||||
/** Returns a normal random number with mean 0 and std dev 1 */ | |||||
float randomNormal(); | |||||
//////////////////// | |||||
// String functions | |||||
//////////////////// | |||||
/** Converts a printf format string and optional arguments into a std::string */ | |||||
std::string stringf(const char *format, ...); | |||||
std::string lowercase(std::string s); | |||||
std::string uppercase(std::string s); | |||||
/** Truncates and adds "..." to a string, not exceeding `len` characters */ | |||||
std::string ellipsize(std::string s, size_t len); | |||||
bool startsWith(std::string str, std::string prefix); | |||||
std::string extractDirectory(std::string path); | |||||
std::string extractFilename(std::string path); | |||||
std::string extractExtension(std::string path); | |||||
//////////////////// | |||||
// Operating system functions | |||||
//////////////////// | |||||
/** Opens a URL, also happens to work with PDFs and folders. | |||||
Shell injection is possible, so make sure the URL is trusted or hard coded. | |||||
May block, so open in a new thread. | |||||
*/ | |||||
void openBrowser(std::string url); | |||||
//////////////////// | //////////////////// | ||||
// Thread functions | // Thread functions | ||||
//////////////////// | //////////////////// |
@@ -6,7 +6,8 @@ | |||||
#include "../ext/oui-blendish/blendish.h" | #include "../ext/oui-blendish/blendish.h" | ||||
#include "../ext/nanosvg/src/nanosvg.h" | #include "../ext/nanosvg/src/nanosvg.h" | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
#include "util/vec.hpp" | |||||
#include "util.hpp" | #include "util.hpp" | ||||
#include "events.hpp" | #include "events.hpp" | ||||
@@ -185,30 +185,7 @@ void ModuleWidget::randomize() { | |||||
void ModuleWidget::draw(NVGcontext *vg) { | void ModuleWidget::draw(NVGcontext *vg) { | ||||
nvgScissor(vg, 0, 0, box.size.x, box.size.y); | nvgScissor(vg, 0, 0, box.size.x, box.size.y); | ||||
Widget::draw(vg); | Widget::draw(vg); | ||||
// CPU usage text | |||||
if (0) { | |||||
float cpuTime = module ? module->cpuTime : 0.0; | |||||
std::string text = stringf("%.1f%%", cpuTime * 100.0); | |||||
nvgSave(vg); | |||||
nvgBeginPath(vg); | |||||
nvgRect(vg, 0.0, 0.0, box.size.x, BND_WIDGET_HEIGHT); | |||||
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
cpuTime = clampf(cpuTime, 0.0, 1.0); | |||||
nvgRect(vg, 0.0, 0.0, box.size.x * cpuTime, BND_WIDGET_HEIGHT); | |||||
nvgFillColor(vg, nvgHSL(0.33 * cubic(1.0 - cpuTime), 1.0, 0.4)); | |||||
nvgFill(vg); | |||||
bndMenuItem(vg, 0.0, 0.0, box.size.x, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, text.c_str()); | |||||
nvgRestore(vg); | |||||
} | |||||
nvgResetScissor(vg); | nvgResetScissor(vg); | ||||
} | } | ||||
@@ -1,5 +1,5 @@ | |||||
#include "util.hpp" | #include "util.hpp" | ||||
#include "math.hpp" | |||||
#include "util/math.hpp" | |||||
#include "audio.hpp" | #include "audio.hpp" | ||||