@@ -34,10 +34,10 @@ struct SVGPanel; | |||
// 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 { | |||
@@ -1,6 +1,6 @@ | |||
#pragma once | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
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 | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
namespace rack { | |||
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
#include <string.h> | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
namespace rack { | |||
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
#include <list> | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
namespace rack { | |||
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
#include "util.hpp" | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
#include "asset.hpp" | |||
#include "plugin.hpp" | |||
#include "engine.hpp" | |||
@@ -8,7 +8,7 @@ | |||
namespace rack { | |||
//////////////////// | |||
// integer functions | |||
// basic integer functions (suffixed with "i") | |||
//////////////////// | |||
inline int mini(int a, int b) { | |||
@@ -19,22 +19,28 @@ inline int maxi(int a, int 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) { | |||
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) { | |||
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) { | |||
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) { | |||
int i = 0; | |||
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) { | |||
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) { | |||
return copysignf(1.f, x); | |||
} | |||
inline float eucmodf(float a, float 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) { | |||
@@ -81,7 +87,7 @@ inline float clampf(float x, float min, float max) { | |||
/** If the magnitude of x if less than eps, return 0 */ | |||
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) { | |||
@@ -92,41 +98,6 @@ inline float crossf(float a, float b, float frac) { | |||
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` | |||
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; | |||
@@ -154,7 +125,7 @@ struct Rect; | |||
struct Vec { | |||
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 neg() { | |||
@@ -203,7 +174,7 @@ struct Vec { | |||
return x == b.x && y == b.y; | |||
} | |||
bool isZero() { | |||
return x == 0.0 && y == 0.0; | |||
return x == 0.f && y == 0.f; | |||
} | |||
bool isFinite() { | |||
return std::isfinite(x) && std::isfinite(y); | |||
@@ -241,13 +212,13 @@ struct Rect { | |||
return pos.isEqual(r.pos) && size.isEqual(r.size); | |||
} | |||
Vec getCenter() { | |||
return pos.plus(size.mult(0.5)); | |||
return pos.plus(size.mult(0.5f)); | |||
} | |||
Vec getTopRight() { | |||
return pos.plus(Vec(size.x, 0.0)); | |||
return pos.plus(Vec(size.x, 0.f)); | |||
} | |||
Vec getBottomLeft() { | |||
return pos.plus(Vec(0.0, size.y)); | |||
return pos.plus(Vec(0.f, size.y)); | |||
} | |||
Vec getBottomRight() { | |||
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 | |||
//////////////////// |
@@ -6,7 +6,8 @@ | |||
#include "../ext/oui-blendish/blendish.h" | |||
#include "../ext/nanosvg/src/nanosvg.h" | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
#include "util/vec.hpp" | |||
#include "util.hpp" | |||
#include "events.hpp" | |||
@@ -185,30 +185,7 @@ void ModuleWidget::randomize() { | |||
void ModuleWidget::draw(NVGcontext *vg) { | |||
nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||
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); | |||
} | |||
@@ -1,5 +1,5 @@ | |||
#include "util.hpp" | |||
#include "math.hpp" | |||
#include "util/math.hpp" | |||
#include "audio.hpp" | |||