From 13b46f987db4be505aab1143a4736cfcb8e08b8a Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Thu, 3 May 2018 14:34:23 +0200 Subject: [PATCH] First try for Teensy-3.5 with audio shield --- EngineMkI.cpp | 24 ++++++++++----------- EngineOpl.cpp | 14 ++++++------ MicroDexed.ino | 56 +++++++++++++++++++++++++++++++++++++++++++++++- dexed.cpp | 52 +++++++++++++++++++------------------------- dexed.h | 4 ++-- fm_core.h | 2 +- fm_op_kernel.cpp | 32 +++++++++++++-------------- lfo.cpp | 2 +- pitchenv.cpp | 2 +- synth.h | 2 +- 10 files changed, 118 insertions(+), 72 deletions(-) diff --git a/EngineMkI.cpp b/EngineMkI.cpp index 3167947..9b94d43 100644 --- a/EngineMkI.cpp +++ b/EngineMkI.cpp @@ -44,9 +44,9 @@ double round(double n) { return n < 0.0 ? ceil(n - 0.5) : floor(n + 0.5); } - __declspec(align(16)) const int zeros[N] = {0}; + __declspec(align(16)) const int zeros[_N_] = {0}; #else - const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; + const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; #endif static const uint16_t NEGATIVE_BIT = 0x8000; @@ -147,12 +147,12 @@ inline int32_t mkiSin(int32_t phase, uint16_t env) { void EngineMkI::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = mkiSin((phase+input[i]), gain); output[i] = y + adder[i]; @@ -163,12 +163,12 @@ void EngineMkI::compute(int32_t *output, const int32_t *input, void EngineMkI::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = mkiSin(phase , gain); output[i] = y + adder[i]; @@ -179,14 +179,14 @@ void EngineMkI::compute_pure(int32_t *output, int32_t phase0, int32_t freq, void EngineMkI::compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; int32_t y0 = fb_buf[0]; int32_t y = fb_buf[1]; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; @@ -215,10 +215,10 @@ void EngineMkI::compute_fb2(int32_t *output, FmOpParams *parms, int32_t gain01, gain[0] = gain01; gain[1] = parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out; - dgain[0] = (gain02 - gain01 + (N >> 1)) >> LG_N; + dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out)); - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); // op 0 @@ -257,12 +257,12 @@ void EngineMkI::compute_fb3(int32_t *output, FmOpParams *parms, int32_t gain01, gain[1] = parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out; gain[2] = parms[2].gain_out == 0 ? (ENV_MAX-1) : parms[2].gain_out; - dgain[0] = (gain02 - gain01 + (N >> 1)) >> LG_N; + dgain[0] = (gain02 - gain01 + (_N_ >> 1)) >> LG_N; dgain[1] = (parms[1].gain_out - (parms[1].gain_out == 0 ? (ENV_MAX-1) : parms[1].gain_out)); dgain[2] = (parms[2].gain_out - (parms[2].gain_out == 0 ? (ENV_MAX-1) : parms[2].gain_out)); - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); // op 0 diff --git a/EngineOpl.cpp b/EngineOpl.cpp index 073881e..0d2c091 100644 --- a/EngineOpl.cpp +++ b/EngineOpl.cpp @@ -28,7 +28,7 @@ #ifdef _WIN32 __declspec(align(16)) const int zeros[N] = {0}; #else - const int32_t __attribute__ ((aligned(16))) zeros[N] = {0}; + const int32_t __attribute__ ((aligned(16))) zeros[_N_] = {0}; #endif uint16_t SignBit = 0x8000; @@ -117,12 +117,12 @@ inline int16_t oplSin( uint16_t phase, uint16_t env ) { } void EngineOpl::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = oplSin((phase+input[i]) >> 14, gain); output[i] = (y << 14) + adder[i]; @@ -131,12 +131,12 @@ void EngineOpl::compute(int32_t *output, const int32_t *input, int32_t phase0, i } void EngineOpl::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = oplSin(phase >> 14, gain); output[i] = (y << 14) + adder[i]; @@ -147,14 +147,14 @@ void EngineOpl::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int3 void EngineOpl::compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; const int32_t *adder = add ? output : zeros; int32_t y0 = fb_buf[0]; int32_t y = fb_buf[1]; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; diff --git a/MicroDexed.ino b/MicroDexed.ino index c857802..c1575c4 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -4,17 +4,71 @@ #include "dexed.h" #define RATE 128 +#define TEENSY 1 -Dexed* dexed=new Dexed(RATE); +#ifdef TEENSY +#include +#include +#include +#include +#include + +// GUItool: begin automatically generated code +AudioPlayQueue queue1; //xy=811,259 +AudioOutputI2S i2s1; //xy=1185,252 +AudioConnection patchCord2(queue1, 0, i2s1, 0); +AudioConnection patchCord3(queue1, 0, i2s1, 1); +AudioControlSGTL5000 sgtl5000_1; //xy=830,376 +// GUItool: end automatically generated code +#endif + +MIDI_CREATE_DEFAULT_INSTANCE(); + +Dexed* dexed = new Dexed(RATE); void setup() { Serial.begin(115200); Serial.println(F("MicroDexed")); + + MIDI.begin(MIDI_CHANNEL_OMNI); + +#ifdef TEENSY + // Audio connections require memory to work. For more + // detailed information, see the MemoryAndCpuUsage example + AudioMemory(8); + + sgtl5000_1.enable(); + sgtl5000_1.volume(0.5); + + // Initialize processor and memory measurements + //AudioProcessorUsageMaxReset(); + //AudioMemoryUsageMaxReset(); +#endif + } void loop() { + int16_t* audio_buffer; // pointer for 128 * int16_t + +#ifdef TEENSY + audio_buffer = queue1.getBuffer(); +#endif + + //memset(buf, 0, 128); + + // process midi->audio + while(MIDI.read()) + { + dexed->ProcessMidiMessage((byte)MIDI.getType(),(byte)MIDI.getData1(),(byte)MIDI.getData2()); + } + + dexed->GetSamples(audio_buffer); +#ifdef TEENSY + // play the current buffer + queue1.playBuffer(); +#endif } diff --git a/dexed.cpp b/dexed.cpp index a231923..3f0261f 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -114,7 +114,7 @@ void Dexed::activate(void) void Dexed::deactivate(void) { - ; + ; // Nothing to do - please reboot ;-) } /* @@ -337,8 +337,7 @@ void Dexed::set_params(void) } */ -// override the run() method -void Dexed::run (uint8_t* midi_data) +/*void Dexed::run (uint8_t* midi_data) { static int16_t buffer; @@ -348,11 +347,11 @@ void Dexed::run (uint8_t* midi_data) GetSamples(&buffer); //fx.process(&buffer,_rate); -} +}*/ void Dexed::GetSamples(int16_t* buffer) { - uint32_t i; + uint32_t i=0; if(refreshVoice) { for(i=0;i < max_notes;i++) { @@ -364,11 +363,11 @@ void Dexed::GetSamples(int16_t* buffer) } // remaining buffer is still to be processed - for (; i < _rate; i += N) { - AlignedBuf audiobuf; - float sumbuf[N]; + for (; i < _rate; i += _N_) { + AlignedBuf audiobuf; + float sumbuf[_N_]; - for (uint32_t j = 0; j < N; ++j) { + for (uint32_t j = 0; j < _N_; ++j) { audiobuf.get()[j] = 0; sumbuf[j] = 0.0; } @@ -379,7 +378,7 @@ void Dexed::GetSamples(int16_t* buffer) for (uint8_t note = 0; note < max_notes; ++note) { if (voices[note].live) { voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); - for (uint32_t j=0; j < N; ++j) { + for (uint32_t j=0; j < _N_; ++j) { int32_t val = audiobuf.get()[j]; val = val >> 4; int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; @@ -392,7 +391,7 @@ void Dexed::GetSamples(int16_t* buffer) } } - for (uint32_t j = 0; j < N; ++j) + for (uint32_t j = 0; j < _N_; ++j) buffer[i + j] = sumbuf[j]; } @@ -434,43 +433,39 @@ void Dexed::GetSamples(int16_t* buffer) } } -bool Dexed::ProcessMidiMessage(uint8_t *buf) { - uint8_t cmd = buf[0]; - +bool Dexed::ProcessMidiMessage(uint8_t cmd,uint8_t data1,uint8_t data2) +{ switch(cmd & 0xf0) { case 0x80 : // TRACE("MIDI keyup event: %d",buf[1]); - keyup(buf[1]); + keyup(data1); return(false); break; case 0x90 : // TRACE("MIDI keydown event: %d %d",buf[1],buf[2]); - keydown(buf[1], buf[2]); + keydown(data1, data2); return(false); break; case 0xb0 : { - uint8_t ctrl = buf[1]; - uint8_t value = buf[2]; - - switch(ctrl) { + switch(data1) { case 1: // TRACE("MIDI modwheel event: %d %d",ctrl,value); - controllers.modwheel_cc = value; + controllers.modwheel_cc = data2; controllers.refresh(); break; case 2: // TRACE("MIDI breath event: %d %d",ctrl,value); - controllers.breath_cc = value; + controllers.breath_cc = data2; controllers.refresh(); break; case 4: // TRACE("MIDI footsw event: %d %d",ctrl,value); - controllers.foot_cc = value; + controllers.foot_cc = data2; controllers.refresh(); break; case 64: // TRACE("MIDI sustain event: %d %d",ctrl,value); - sustain = value > 63; + sustain = data2 > 63; if (!sustain) { for (uint8_t note = 0; note < max_notes; note++) { if (voices[note].sustained && !voices[note].keydown) { @@ -495,23 +490,20 @@ bool Dexed::ProcessMidiMessage(uint8_t *buf) { } // case 0xc0 : -// setCurrentProgram(buf[1]); +// setCurrentProgram(data1); // break; // channel aftertouch case 0xd0 : - // TRACE("MIDI aftertouch 0xd0 event: %d %d",buf[1]); - controllers.aftertouch_cc = buf[1]; + controllers.aftertouch_cc = data1; controllers.refresh(); break; // pitchbend case 0xe0 : - // TRACE("MIDI pitchbend 0xe0 event: %d %d",buf[1],buf[2]); - controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7); + controllers.values_[kControllerPitch] = data1 | (data2 << 7); break; default: - // TRACE("MIDI event unknown: cmd=%d, val1=%d, val2=%d",buf[0],buf[1],buf[2]); break; } diff --git a/dexed.h b/dexed.h index 6e862c2..000e54e 100644 --- a/dexed.h +++ b/dexed.h @@ -83,12 +83,12 @@ class Dexed void setMonoMode(bool mode); void set_params(void); void GetSamples(int16_t* buffer); + bool ProcessMidiMessage(uint8_t cmd,uint8_t data1,uint8_t data2); Controllers controllers; VoiceStatus voiceStatus; protected: - bool ProcessMidiMessage(uint8_t* buf); //void onParam(uint8_t param_num,float param_val); void keyup(uint8_t pitch); void keydown(uint8_t pitch, uint8_t velo); @@ -110,7 +110,7 @@ class Dexed EngineOpl* engineOpl; float* outbuf_; uint32_t bufsize_; - float extra_buf_[N]; + float extra_buf_[_N_]; uint32_t extra_buf_size_; private: diff --git a/fm_core.h b/fm_core.h index 4062244..ab3e0e5 100644 --- a/fm_core.h +++ b/fm_core.h @@ -51,7 +51,7 @@ public: uint8_t get_carrier_operators(uint8_t algorithm); virtual void render(int32_t *output, FmOpParams *params, int algorithm, int32_t *fb_buf, int32_t feedback_gain); protected: - AlignedBufbuf_[2]; + AlignedBufbuf_[2]; const static FmAlgorithm algorithms[32]; }; diff --git a/fm_op_kernel.cpp b/fm_op_kernel.cpp index 56a4cc0..6b36de2 100644 --- a/fm_op_kernel.cpp +++ b/fm_op_kernel.cpp @@ -47,7 +47,7 @@ static bool hasNeon() { void FmOpKernel::compute(int32_t *output, const int32_t *input, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; if (hasNeon()) { @@ -57,7 +57,7 @@ void FmOpKernel::compute(int32_t *output, const int32_t *input, #endif } else { if (add) { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = Sin::lookup(phase + input[i]); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; @@ -65,7 +65,7 @@ void FmOpKernel::compute(int32_t *output, const int32_t *input, phase += freq; } } else { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = Sin::lookup(phase + input[i]); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; @@ -78,17 +78,17 @@ void FmOpKernel::compute(int32_t *output, const int32_t *input, void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; if (hasNeon()) { #ifdef HAVE_NEON - neon_fm_kernel(zeros, add ? output : zeros, output, N, + neon_fm_kernel(zeros, add ? output : zeros, output, _N_, phase0, freq, gain, dgain); #endif } else { if (add) { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = Sin::lookup(phase); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; @@ -96,7 +96,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, phase += freq; } } else { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t y = Sin::lookup(phase); int32_t y1 = ((int64_t)y * (int64_t)gain) >> 24; @@ -113,13 +113,13 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, int32_t *fb_buf, int fb_shift, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; int32_t y0 = fb_buf[0]; int32_t y = fb_buf[1]; if (add) { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; @@ -129,7 +129,7 @@ void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, phase += freq; } } else { - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; int32_t scaled_fb = (y0 + y) >> (fb_shift + 1); y0 = y; @@ -154,7 +154,7 @@ void FmOpKernel::compute_fb(int32_t *output, int32_t phase0, int32_t freq, // high accuracy: 5.0 mean, 49 worst case void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY @@ -188,7 +188,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // freq < 0.25: 17.9 mean, 78 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY @@ -202,7 +202,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, v = ((int64_t)v * gain) >> 24; int32_t a = Sin::compute(freq >> 1) << 1; #endif - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { output[i] = u; v -= ((int64_t)a * (int64_t)u) >> 24; u += ((int64_t)a * (int64_t)v) >> 24; @@ -216,7 +216,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // 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) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef DOUBLE_ACCURACY @@ -242,7 +242,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, #endif if (aa < 0) aa = (1 << 31) - 1; - for (int i = 0; i < N; i++) { + for (int i = 0; i < _N_; i++) { gain += dgain; output[i] = ((int64_t)u * (int64_t)gain) >> 30; v -= ((int64_t)aa * (int64_t)u) >> 29; @@ -256,7 +256,7 @@ void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, // high accuracy 2.9 mean, 143 worst void FmOpKernel::compute_pure(int32_t *output, int32_t phase0, int32_t freq, int32_t gain1, int32_t gain2, bool add) { - int32_t dgain = (gain2 - gain1 + (N >> 1)) >> LG_N; + int32_t dgain = (gain2 - gain1 + (_N_ >> 1)) >> LG_N; int32_t gain = gain1; int32_t phase = phase0; #ifdef HIGH_ACCURACY diff --git a/lfo.cpp b/lfo.cpp index e3ffddd..046e67c 100644 --- a/lfo.cpp +++ b/lfo.cpp @@ -25,7 +25,7 @@ uint32_t Lfo::unit_; void Lfo::init(double sample_rate) { // 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); } void Lfo::reset(const uint8_t params[6]) { diff --git a/pitchenv.cpp b/pitchenv.cpp index e46ac4b..8b1f208 100644 --- a/pitchenv.cpp +++ b/pitchenv.cpp @@ -20,7 +20,7 @@ int PitchEnv::unit_; void PitchEnv::init(double sample_rate) { - unit_ = N * (1 << 24) / (21.3 * sample_rate) + 0.5; + unit_ = _N_ * (1 << 24) / (21.3 * sample_rate) + 0.5; } const uint8_t pitchenv_rate[] = { diff --git a/synth.h b/synth.h index 4d1c51c..b1166c3 100644 --- a/synth.h +++ b/synth.h @@ -27,7 +27,7 @@ typedef __int16 SInt16; #endif #define LG_N 6 -#define N (1 << LG_N) +#define _N_ (1 << LG_N) #if defined(__APPLE__) #include