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.
pull/4/head
Holger Wirtz 7 years ago
parent b440783402
commit 06dbd23898
  1. 4
      EngineMkI.cpp
  2. 5
      MicroDexed.ino
  3. 2
      dx7note.cpp
  4. 6
      env.cc
  5. 2
      env.cpp
  6. 2
      env.h
  7. 20
      exp2.cpp
  8. 4
      fm_op_kernel.cc
  9. 4
      fm_op_kernel.cpp
  10. 6
      freqlut.cpp
  11. 4
      freqlut.h
  12. 2
      lfo.cpp
  13. 2
      lfo.h
  14. 2
      pitchenv.cpp
  15. 2
      pitchenv.h
  16. 2
      sin.cpp
  17. 2
      synth.h

@ -36,10 +36,10 @@
#ifdef _WIN32 #ifdef _WIN32
#if _MSC_VER < 1800 #if _MSC_VER < 1800
double log2(double n) { FRAC_NUM log2(FRAC_NUM n) {
return log(n) / log(2.0); 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); return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5);
} }
#endif #endif

@ -21,7 +21,7 @@
#define MAX_NOTES 10 #define MAX_NOTES 10
#define TEST_MIDI 1 #define TEST_MIDI 1
#define TEST_NOTE 40 #define TEST_NOTE 40
#define TEST_VEL 60 #define TEST_VEL 127
//#define ADD_EFFECT_CHORUS 1 //#define ADD_EFFECT_CHORUS 1
// Use these with the Teensy Audio Shield // Use these with the Teensy Audio Shield
@ -180,6 +180,9 @@ void loop()
break; break;
} }
if(!queue1.available())
continue;
#if defined(SHOW_DEXED_TIMING) || defined(SHOW_XRUN) #if defined(SHOW_DEXED_TIMING) || defined(SHOW_XRUN)
elapsedMicros t1; elapsedMicros t1;
#endif #endif

@ -45,7 +45,7 @@ int32_t osc_freq(int midinote, int mode, int coarse, int fine, int detune) {
if (mode == 0) { if (mode == 0) {
logfreq = midinote_to_logfreq(midinote); logfreq = midinote_to_logfreq(midinote);
// could use more precision, closer enough for now. those numbers comes from my DX7 // 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 += detuneRatio * logfreq * (detune - 7);
logfreq += coarsemul[coarse & 31]; logfreq += coarsemul[coarse & 31];

@ -39,11 +39,11 @@ const int statics[] = {
6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249, 6615, 6615, 5512, 5512, 4410, 3969, 3969, 3439, 2866, 2690, 2249,
1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705, 1984, 1896, 1808, 1411, 1367, 1234, 1146, 926, 837, 837, 705,
573, 573, 529, 441, 441 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 #endif
void Env::init_sr(double sampleRate) { void Env::init_sr(FRAC_NUM sampleRate) {
sr_multiplier = (44100.0 / sampleRate) * (1<<24); sr_multiplier = (44100.0 / sampleRate) * (1<<24);
} }
@ -128,7 +128,7 @@ void Env::advance(int newix) {
#ifdef ACCURATE_ENVELOPE #ifdef ACCURATE_ENVELOPE
if (targetlevel_ == level_) { if (targetlevel_ == level_) {
// approximate number of samples at 44.100 kHz to achieve the time // 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. // and cleanup, but it's pretty close for now.
int staticrate = rates_[ix_]; int staticrate = rates_[ix_];
staticrate += rate_scaling_; // needs to be checked, as well, but seems correct staticrate += rate_scaling_; // needs to be checked, as well, but seems correct

@ -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 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); sr_multiplier = (44100.0 / sampleRate) * (1<<24);
} }

@ -48,7 +48,7 @@ class Env {
static int scaleoutlevel(int outlevel); static int scaleoutlevel(int outlevel);
void getPosition(char *step); void getPosition(char *step);
static void init_sr(double sample_rate); static void init_sr(FRAC_NUM sample_rate);
void transfer(Env &src); void transfer(Env &src);
private: private:

@ -31,8 +31,8 @@
int32_t exp2tab[EXP2_N_SAMPLES << 1]; int32_t exp2tab[EXP2_N_SAMPLES << 1];
void Exp2::init() { void Exp2::init() {
double inc = exp2(1.0 / EXP2_N_SAMPLES); FRAC_NUM inc = exp2(1.0 / EXP2_N_SAMPLES);
double y = 1 << 30; FRAC_NUM y = 1 << 30;
for (int i = 0; i < EXP2_N_SAMPLES; i++) { for (int i = 0; i < EXP2_N_SAMPLES; i++) {
exp2tab[(i << 1) + 1] = (int32_t)floor(y + 0.5); exp2tab[(i << 1) + 1] = (int32_t)floor(y + 0.5);
y *= inc; y *= inc;
@ -45,23 +45,23 @@ void Exp2::init() {
int32_t tanhtab[TANH_N_SAMPLES << 1]; int32_t tanhtab[TANH_N_SAMPLES << 1];
static double dtanh(double y) { static FRAC_NUM dtanh(FRAC_NUM y) {
return 1 - y * y; return 1 - y * y;
} }
void Tanh::init() { void Tanh::init() {
double step = 4.0 / TANH_N_SAMPLES; FRAC_NUM step = 4.0 / TANH_N_SAMPLES;
double y = 0; FRAC_NUM y = 0;
for (int i = 0; i < TANH_N_SAMPLES; i++) { for (int i = 0; i < TANH_N_SAMPLES; i++) {
tanhtab[(i << 1) + 1] = (1 << 24) * y + 0.5; tanhtab[(i << 1) + 1] = (1 << 24) * y + 0.5;
//printf("%d\n", tanhtab[(i << 1) + 1]); //printf("%d\n", tanhtab[(i << 1) + 1]);
// Use a basic 4th order Runge-Kutte to compute tanh from its // Use a basic 4th order Runge-Kutte to compute tanh from its
// differential equation. // differential equation.
double k1 = dtanh(y); FRAC_NUM k1 = dtanh(y);
double k2 = dtanh(y + 0.5 * step * k1); FRAC_NUM k2 = dtanh(y + 0.5 * step * k1);
double k3 = dtanh(y + 0.5 * step * k2); FRAC_NUM k3 = dtanh(y + 0.5 * step * k2);
double k4 = dtanh(y + step * k3); FRAC_NUM k4 = dtanh(y + step * k3);
double dy = (step / 6) * (k1 + k4 + 2 * (k2 + k3)); FRAC_NUM dy = (step / 6) * (k1 + k4 + 2 * (k2 + k3));
y += dy; y += dy;
} }
for (int i = 0; i < TANH_N_SAMPLES - 1; i++) { for (int i = 0; i < TANH_N_SAMPLES - 1; i++) {

@ -212,7 +212,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
#if 0 #if 0
// Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) // 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) // 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, void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
int32_t gain1, int32_t gain2, bool add) { 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; int32_t phase = phase0;
#ifdef DOUBLE_ACCURACY #ifdef DOUBLE_ACCURACY
int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); 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) * int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) *
(M_PI / (1 << 23))) + 0.5); (M_PI / (1 << 23))) + 0.5);
int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5);

@ -212,7 +212,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
#if 0 #if 0
// Results: accuracy 370.0 mean, 15480 worst case (near freq = 0.5) // 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) // 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, void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq,
int32_t gain1, int32_t gain2, bool add) { 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; int32_t phase = phase0;
#ifdef DOUBLE_ACCURACY #ifdef DOUBLE_ACCURACY
int32_t u = floor((1 << 30) * sin(phase * (M_PI / (1 << 23))) + 0.5); 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) * int32_t v = floor((1LL << 31) * a_d * cos((phase - freq * 0.5) *
(M_PI / (1 << 23))) + 0.5); (M_PI / (1 << 23))) + 0.5);
int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5); int32_t aa = floor((1LL << 31) * a_d * a_d + 0.5);

@ -32,9 +32,9 @@
int32_t lut[N_SAMPLES + 1]; int32_t lut[N_SAMPLES + 1];
void Freqlut::init(double sample_rate) { void Freqlut::init(FRAC_NUM sample_rate) {
double y = (1LL << (24 + MAX_LOGFREQ_INT)) / sample_rate; FRAC_NUM y = (1LL << (24 + MAX_LOGFREQ_INT)) / sample_rate;
double inc = pow(2, 1.0 / N_SAMPLES); FRAC_NUM inc = pow(2, 1.0 / N_SAMPLES);
for (int i = 0; i < N_SAMPLES + 1; i++) { for (int i = 0; i < N_SAMPLES + 1; i++) {
lut[i] = (int32_t)floor(y + 0.5); lut[i] = (int32_t)floor(y + 0.5);
y *= inc; y *= inc;

@ -14,8 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include "synth.h"
class Freqlut { class Freqlut {
public: public:
static void init(double sample_rate); static void init(FRAC_NUM sample_rate);
static int32_t lookup(int32_t logfreq); static int32_t lookup(int32_t logfreq);
}; };

@ -23,7 +23,7 @@
uint32_t Lfo::unit_; uint32_t Lfo::unit_;
void Lfo::init(double sample_rate) { void Lfo::init(FRAC_NUM sample_rate) {
// constant is 1 << 32 / 15.5s / 11 // constant is 1 << 32 / 15.5s / 11
Lfo::unit_ = (int32_t)(_N_ * 25190424 / sample_rate + 0.5); Lfo::unit_ = (int32_t)(_N_ * 25190424 / sample_rate + 0.5);
} }

@ -18,7 +18,7 @@
class Lfo { class Lfo {
public: public:
static void init(double sample_rate); static void init(FRAC_NUM sample_rate);
void reset(const uint8_t params[6]); void reset(const uint8_t params[6]);
// result is 0..1 in Q24 // result is 0..1 in Q24

@ -19,7 +19,7 @@
int PitchEnv::unit_; 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; unit_ = _N_ * (1 << 24) / (21.3 * sample_rate) + 0.5;
} }

@ -21,7 +21,7 @@
class PitchEnv { class PitchEnv {
public: 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 // The rates and levels arrays are calibrated to match the Dx7 parameters
// (ie, value 0..99). // (ie, value 0..99).

@ -29,7 +29,7 @@ int32_t sintab[SIN_N_SAMPLES + 1];
#endif #endif
void Sin::init() { 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 c = (int32_t)floor(cos(dphase) * (1 << 30) + 0.5);
int32_t s = (int32_t)floor(sin(dphase) * (1 << 30) + 0.5); int32_t s = (int32_t)floor(sin(dphase) * (1 << 30) + 0.5);
int32_t u = 1 << 30; int32_t u = 1 << 30;

@ -62,4 +62,6 @@ inline static T max(const T& a, const T& b) {
#define QER(n,b) ( ((float)n)/(1<<b) ) #define QER(n,b) ( ((float)n)/(1<<b) )
#define FRAC_NUM float
#endif // __SYNTH_H #endif // __SYNTH_H

Loading…
Cancel
Save