From 06dbd23898291b90e46f7394c8c0d92082e09bc9 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Thu, 17 May 2018 08:19:40 +0200 Subject: [PATCH] Changed all "double" values to macro FRAC_NUM (defined in synth.h as float), for using the FPU in the Teensy. Added shortcut if audio output is blocking -> go to MIDI input checking. --- EngineMkI.cpp | 4 ++-- MicroDexed.ino | 5 ++++- dx7note.cpp | 2 +- env.cc | 6 +++--- env.cpp | 2 +- env.h | 2 +- exp2.cpp | 20 ++++++++++---------- fm_op_kernel.cc | 4 ++-- fm_op_kernel.cpp | 4 ++-- freqlut.cpp | 6 +++--- freqlut.h | 4 +++- lfo.cpp | 2 +- lfo.h | 2 +- pitchenv.cpp | 2 +- pitchenv.h | 2 +- sin.cpp | 2 +- synth.h | 2 ++ 17 files changed, 39 insertions(+), 32 deletions(-) diff --git a/EngineMkI.cpp b/EngineMkI.cpp index 4924e33..a4a1709 100644 --- a/EngineMkI.cpp +++ b/EngineMkI.cpp @@ -36,10 +36,10 @@ #ifdef _WIN32 #if _MSC_VER < 1800 - double log2(double n) { + FRAC_NUM log2(FRAC_NUM n) { return log(n) / log(2.0); } - double round(double n) { + FRAC_NUM round(FRAC_NUM n) { return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); } #endif diff --git a/MicroDexed.ino b/MicroDexed.ino index ca88799..cac25ae 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -21,7 +21,7 @@ #define MAX_NOTES 10 #define TEST_MIDI 1 #define TEST_NOTE 40 -#define TEST_VEL 60 +#define TEST_VEL 127 //#define ADD_EFFECT_CHORUS 1 // Use these with the Teensy Audio Shield @@ -180,6 +180,9 @@ void loop() break; } + if(!queue1.available()) + continue; + #if defined(SHOW_DEXED_TIMING) || defined(SHOW_XRUN) elapsedMicros t1; #endif diff --git a/dx7note.cpp b/dx7note.cpp index 0bd6071..cd8bd4f 100644 --- a/dx7note.cpp +++ b/dx7note.cpp @@ -45,7 +45,7 @@ int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) { if (mode == 0) { logfreq = midinote_to_logfreq(midinote); // could use more precision, closer enough for now. those numbers comes from my DX7 - double detuneRatio = 0.0209 * exp(-0.396 * (((float)logfreq) / (1 << 24))) / 7; + FRAC_NUM detuneRatio = 0.0209 * exp(-0.396 * (((float)logfreq) / (1 << 24))) / 7; logfreq += detuneRatio * logfreq * (detune - 7); logfreq += coarsemul[coarse & 31]; diff --git a/env.cc b/env.cc index 58478a3..8e497c4 100644 --- a/env.cc +++ b/env.cc @@ -39,11 +39,11 @@ const int statics[] = { 6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249, 1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705, 573, 573, 529, 441, 441 - // and so on, I stopped measuring after R=76 (needs to be double-checked anyway) + // and so on, I stopped measuring after R=76 (needs to be FRAC_NUM-checked anyway) }; #endif -void Env::init_sr(double sampleRate) { +void Env::init_sr(FRAC_NUM sampleRate) { sr_multiplier = (44100.0 / sampleRate) * (1<<24); } @@ -128,7 +128,7 @@ void Env::advance(int newix) { #ifdef ACCURATE_ENVELOPE if (targetlevel_ == level_) { // approximate number of samples at 44.100 kHz to achieve the time - // empirically gathered using 2 TF1s, could probably use some double-checking + // empirically gathered using 2 TF1s, could probably use some FRAC_NUM-checking // and cleanup, but it's pretty close for now. int staticrate = rates_[ix_]; staticrate += rate_scaling_; // needs to be checked, as well, but seems correct diff --git a/env.cpp b/env.cpp index b6b98de..797841f 100644 --- a/env.cpp +++ b/env.cpp @@ -28,7 +28,7 @@ const int levellut[] = { 0, 5, 9, 13, 17, 20, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 43, 45, 46 }; -void Env::init_sr(double sampleRate) { +void Env::init_sr(FRAC_NUM sampleRate) { sr_multiplier = (44100.0 / sampleRate) * (1<<24); } diff --git a/env.h b/env.h index 1285412..cc5b124 100644 --- a/env.h +++ b/env.h @@ -48,7 +48,7 @@ class Env { static int scaleoutlevel(int outlevel); void getPosition(char *step); - static void init_sr(double sample_rate); + static void init_sr(FRAC_NUM sample_rate); void transfer(Env &src); private: diff --git a/exp2.cpp b/exp2.cpp index 84feb20..5c93b3b 100644 --- a/exp2.cpp +++ b/exp2.cpp @@ -31,8 +31,8 @@ int32_t exp2tab[EXP2_N_SAMPLES << 1]; void Exp2::init() { - double inc = exp2(1.0 / EXP2_N_SAMPLES); - double y = 1 << 30; + FRAC_NUM inc = exp2(1.0 / EXP2_N_SAMPLES); + FRAC_NUM y = 1 << 30; for (int i = 0; i < EXP2_N_SAMPLES; i++) { exp2tab[(i << 1) + 1] = (int32_t)floor(y + 0.5); y *= inc; @@ -45,23 +45,23 @@ void Exp2::init() { int32_t tanhtab[TANH_N_SAMPLES << 1]; -static double dtanh(double y) { +static FRAC_NUM dtanh(FRAC_NUM y) { return 1 - y * y; } void Tanh::init() { - double step = 4.0 / TANH_N_SAMPLES; - double y = 0; + FRAC_NUM step = 4.0 / TANH_N_SAMPLES; + FRAC_NUM y = 0; for (int i = 0; i < TANH_N_SAMPLES; i++) { tanhtab[(i << 1) + 1] = (1 << 24) * y + 0.5; //printf("%d\n", tanhtab[(i << 1) + 1]); // Use a basic 4th order Runge-Kutte to compute tanh from its // differential equation. - double k1 = dtanh(y); - double k2 = dtanh(y + 0.5 * step * k1); - double k3 = dtanh(y + 0.5 * step * k2); - double k4 = dtanh(y + step * k3); - double dy = (step / 6) * (k1 + k4 + 2 * (k2 + k3)); + FRAC_NUM k1 = dtanh(y); + FRAC_NUM k2 = dtanh(y + 0.5 * step * k1); + FRAC_NUM k3 = dtanh(y + 0.5 * step * k2); + FRAC_NUM k4 = dtanh(y + step * k3); + FRAC_NUM dy = (step / 6) * (k1 + k4 + 2 * (k2 + k3)); y += dy; } for (int i = 0; i < TANH_N_SAMPLES - 1; i++) { diff --git a/fm_op_kernel.cc b/fm_op_kernel.cc index 20a61a8..1c93ba0 100644 --- a/fm_op_kernel.cc +++ b/fm_op_kernel.cc @@ -212,7 +212,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, #if 0 // Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) -// with double accuracy initialization: mean 1.55, worst 58 (near freq = 0) +// with FRAC_NUM accuracy initialization: mean 1.55, worst 58 (near freq = 0) // with high accuracy: mean 4.2, worst 292 (near freq = 0.5) void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { @@ -221,7 +221,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t phase = phase0; #ifdef DOUBLE_ACCURACY int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); - double a_d = sin(freq * (M_PI / (1 << 24))); + FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24))); int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); diff --git a/fm_op_kernel.cpp b/fm_op_kernel.cpp index 83c8f3b..bf962ca 100644 --- a/fm_op_kernel.cpp +++ b/fm_op_kernel.cpp @@ -212,7 +212,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, #if 0 // Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) -// with double accuracy initialization: mean 1.55, worst 58 (near freq = 0) +// with FRAC_NUM accuracy initialization: mean 1.55, worst 58 (near freq = 0) // with high accuracy: mean 4.2, worst 292 (near freq = 0.5) void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { @@ -221,7 +221,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t phase = phase0; #ifdef DOUBLE_ACCURACY int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); - double a_d = sin(freq * (M_PI / (1 << 24))); + FRAC_NUM a_d = sin(freq * (M_PI / (1 << 24))); int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) * (M_PI / (1 << 23))) + 0.5); int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); diff --git a/freqlut.cpp b/freqlut.cpp index 931ef67..9ecdc86 100644 --- a/freqlut.cpp +++ b/freqlut.cpp @@ -32,9 +32,9 @@ int32_t lut[N_SAMPLES + 1]; -void Freqlut::init(double sample_rate) { - double y = (1LL << (24 + MAX_LOGFREQ_INT)) / sample_rate; - double inc = pow(2, 1.0 / N_SAMPLES); +void Freqlut::init(FRAC_NUM sample_rate) { + FRAC_NUM y = (1LL << (24 + MAX_LOGFREQ_INT)) / sample_rate; + FRAC_NUM inc = pow(2, 1.0 / N_SAMPLES); for (int i = 0; i < N_SAMPLES + 1; i++) { lut[i] = (int32_t)floor(y + 0.5); y *= inc; diff --git a/freqlut.h b/freqlut.h index 5cba4af..3fc2e38 100644 --- a/freqlut.h +++ b/freqlut.h @@ -14,8 +14,10 @@ * limitations under the License. */ +#include "synth.h" + class Freqlut { public: - static void init(double sample_rate); + static void init(FRAC_NUM sample_rate); static int32_t lookup(int32_t logfreq); }; diff --git a/lfo.cpp b/lfo.cpp index 1486811..f6ee069 100644 --- a/lfo.cpp +++ b/lfo.cpp @@ -23,7 +23,7 @@ uint32_t Lfo::unit_; -void Lfo::init(double sample_rate) { +void Lfo::init(FRAC_NUM sample_rate) { // constant is 1 << 32 / 15.5s / 11 Lfo::unit_ = (int32_t)(_N_ * 25190424 / sample_rate + 0.5); } diff --git a/lfo.h b/lfo.h index 5a17625..f59bbf6 100644 --- a/lfo.h +++ b/lfo.h @@ -18,7 +18,7 @@ class Lfo { public: - static void init(double sample_rate); + static void init(FRAC_NUM sample_rate); void reset(const uint8_t params[6]); // result is 0..1 in Q24 diff --git a/pitchenv.cpp b/pitchenv.cpp index 8b1f208..9ff29ca 100644 --- a/pitchenv.cpp +++ b/pitchenv.cpp @@ -19,7 +19,7 @@ int PitchEnv::unit_; -void PitchEnv::init(double sample_rate) { +void PitchEnv::init(FRAC_NUM sample_rate) { unit_ = _N_ * (1 << 24) / (21.3 * sample_rate) + 0.5; } diff --git a/pitchenv.h b/pitchenv.h index e106341..6386fc5 100644 --- a/pitchenv.h +++ b/pitchenv.h @@ -21,7 +21,7 @@ class PitchEnv { public: - static void init(double sample_rate); + static void init(FRAC_NUM sample_rate); // The rates and levels arrays are calibrated to match the Dx7 parameters // (ie, value 0..99). diff --git a/sin.cpp b/sin.cpp index 5b09de4..d137a72 100644 --- a/sin.cpp +++ b/sin.cpp @@ -29,7 +29,7 @@ int32_t sintab[SIN_N_SAMPLES + 1]; #endif void Sin::init() { - double dphase = 2 * M_PI / SIN_N_SAMPLES; + FRAC_NUM dphase = 2 * M_PI / SIN_N_SAMPLES; int32_t c = (int32_t)floor(cos(dphase) * (1 << 30) + 0.5); int32_t s = (int32_t)floor(sin(dphase) * (1 << 30) + 0.5); int32_t u = 1 << 30; diff --git a/synth.h b/synth.h index f24aab5..6080590 100644 --- a/synth.h +++ b/synth.h @@ -62,4 +62,6 @@ inline static T max(const T& a, const T& b) { #define QER(n,b) ( ((float)n)/(1<