First try for Teensy-3.5 with audio shield

pull/4/head
Holger Wirtz 6 years ago
parent ca3a5af54e
commit 13b46f987d
  1. 24
      EngineMkI.cpp
  2. 14
      EngineOpl.cpp
  3. 56
      MicroDexed.ino
  4. 52
      dexed.cpp
  5. 4
      dexed.h
  6. 2
      fm_core.h
  7. 32
      fm_op_kernel.cpp
  8. 2
      lfo.cpp
  9. 2
      pitchenv.cpp
  10. 2
      synth.h

@ -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

@ -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;

@ -4,17 +4,71 @@
#include "dexed.h"
#define RATE 128
#define TEENSY 1
Dexed* dexed=new Dexed(RATE);
#ifdef TEENSY
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// 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
}

@ -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<int32_t, N> audiobuf;
float sumbuf[N];
for (; i < _rate; i += _N_) {
AlignedBuf<int32_t, _N_> 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;
}

@ -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:

@ -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:
AlignedBuf<int32_t, N>buf_[2];
AlignedBuf<int32_t, _N_>buf_[2];
const static FmAlgorithm algorithms[32];
};

@ -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

@ -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]) {

@ -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[] = {

@ -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 <libkern/OSAtomic.h>

Loading…
Cancel
Save