pull/4/head
Holger Wirtz 7 years ago
parent 25862c59b1
commit d18b6bf1aa
  1. 1
      EngineMkI.cpp
  2. 1
      EngineMkI.h
  3. 58
      MicroDexed.ino
  4. 7
      controllers.h
  5. 688
      dexed.cpp
  6. 7
      dexed.h
  7. 1
      dx7note.h
  8. 1
      fm_core.h

@ -21,7 +21,6 @@
* *
*/ */
#include <Arduino.h>
#include "EngineMkI.h" #include "EngineMkI.h"
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <cmath> #include <cmath>

@ -18,6 +18,7 @@
#ifndef ENGINEMKI_H_INCLUDED #ifndef ENGINEMKI_H_INCLUDED
#define ENGINEMKI_H_INCLUDED #define ENGINEMKI_H_INCLUDED
#include <Arduino.h>
#include "synth.h" #include "synth.h"
#include "aligned_buf.h" #include "aligned_buf.h"
#include "fm_op_kernel.h" #include "fm_op_kernel.h"

@ -6,6 +6,7 @@
#define RATE 128 #define RATE 128
#define TEENSY 1 #define TEENSY 1
#define TEST_MIDI 1 #define TEST_MIDI 1
#define TEST_NOTE 32
#ifdef TEENSY #ifdef TEENSY
#include <Audio.h> #include <Audio.h>
@ -42,7 +43,7 @@ void setup()
AudioMemory(8); AudioMemory(8);
sgtl5000_1.enable(); sgtl5000_1.enable();
sgtl5000_1.volume(0.2); sgtl5000_1.volume(0.3);
// Initialize processor and memory measurements // Initialize processor and memory measurements
//AudioProcessorUsageMaxReset(); //AudioProcessorUsageMaxReset();
@ -59,10 +60,10 @@ void setup()
dexed->activate(); dexed->activate();
#ifdef TEST_MIDI #ifdef TEST_MIDI
dexed->ProcessMidiMessage(0x90, 64, 100); dexed->ProcessMidiMessage(0x90, TEST_NOTE, 100);
//dexed->ProcessMidiMessage(0x90, 66, 127);
#endif #endif
Serial.println(dexed->getEngineType(), DEC);
Serial.println("Go"); Serial.println("Go");
} }
@ -70,8 +71,18 @@ void loop()
{ {
int16_t* audio_buffer; // pointer for 128 * int16_t int16_t* audio_buffer; // pointer for 128 * int16_t
#ifdef TEST_MIDI
if (millis() > 3000 && millis() < 3050)
dexed->ProcessMidiMessage(0x80, TEST_NOTE, 0);
#endif
#ifdef TEENSY #ifdef TEENSY
audio_buffer = queue1.getBuffer(); audio_buffer = queue1.getBuffer();
if (audio_buffer == NULL)
{
Serial.println("audio_buffer allocation problems!");
return;
}
#endif #endif
// process midi->audio // process midi->audio
@ -79,40 +90,29 @@ void loop()
{ {
dexed->ProcessMidiMessage(MIDI.getType(), MIDI.getData1(), MIDI.getData2()); dexed->ProcessMidiMessage(MIDI.getType(), MIDI.getData1(), MIDI.getData2());
} }
uint8_t i = 0;
/* Serial.println("Before:"); dexed->GetSamples(RATE, audio_buffer);
/* uint8_t i = 0;
for (i = 0; i < 128; i++) for (i = 0; i < 128; i++)
{ {
if ((i % 16) == 0)
Serial.println();
if (i < 10)
Serial.print(" ");
if (i > 9 && i < 100)
Serial.print(" ");
Serial.print("[");
Serial.print(i, DEC);
Serial.print("]:");
Serial.print(audio_buffer[i]); Serial.print(audio_buffer[i]);
Serial.print(","); Serial.print(" ");
} }
Serial.println();*/ Serial.println();*/
dexed->GetSamples(RATE, audio_buffer);
for (i = 0; i < 128; i++)
{
if ((i % 16) == 0)
Serial.println();
if (i < 10)
Serial.print(" ");
if (i > 9 && i < 100)
Serial.print(" ");
Serial.print("[");
Serial.print(i, DEC);
Serial.print("]:");
Serial.print(audio_buffer[i]);
Serial.print(" ");
}
Serial.println();
#ifdef TEENSY #ifdef TEENSY
// play the current buffer
while (!queue1.available())
Serial.println("Block");
queue1.playBuffer(); queue1.playBuffer();
#endif #endif
delay(500);
} }

@ -17,10 +17,10 @@
#ifndef __CONTROLLERS_H #ifndef __CONTROLLERS_H
#define __CONTROLLERS_H #define __CONTROLLERS_H
#include <Arduino.h>
#include "synth.h" #include "synth.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "trace.h"
#ifdef _WIN32 #ifdef _WIN32
#define snprintf _snprintf #define snprintf _snprintf
@ -48,17 +48,14 @@ struct FmMod {
void setRange(uint8_t r) { void setRange(uint8_t r) {
range = r < 0 && r > 127 ? 0 : r; range = r < 0 && r > 127 ? 0 : r;
TRACE("range=%d",range);
} }
void setTarget(uint8_t assign) { void setTarget(uint8_t assign) {
TRACE("Target: %d", assign);
assign=assign < 0 && assign > 7 ? 0 : assign; assign=assign < 0 && assign > 7 ? 0 : assign;
pitch=assign&1; // AMP pitch=assign&1; // AMP
amp=assign&2; // PITCH amp=assign&2; // PITCH
eg=assign&4; // EG eg=assign&4; // EG
TRACE("pitch[%d] amp[%d] eg[%d]", pitch,amp,eg);
} }
}; };
@ -66,8 +63,6 @@ class Controllers {
void applyMod(int cc, FmMod &mod) { void applyMod(int cc, FmMod &mod) {
float range = 0.01 * mod.range; float range = 0.01 * mod.range;
uint8_t total = (float)cc * range; uint8_t total = (float)cc * range;
TRACE("amp[%d]|pitch[%d]|eg[%d]",mod.amp,mod.pitch,mod.eg);
TRACE("range=%f mod.range=%d total=%d cc=%d",range,mod.range,total,cc);
if(mod.amp) if(mod.amp)
amp_mod = max(amp_mod, total); amp_mod = max(amp_mod, total);

@ -18,6 +18,7 @@
*/ */
#include "synth.h"
#include "dexed.h" #include "dexed.h"
#include "EngineMkI.h" #include "EngineMkI.h"
#include "EngineOpl.h" #include "EngineOpl.h"
@ -26,12 +27,11 @@
#include "sin.h" #include "sin.h"
#include "freqlut.h" #include "freqlut.h"
#include "controllers.h" #include "controllers.h"
//#include "PluginFx.h" #include "trace.h"
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
#include <math.h>
Dexed::Dexed(uint16_t num_samples) Dexed::Dexed(uint8_t rate)
{ {
uint8_t i; uint8_t i;
@ -39,18 +39,31 @@ Dexed::Dexed(uint16_t num_samples)
Tanh::init(); Tanh::init();
Sin::init(); Sin::init();
_rate = num_samples; Freqlut::init(rate);
Lfo::init(rate);
Freqlut::init(_rate); PitchEnv::init(rate);
Lfo::init(_rate); Env::init_sr(rate);
PitchEnv::init(_rate);
Env::init_sr(_rate);
//fx.init(_rate);
engineMkI = new EngineMkI; engineMkI = new EngineMkI;
engineOpl = new EngineOpl; engineOpl = new EngineOpl;
engineMsfa = new FmCore; engineMsfa = new FmCore;
/*
if(!(engineMkI=new (std::nothrow) EngineMkI))
TRACE("Cannot not create engine EngineMkI");
if(!(engineOpl=new (std::nothrow) EngineOpl))
{
delete(engineMkI);
TRACE("Cannot not create engine EngineOpl");
}
if(!(engineMsfa=new (std::nothrow) FmCore))
{
delete(engineMkI);
delete(engineOpl);
TRACE("Cannot create engine FmCore");
}
*/
for (i = 0; i < MAX_ACTIVE_NOTES; i++) { for (i = 0; i < MAX_ACTIVE_NOTES; i++) {
voices[i].dx7_note = new Dx7Note; voices[i].dx7_note = new Dx7Note;
voices[i].keydown = false; voices[i].keydown = false;
@ -58,6 +71,11 @@ Dexed::Dexed(uint16_t num_samples)
voices[i].live = false; voices[i].live = false;
} }
/* for(i=0;i<sizeof(data);++i)
{
data_float[i]=static_cast<float>(data[i]);
}*/
max_notes = 16; max_notes = 16;
currentNote = 0; currentNote = 0;
controllers.values_[kControllerPitch] = 0x2000; controllers.values_[kControllerPitch] = 0x2000;
@ -69,6 +87,11 @@ Dexed::Dexed(uint16_t num_samples)
controllers.aftertouch_cc = 0; controllers.aftertouch_cc = 0;
controllers.masterTune = 0; controllers.masterTune = 0;
controllers.opSwitch = 0x3f; // enable all operators controllers.opSwitch = 0x3f; // enable all operators
//controllers.opSwitch=0x00;
bufsize_ = 256;
outbuf_ = new float[bufsize_];
lfo.reset(data + 137); lfo.reset(data + 137);
@ -76,33 +99,25 @@ Dexed::Dexed(uint16_t num_samples)
sustain = false; sustain = false;
extra_buf_size_ = 0;
memset(&voiceStatus, 0, sizeof(VoiceStatus)); memset(&voiceStatus, 0, sizeof(VoiceStatus));
setEngineType(DEXED_ENGINE_MARKI); setEngineType(DEXED_ENGINE_MODERN);
} }
Dexed::~Dexed() Dexed::~Dexed()
{ {
delete [] outbuf_;
currentNote = -1; currentNote = -1;
for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; ++note) for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; ++note)
{ delete voices[note].dx7_note;
if ( voices[note].dx7_note != NULL )
{
delete voices[note].dx7_note;
voices[note].dx7_note = NULL;
}
voices[note].keydown = false;
voices[note].sustained = false;
voices[note].live = false;
}
if (engineMsfa) delete(engineMsfa);
delete(engineMkI); delete(engineOpl);
if (engineOpl) delete(engineMkI);
delete(engineMkI);
if (engineMkI)
delete(engineMkI);
} }
void Dexed::activate(void) void Dexed::activate(void)
@ -114,12 +129,12 @@ void Dexed::activate(void)
void Dexed::deactivate(void) void Dexed::deactivate(void)
{ {
; // Nothing to do - please reboot ;-) ; // nothing to do...
} }
void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer) void Dexed::GetSamples(uint16_t n_samples, int16_t* buffer)
{ {
uint32_t i; uint16_t i;
if (refreshVoice) { if (refreshVoice) {
for (i = 0; i < max_notes; i++) { for (i = 0; i < max_notes; i++) {
@ -130,42 +145,65 @@ void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer)
refreshVoice = false; refreshVoice = false;
} }
for (i = 0; i < n_samples; i += _N_) { // flush first events
AlignedBuf<int32_t, _N_> audiobuf; for (i = 0; i < n_samples && i < extra_buf_size_; i++) {
float sumbuf[_N_]; buffer[i] = extra_buf_[i];
}
for (uint32_t j = 0; j < _N_; ++j) { // remaining buffer is still to be processed
audiobuf.get()[j] = 0; if (extra_buf_size_ > n_samples) {
sumbuf[j] = 0.0; for (uint16_t j = 0; j < extra_buf_size_ - n_samples; j++) {
extra_buf_[j] = extra_buf_[j + n_samples];
} }
extra_buf_size_ -= n_samples;
}
else
{
for (; i < n_samples; i += _N_) {
AlignedBuf<int32_t, _N_> audiobuf;
int16_t sumbuf[_N_];
for (uint8_t j = 0; j < _N_; ++j) {
audiobuf.get()[j] = 0;
//sumbuf[j] = 0.0;
sumbuf[j] = 0;
}
int32_t lfovalue = lfo.getsample(); int32_t lfovalue = lfo.getsample();
int32_t lfodelay = lfo.getdelay(); int32_t lfodelay = lfo.getdelay();
for (uint8_t note = 0; note < max_notes; ++note) { for (uint8_t note = 0; note < max_notes; ++note) {
if (voices[note].live) {
if (voices[note].live) { voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers);
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); for (uint8_t j = 0; j < _N_; ++j) {
int32_t val = audiobuf.get()[j];
for (uint32_t j = 0; j < _N_; ++j) { //val = val >> 4;
int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9;
/* float f = static_cast<float>(clip_val >> 1) / static_cast<float>(0x8000);
if (f > 1) f = 1;
if (f < -1) f = -1;
sumbuf[j] += f;*/
sumbuf[j] += clip_val;
audiobuf.get()[j] = 0;
}
}
}
int32_t val = audiobuf.get()[j]; uint16_t jmax = n_samples - i;
val = val >> 4; for (uint8_t j = 0; j < _N_; ++j) {
int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; if (j < jmax)
float f = static_cast<float>(clip_val >> 1) / 0x8000; {
if (f > 1) f = 1; //buffer[i + j] = static_cast<int16_t>(sumbuf[j]*0x8000);
if (f < -1) f = -1; buffer[i + j] = sumbuf[j];
sumbuf[j] += f; Serial.println(buffer[i + j], DEC);
audiobuf.get()[j] = 0;
} }
else
extra_buf_[j - jmax] = sumbuf[j];
} }
} }
for (uint32_t j = 0; j < _N_; ++j) { extra_buf_size_ = i - n_samples;
buffer[j + (i * _N_)] = sumbuf[j];
}
} }
// mark unused voice as not live
if (++_k_rate_counter % 32 && !monoMode) if (++_k_rate_counter % 32 && !monoMode)
{ {
uint8_t op_carrier = controllers.core->get_carrier_operators(data[134]); // look for carriers uint8_t op_carrier = controllers.core->get_carrier_operators(data[134]); // look for carriers
@ -188,6 +226,8 @@ void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer)
// this voice is a carrier! // this voice is a carrier!
op_carrier_num++; op_carrier_num++;
//TRACE("Voice[%2d] OP [%d] amp=%ld,amp_step=%d,pitch_step=%d",i,op,voiceStatus.amp[op],voiceStatus.ampStep[op],voiceStatus.pitchStep);
if (voiceStatus.amp[op] <= 1069 && voiceStatus.ampStep[op] == 4) // this voice produces no audio output if (voiceStatus.amp[op] <= 1069 && voiceStatus.ampStep[op] == 4) // this voice produces no audio output
op_amp++; op_amp++;
} }
@ -198,8 +238,10 @@ void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer)
voices[i].live = false; voices[i].live = false;
voices[i].sustained = false; voices[i].sustained = false;
voices[i].keydown = false; voices[i].keydown = false;
TRACE("Shutted down Voice[%2d]", i);
} }
} }
// TRACE("Voice[%2d] live=%d keydown=%d",i,voices[i].live,voices[i].keydown);
} }
} }
} }
@ -208,34 +250,38 @@ bool Dexed::ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2)
{ {
switch (cmd & 0xf0) { switch (cmd & 0xf0) {
case 0x80 : case 0x80 :
// TRACE("MIDI keyup event: %d",buf[1]); //TRACE("MIDI keyup event: %d", data1);
keyup(data1); keyup(data1);
return (false); return (false);
break; break;
case 0x90 : case 0x90 :
//TRACE("MIDI keydown event: %d %d", data1, data2);
keydown(data1, data2); keydown(data1, data2);
return (false); return (false);
break; break;
case 0xb0 : { case 0xb0 : {
switch (data1) { uint8_t ctrl = data1;
uint8_t value = data2;
switch (ctrl) {
case 1: case 1:
// TRACE("MIDI modwheel event: %d %d",ctrl,value); //TRACE("MIDI modwheel event: %d %d", ctrl, value);
controllers.modwheel_cc = data2; controllers.modwheel_cc = value;
controllers.refresh(); controllers.refresh();
break; break;
case 2: case 2:
// TRACE("MIDI breath event: %d %d",ctrl,value); //TRACE("MIDI breath event: %d %d", ctrl, value);
controllers.breath_cc = data2; controllers.breath_cc = value;
controllers.refresh(); controllers.refresh();
break; break;
case 4: case 4:
// TRACE("MIDI footsw event: %d %d",ctrl,value); //TRACE("MIDI footsw event: %d %d", ctrl, value);
controllers.foot_cc = data2; controllers.foot_cc = value;
controllers.refresh(); controllers.refresh();
break; break;
case 64: case 64:
// TRACE("MIDI sustain event: %d %d",ctrl,value); //TRACE("MIDI sustain event: %d %d", ctrl, value);
sustain = data2 > 63; sustain = value > 63;
if (!sustain) { if (!sustain) {
for (uint8_t note = 0; note < max_notes; note++) { for (uint8_t note = 0; note < max_notes; note++) {
if (voices[note].sustained && !voices[note].keydown) { if (voices[note].sustained && !voices[note].keydown) {
@ -246,12 +292,12 @@ bool Dexed::ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2)
} }
break; break;
case 120: case 120:
// TRACE("MIDI all-sound-off: %d %d",ctrl,value); //TRACE("MIDI all-sound-off: %d %d", ctrl, value);
panic(); panic();
return (true); return (true);
break; break;
case 123: case 123:
// TRACE("MIDI all-notes-off: %d %d",ctrl,value); //TRACE("MIDI all-notes-off: %d %d", ctrl, value);
notes_off(); notes_off();
return (true); return (true);
break; break;
@ -265,22 +311,28 @@ bool Dexed::ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2)
// channel aftertouch // channel aftertouch
case 0xd0 : case 0xd0 :
//TRACE("MIDI aftertouch 0xd0 event: %d %d", data1);
controllers.aftertouch_cc = data1; controllers.aftertouch_cc = data1;
controllers.refresh(); controllers.refresh();
break; break;
// pitchbend // pitchbend
case 0xe0 : case 0xe0 :
//TRACE("MIDI pitchbend 0xe0 event: %d %d", data1, data2);
controllers.values_[kControllerPitch] = data1 | (data2 << 7); controllers.values_[kControllerPitch] = data1 | (data2 << 7);
break; break;
default: default:
//TRACE("MIDI event unknown: cmd=%d, val1=%d, val2=%d", cmd, data1, data2);
break; break;
} }
TRACE("Bye");
return (false); return (false);
} }
void Dexed::keydown(uint8_t pitch, uint8_t velo) { void Dexed::keydown(uint8_t pitch, uint8_t velo) {
TRACE("Hi");
TRACE("pitch=%d, velo=%d\n", pitch, velo);
if ( velo == 0 ) { if ( velo == 0 ) {
keyup(pitch); keyup(pitch);
return; return;
@ -331,9 +383,13 @@ void Dexed::keydown(uint8_t pitch, uint8_t velo) {
} }
voices[note].live = true; voices[note].live = true;
TRACE("Bye");
} }
void Dexed::keyup(uint8_t pitch) { void Dexed::keyup(uint8_t pitch) {
TRACE("Hi");
TRACE("pitch=%d\n", pitch);
pitch += data[144] - 24; pitch += data[144] - 24;
uint8_t note; uint8_t note;
@ -346,6 +402,7 @@ void Dexed::keyup(uint8_t pitch) {
// note not found ? // note not found ?
if ( note >= max_notes ) { if ( note >= max_notes ) {
TRACE("note-off not found???");
return; return;
} }
@ -359,7 +416,7 @@ void Dexed::keyup(uint8_t pitch) {
} }
} }
if ( highNote != -1 ) { if ( highNote != -1 && voices[note].live ) {
voices[note].live = false; voices[note].live = false;
voices[target].live = true; voices[target].live = true;
voices[target].dx7_note->transferState(*voices[note].dx7_note); voices[target].dx7_note->transferState(*voices[note].dx7_note);
@ -371,59 +428,81 @@ void Dexed::keyup(uint8_t pitch) {
} else { } else {
voices[note].dx7_note->keyup(); voices[note].dx7_note->keyup();
} }
TRACE("Bye");
} }
/*void Dexed::onParam(uint8_t param_num,float param_val) /*
void Dexed::onParam(uint8_t param_num, float param_val)
{ {
int32_t tune; int32_t tune;
if(param_val!=data_float[param_num]) if (param_val != data_float[param_num])
{ {
TRACE("Parameter %d change from %f to %f", param_num, data_float[param_num], param_val);
#ifdef DEBUG
uint8_t tmp = data[param_num];
#endif
_param_change_counter++; _param_change_counter++;
if(param_num==144 || param_num==134 || param_num==172) if (param_num == 144 || param_num == 134 || param_num == 172)
panic(); panic();
refreshVoice=true; refreshVoice = true;
data[param_num]=static_cast<uint8_t>(param_val); data[param_num] = static_cast<uint8_t>(param_val);
data_float[param_num]=param_val; data_float[param_num] = param_val;
switch(param_num) switch (param_num)
{ {
case 155: case 155:
controllers.values_[kControllerPitchRange]=data[param_num]; controllers.values_[kControllerPitchRange] = data[param_num];
break; break;
case 156: case 156:
controllers.values_[kControllerPitchStep]=data[param_num]; controllers.values_[kControllerPitchStep] = data[param_num];
break; break;
case 157: case 157:
// TRACE("wheel.setRange(%d)",data[param_num]);
controllers.wheel.setRange(data[param_num]); controllers.wheel.setRange(data[param_num]);
controllers.wheel.setTarget(data[param_num + 1]);
controllers.refresh();
break; break;
case 158: case 158:
controllers.wheel.setRange(data[param_num - 1]);
controllers.wheel.setTarget(data[param_num]); controllers.wheel.setTarget(data[param_num]);
controllers.refresh();
break; break;
case 159: case 159:
controllers.foot.setRange(data[param_num]); controllers.foot.setRange(data[param_num]);
controllers.foot.setTarget(data[param_num + 1]);
controllers.refresh();
break; break;
case 160: case 160:
controllers.foot.setRange(data[param_num - 1]);
controllers.foot.setTarget(data[param_num]); controllers.foot.setTarget(data[param_num]);
controllers.refresh();
break; break;
case 161: case 161:
controllers.breath.setRange(data[param_num]); controllers.breath.setRange(data[param_num]);
controllers.breath.setTarget(data[param_num + 1]);
controllers.refresh();
break; break;
case 162: case 162:
controllers.breath.setRange(data[param_num - 1]);
controllers.breath.setTarget(data[param_num]); controllers.breath.setTarget(data[param_num]);
controllers.refresh();
break; break;
case 163: case 163:
controllers.at.setRange(data[param_num]); controllers.at.setRange(data[param_num]);
controllers.at.setTarget(data[param_num + 1]);
controllers.refresh();
break; break;
case 164: case 164:
controllers.at.setRange(data[param_num - 1]);
controllers.at.setTarget(data[param_num]); controllers.at.setTarget(data[param_num]);
controllers.refresh();
break; break;
case 165: case 165:
tune=param_val*0x4000; tune = param_val * 0x4000;
controllers.masterTune=(tune<<11)*(1.0/12); controllers.masterTune = (tune << 11) * (1.0 / 12);
break; break;
case 166: case 166:
case 167: case 167:
@ -431,12 +510,14 @@ void Dexed::keyup(uint8_t pitch) {
case 169: case 169:
case 170: case 170:
case 171: case 171:
controllers.opSwitch=(data[166]<<5)|(data[167]<<4)|(data[168]<<3)|(data[169]<<2)|(data[170]<<1)|data[171]; controllers.opSwitch = (data[166] << 5) | (data[167] << 4) | (data[168] << 3) | (data[169] << 2) | (data[170] << 1) | data[171];
break; break;
case 172: case 172:
max_notes=data[param_num]; max_notes = data[param_num];
break; break;
} }
TRACE("Done: Parameter %d changed from %d to %d", param_num, tmp, data[param_num]);
} }
} }
*/ */
@ -446,17 +527,22 @@ uint8_t Dexed::getEngineType() {
} }
void Dexed::setEngineType(uint8_t tp) { void Dexed::setEngineType(uint8_t tp) {
TRACE("settings engine %d", tp);
if (engineType == tp && controllers.core != NULL) if (engineType == tp && controllers.core != NULL)
return; return;
switch (tp) { switch (tp) {
case DEXED_ENGINE_MARKI: case DEXED_ENGINE_MARKI:
TRACE("DEXED_ENGINE_MARKI:%d", DEXED_ENGINE_MARKI);
controllers.core = engineMkI; controllers.core = engineMkI;
break; break;
case DEXED_ENGINE_OPL: case DEXED_ENGINE_OPL:
TRACE("DEXED_ENGINE_OPL:%d", DEXED_ENGINE_OPL);
controllers.core = engineOpl; controllers.core = engineOpl;
break; break;
default: default:
TRACE("DEXED_ENGINE_MODERN:%d", DEXED_ENGINE_MODERN);
controllers.core = engineMsfa; controllers.core = engineMsfa;
tp = DEXED_ENGINE_MODERN; tp = DEXED_ENGINE_MODERN;
break; break;
@ -499,223 +585,227 @@ void Dexed::notes_off(void) {
} }
} }
/* void Dexed::set_params(void)
void Dexed::set_params(void) {
{ /* //TRACE("Hi");
_param_change_counter=0;
bool polymono=bool(*p(p_polymono)); _param_change_counter=0;
uint8_t engine=uint8_t(*p(p_engine));
float f_gain=*p(p_output);
float f_cutoff=*p(p_cutoff);
float f_reso=*p(p_resonance);
// Dexed-Unisono bool polymono=bool(*p(p_polymono));
if(isMonoMode()!=polymono) uint8_t engine=uint8_t(*p(p_engine));
setMonoMode(polymono); float f_gain=*p(p_output);
float f_cutoff=*p(p_cutoff);
float f_reso=*p(p_resonance);
// Dexed-Engine // Dexed-Unisono
if(controllers.core==NULL || getEngineType()!=engine) if(isMonoMode()!=polymono)
{ setMonoMode(polymono);
setEngineType(engine);
refreshVoice=true;
}
// Dexed-Filter // Dexed-Engine
if(fx.uiCutoff!=f_cutoff) if(controllers.core==NULL || getEngineType()!=engine)
{ {
fx.uiCutoff=f_cutoff; setEngineType(engine);
refreshVoice=true; refreshVoice=true;
} }
if(fx.uiReso!=f_reso)
{
fx.uiReso=f_reso;
refreshVoice=true;
}
if(fx.uiGain!=f_gain)
{
fx.uiGain=f_gain;
refreshVoice=true;
}
// OP6 // Dexed-Filter
onParam(0,*p(p_op6_eg_rate_1)); if(fx.uiCutoff!=f_cutoff)
onParam(1,*p(p_op6_eg_rate_2)); {
onParam(2,*p(p_op6_eg_rate_3)); fx.uiCutoff=f_cutoff;
onParam(3,*p(p_op6_eg_rate_4)); refreshVoice=true;
onParam(4,*p(p_op6_eg_level_1)); }
onParam(5,*p(p_op6_eg_level_2)); if(fx.uiReso!=f_reso)
onParam(6,*p(p_op6_eg_level_3)); {
onParam(7,*p(p_op6_eg_level_4)); fx.uiReso=f_reso;
onParam(8,*p(p_op6_kbd_lev_scl_brk_pt)); refreshVoice=true;
onParam(9,*p(p_op6_kbd_lev_scl_lft_depth)); }
onParam(10,*p(p_op6_kbd_lev_scl_rht_depth)); if(fx.uiGain!=f_gain)
onParam(11,*p(p_op6_kbd_lev_scl_lft_curve)); {
onParam(12,*p(p_op6_kbd_lev_scl_rht_curve)); fx.uiGain=f_gain;
onParam(13,*p(p_op6_kbd_rate_scaling)); refreshVoice=true;
onParam(14,*p(p_op6_amp_mod_sensitivity)); }
onParam(15,*p(p_op6_key_vel_sensitivity));
onParam(16,*p(p_op6_operator_output_level)); // OP6
onParam(17,*p(p_op6_osc_mode)); onParam(0,*p(p_op6_eg_rate_1));
onParam(18,*p(p_op6_osc_freq_coarse)); onParam(1,*p(p_op6_eg_rate_2));
onParam(19,*p(p_op6_osc_freq_fine)); onParam(2,*p(p_op6_eg_rate_3));
onParam(20,*p(p_op6_osc_detune)+7); onParam(3,*p(p_op6_eg_rate_4));
// OP5 onParam(4,*p(p_op6_eg_level_1));
onParam(21,*p(p_op5_eg_rate_1)); onParam(5,*p(p_op6_eg_level_2));
onParam(22,*p(p_op5_eg_rate_2)); onParam(6,*p(p_op6_eg_level_3));
onParam(23,*p(p_op5_eg_rate_3)); onParam(7,*p(p_op6_eg_level_4));
onParam(24,*p(p_op5_eg_rate_4)); onParam(8,*p(p_op6_kbd_lev_scl_brk_pt));
onParam(25,*p(p_op5_eg_level_1)); onParam(9,*p(p_op6_kbd_lev_scl_lft_depth));
onParam(26,*p(p_op5_eg_level_2)); onParam(10,*p(p_op6_kbd_lev_scl_rht_depth));
onParam(27,*p(p_op5_eg_level_3)); onParam(11,*p(p_op6_kbd_lev_scl_lft_curve));
onParam(28,*p(p_op5_eg_level_4)); onParam(12,*p(p_op6_kbd_lev_scl_rht_curve));
onParam(29,*p(p_op5_kbd_lev_scl_brk_pt)); onParam(13,*p(p_op6_kbd_rate_scaling));
onParam(30,*p(p_op5_kbd_lev_scl_lft_depth)); onParam(14,*p(p_op6_amp_mod_sensitivity));
onParam(31,*p(p_op5_kbd_lev_scl_rht_depth)); onParam(15,*p(p_op6_key_vel_sensitivity));
onParam(32,*p(p_op5_kbd_lev_scl_lft_curve)); onParam(16,*p(p_op6_operator_output_level));
onParam(33,*p(p_op5_kbd_lev_scl_rht_curve)); onParam(17,*p(p_op6_osc_mode));
onParam(34,*p(p_op5_kbd_rate_scaling)); onParam(18,*p(p_op6_osc_freq_coarse));
onParam(35,*p(p_op5_amp_mod_sensitivity)); onParam(19,*p(p_op6_osc_freq_fine));
onParam(36,*p(p_op5_key_vel_sensitivity)); onParam(20,*p(p_op6_osc_detune)+7);
onParam(37,*p(p_op5_operator_output_level)); // OP5
onParam(38,*p(p_op5_osc_mode)); onParam(21,*p(p_op5_eg_rate_1));
onParam(39,*p(p_op5_osc_freq_coarse)); onParam(22,*p(p_op5_eg_rate_2));
onParam(40,*p(p_op5_osc_freq_fine)); onParam(23,*p(p_op5_eg_rate_3));
onParam(41,*p(p_op5_osc_detune)+7); onParam(24,*p(p_op5_eg_rate_4));
// OP4 onParam(25,*p(p_op5_eg_level_1));
onParam(42,*p(p_op4_eg_rate_1)); onParam(26,*p(p_op5_eg_level_2));
onParam(43,*p(p_op4_eg_rate_2)); onParam(27,*p(p_op5_eg_level_3));
onParam(44,*p(p_op4_eg_rate_3)); onParam(28,*p(p_op5_eg_level_4));
onParam(45,*p(p_op4_eg_rate_4)); onParam(29,*p(p_op5_kbd_lev_scl_brk_pt));
onParam(46,*p(p_op4_eg_level_1)); onParam(30,*p(p_op5_kbd_lev_scl_lft_depth));
onParam(47,*p(p_op4_eg_level_2)); onParam(31,*p(p_op5_kbd_lev_scl_rht_depth));
onParam(48,*p(p_op4_eg_level_3)); onParam(32,*p(p_op5_kbd_lev_scl_lft_curve));
onParam(49,*p(p_op4_eg_level_4)); onParam(33,*p(p_op5_kbd_lev_scl_rht_curve));
onParam(50,*p(p_op4_kbd_lev_scl_brk_pt)); onParam(34,*p(p_op5_kbd_rate_scaling));
onParam(51,*p(p_op4_kbd_lev_scl_lft_depth)); onParam(35,*p(p_op5_amp_mod_sensitivity));
onParam(52,*p(p_op4_kbd_lev_scl_rht_depth)); onParam(36,*p(p_op5_key_vel_sensitivity));
onParam(53,*p(p_op4_kbd_lev_scl_lft_curve)); onParam(37,*p(p_op5_operator_output_level));
onParam(54,*p(p_op4_kbd_lev_scl_rht_curve)); onParam(38,*p(p_op5_osc_mode));
onParam(55,*p(p_op4_kbd_rate_scaling)); onParam(39,*p(p_op5_osc_freq_coarse));
onParam(56,*p(p_op4_amp_mod_sensitivity)); onParam(40,*p(p_op5_osc_freq_fine));
onParam(57,*p(p_op4_key_vel_sensitivity)); onParam(41,*p(p_op5_osc_detune)+7);
onParam(58,*p(p_op4_operator_output_level)); // OP4
onParam(59,*p(p_op4_osc_mode)); onParam(42,*p(p_op4_eg_rate_1));
onParam(60,*p(p_op4_osc_freq_coarse)); onParam(43,*p(p_op4_eg_rate_2));
onParam(61,*p(p_op4_osc_freq_fine)); onParam(44,*p(p_op4_eg_rate_3));
onParam(62,*p(p_op4_osc_detune)+7); onParam(45,*p(p_op4_eg_rate_4));
// OP3 onParam(46,*p(p_op4_eg_level_1));
onParam(63,*p(p_op3_eg_rate_1)); onParam(47,*p(p_op4_eg_level_2));
onParam(64,*p(p_op3_eg_rate_2)); onParam(48,*p(p_op4_eg_level_3));
onParam(65,*p(p_op3_eg_rate_3)); onParam(49,*p(p_op4_eg_level_4));
onParam(66,*p(p_op3_eg_rate_4)); onParam(50,*p(p_op4_kbd_lev_scl_brk_pt));
onParam(67,*p(p_op3_eg_level_1)); onParam(51,*p(p_op4_kbd_lev_scl_lft_depth));
onParam(68,*p(p_op3_eg_level_2)); onParam(52,*p(p_op4_kbd_lev_scl_rht_depth));
onParam(69,*p(p_op3_eg_level_3)); onParam(53,*p(p_op4_kbd_lev_scl_lft_curve));
onParam(70,*p(p_op3_eg_level_4)); onParam(54,*p(p_op4_kbd_lev_scl_rht_curve));
onParam(71,*p(p_op3_kbd_lev_scl_brk_pt)); onParam(55,*p(p_op4_kbd_rate_scaling));
onParam(72,*p(p_op3_kbd_lev_scl_lft_depth)); onParam(56,*p(p_op4_amp_mod_sensitivity));
onParam(73,*p(p_op3_kbd_lev_scl_rht_depth)); onParam(57,*p(p_op4_key_vel_sensitivity));
onParam(74,*p(p_op3_kbd_lev_scl_lft_curve)); onParam(58,*p(p_op4_operator_output_level));
onParam(75,*p(p_op3_kbd_lev_scl_rht_curve)); onParam(59,*p(p_op4_osc_mode));
onParam(76,*p(p_op3_kbd_rate_scaling)); onParam(60,*p(p_op4_osc_freq_coarse));
onParam(77,*p(p_op3_amp_mod_sensitivity)); onParam(61,*p(p_op4_osc_freq_fine));
onParam(78,*p(p_op3_key_vel_sensitivity)); onParam(62,*p(p_op4_osc_detune)+7);
onParam(79,*p(p_op3_operator_output_level)); // OP3
onParam(80,*p(p_op3_osc_mode)); onParam(63,*p(p_op3_eg_rate_1));
onParam(81,*p(p_op3_osc_freq_coarse)); onParam(64,*p(p_op3_eg_rate_2));
onParam(82,*p(p_op3_osc_freq_fine)); onParam(65,*p(p_op3_eg_rate_3));
onParam(83,*p(p_op3_osc_detune)+7); onParam(66,*p(p_op3_eg_rate_4));
// OP2 onParam(67,*p(p_op3_eg_level_1));
onParam(84,*p(p_op2_eg_rate_1)); onParam(68,*p(p_op3_eg_level_2));
onParam(85,*p(p_op2_eg_rate_2)); onParam(69,*p(p_op3_eg_level_3));
onParam(86,*p(p_op2_eg_rate_3)); onParam(70,*p(p_op3_eg_level_4));
onParam(87,*p(p_op2_eg_rate_4)); onParam(71,*p(p_op3_kbd_lev_scl_brk_pt));
onParam(88,*p(p_op2_eg_level_1)); onParam(72,*p(p_op3_kbd_lev_scl_lft_depth));
onParam(89,*p(p_op2_eg_level_2)); onParam(73,*p(p_op3_kbd_lev_scl_rht_depth));
onParam(90,*p(p_op2_eg_level_3)); onParam(74,*p(p_op3_kbd_lev_scl_lft_curve));
onParam(91,*p(p_op2_eg_level_4)); onParam(75,*p(p_op3_kbd_lev_scl_rht_curve));
onParam(92,*p(p_op2_kbd_lev_scl_brk_pt)); onParam(76,*p(p_op3_kbd_rate_scaling));
onParam(93,*p(p_op2_kbd_lev_scl_lft_depth)); onParam(77,*p(p_op3_amp_mod_sensitivity));
onParam(94,*p(p_op2_kbd_lev_scl_rht_depth)); onParam(78,*p(p_op3_key_vel_sensitivity));
onParam(95,*p(p_op2_kbd_lev_scl_lft_curve)); onParam(79,*p(p_op3_operator_output_level));
onParam(96,*p(p_op2_kbd_lev_scl_rht_curve)); onParam(80,*p(p_op3_osc_mode));
onParam(97,*p(p_op2_kbd_rate_scaling)); onParam(81,*p(p_op3_osc_freq_coarse));
onParam(98,*p(p_op2_amp_mod_sensitivity)); onParam(82,*p(p_op3_osc_freq_fine));
onParam(99,*p(p_op2_key_vel_sensitivity)); onParam(83,*p(p_op3_osc_detune)+7);
onParam(100,*p(p_op2_operator_output_level)); // OP2
onParam(101,*p(p_op2_osc_mode)); onParam(84,*p(p_op2_eg_rate_1));
onParam(102,*p(p_op2_osc_freq_coarse)); onParam(85,*p(p_op2_eg_rate_2));
onParam(103,*p(p_op2_osc_freq_fine)); onParam(86,*p(p_op2_eg_rate_3));
onParam(104,*p(p_op2_osc_detune)+7); onParam(87,*p(p_op2_eg_rate_4));
// OP1 onParam(88,*p(p_op2_eg_level_1));
onParam(105,*p(p_op1_eg_rate_1)); onParam(89,*p(p_op2_eg_level_2));
onParam(106,*p(p_op1_eg_rate_2)); onParam(90,*p(p_op2_eg_level_3));
onParam(107,*p(p_op1_eg_rate_3)); onParam(91,*p(p_op2_eg_level_4));
onParam(108,*p(p_op1_eg_rate_4)); onParam(92,*p(p_op2_kbd_lev_scl_brk_pt));
onParam(109,*p(p_op1_eg_level_1)); onParam(93,*p(p_op2_kbd_lev_scl_lft_depth));
onParam(110,*p(p_op1_eg_level_2)); onParam(94,*p(p_op2_kbd_lev_scl_rht_depth));
onParam(111,*p(p_op1_eg_level_3)); onParam(95,*p(p_op2_kbd_lev_scl_lft_curve));
onParam(112,*p(p_op1_eg_level_4)); onParam(96,*p(p_op2_kbd_lev_scl_rht_curve));
onParam(113,*p(p_op1_kbd_lev_scl_brk_pt)); onParam(97,*p(p_op2_kbd_rate_scaling));
onParam(114,*p(p_op1_kbd_lev_scl_lft_depth)); onParam(98,*p(p_op2_amp_mod_sensitivity));
onParam(115,*p(p_op1_kbd_lev_scl_rht_depth)); onParam(99,*p(p_op2_key_vel_sensitivity));
onParam(116,*p(p_op1_kbd_lev_scl_lft_curve)); onParam(100,*p(p_op2_operator_output_level));
onParam(117,*p(p_op1_kbd_lev_scl_rht_curve)); onParam(101,*p(p_op2_osc_mode));
onParam(118,*p(p_op1_kbd_rate_scaling)); onParam(102,*p(p_op2_osc_freq_coarse));
onParam(119,*p(p_op1_amp_mod_sensitivity)); onParam(103,*p(p_op2_osc_freq_fine));
onParam(120,*p(p_op1_key_vel_sensitivity)); onParam(104,*p(p_op2_osc_detune)+7);
onParam(121,*p(p_op1_operator_output_level)); // OP1
onParam(122,*p(p_op1_osc_mode)); onParam(105,*p(p_op1_eg_rate_1));
onParam(123,*p(p_op1_osc_freq_coarse)); onParam(106,*p(p_op1_eg_rate_2));
onParam(124,*p(p_op1_osc_freq_fine)); onParam(107,*p(p_op1_eg_rate_3));
onParam(125,*p(p_op1_osc_detune)+7); onParam(108,*p(p_op1_eg_rate_4));
// Global for all OPs onParam(109,*p(p_op1_eg_level_1));
onParam(126,*p(p_pitch_eg_rate_1)); onParam(110,*p(p_op1_eg_level_2));
onParam(127,*p(p_pitch_eg_rate_2)); onParam(111,*p(p_op1_eg_level_3));
onParam(128,*p(p_pitch_eg_rate_3)); onParam(112,*p(p_op1_eg_level_4));
onParam(129,*p(p_pitch_eg_rate_4)); onParam(113,*p(p_op1_kbd_lev_scl_brk_pt));
onParam(130,*p(p_pitch_eg_level_1)); onParam(114,*p(p_op1_kbd_lev_scl_lft_depth));
onParam(131,*p(p_pitch_eg_level_2)); onParam(115,*p(p_op1_kbd_lev_scl_rht_depth));
onParam(132,*p(p_pitch_eg_level_3)); onParam(116,*p(p_op1_kbd_lev_scl_lft_curve));
onParam(133,*p(p_pitch_eg_level_4)); onParam(117,*p(p_op1_kbd_lev_scl_rht_curve));
onParam(134,*p(p_algorithm_num)-1); onParam(118,*p(p_op1_kbd_rate_scaling));
onParam(135,*p(p_feedback)); onParam(119,*p(p_op1_amp_mod_sensitivity));
onParam(136,*p(p_oscillator_sync)); onParam(120,*p(p_op1_key_vel_sensitivity));
onParam(137,*p(p_lfo_speed)); onParam(121,*p(p_op1_operator_output_level));
onParam(138,*p(p_lfo_delay)); onParam(122,*p(p_op1_osc_mode));
onParam(139,*p(p_lfo_pitch_mod_depth)); onParam(123,*p(p_op1_osc_freq_coarse));
onParam(140,*p(p_lfo_amp_mod_depth)); onParam(124,*p(p_op1_osc_freq_fine));
onParam(141,*p(p_lfo_sync)); onParam(125,*p(p_op1_osc_detune)+7);
onParam(142,*p(p_lfo_waveform)); // Global for all OPs
onParam(143,*p(p_pitch_mod_sensitivity)); onParam(126,*p(p_pitch_eg_rate_1));
onParam(144,*p(p_transpose)); onParam(127,*p(p_pitch_eg_rate_2));
// 10 bytes (145-154) are the name of the patch onParam(128,*p(p_pitch_eg_rate_3));
// Controllers (added at the end of the data[]) onParam(129,*p(p_pitch_eg_rate_4));
onParam(155,*p(p_pitch_bend_range)); onParam(130,*p(p_pitch_eg_level_1));
onParam(156,*p(p_pitch_bend_step)); onParam(131,*p(p_pitch_eg_level_2));
onParam(157,*p(p_mod_wheel_range)); onParam(132,*p(p_pitch_eg_level_3));
onParam(158,*p(p_mod_wheel_assign)); onParam(133,*p(p_pitch_eg_level_4));
onParam(159,*p(p_foot_ctrl_range)); onParam(134,*p(p_algorithm_num)-1);
onParam(160,*p(p_foot_ctrl_assign)); onParam(135,*p(p_feedback));
onParam(161,*p(p_breath_ctrl_range)); onParam(136,*p(p_oscillator_sync));
onParam(162,*p(p_breath_ctrl_assign)); onParam(137,*p(p_lfo_speed));
onParam(163,*p(p_aftertouch_range)); onParam(138,*p(p_lfo_delay));
onParam(164,*p(p_aftertouch_assign)); onParam(139,*p(p_lfo_pitch_mod_depth));
onParam(165,*p(p_master_tune)); onParam(140,*p(p_lfo_amp_mod_depth));
onParam(166,*p(p_op1_enable)); onParam(141,*p(p_lfo_sync));
onParam(167,*p(p_op2_enable)); onParam(142,*p(p_lfo_waveform));
onParam(168,*p(p_op3_enable)); onParam(143,*p(p_pitch_mod_sensitivity));
onParam(169,*p(p_op4_enable)); onParam(144,*p(p_transpose));
onParam(170,*p(p_op5_enable)); // 10 bytes (145-154) are the name of the patch
onParam(171,*p(p_op6_enable)); // Controllers (added at the end of the data[])
onParam(172,*p(p_number_of_voices)); onParam(155,*p(p_pitch_bend_range));
onParam(156,*p(p_pitch_bend_step));
if(_param_change_counter>PARAM_CHANGE_LEVEL) onParam(157,*p(p_mod_wheel_range));
{ onParam(158,*p(p_mod_wheel_assign));
panic(); onParam(159,*p(p_foot_ctrl_range));
controllers.refresh(); onParam(160,*p(p_foot_ctrl_assign));
} onParam(161,*p(p_breath_ctrl_range));
} onParam(162,*p(p_breath_ctrl_assign));
*/ onParam(163,*p(p_aftertouch_range));
onParam(164,*p(p_aftertouch_assign));
onParam(165,*p(p_master_tune));
onParam(166,*p(p_op1_enable));
onParam(167,*p(p_op2_enable));
onParam(168,*p(p_op3_enable));
onParam(169,*p(p_op4_enable));
onParam(170,*p(p_op5_enable));
onParam(171,*p(p_op6_enable));
onParam(172,*p(p_number_of_voices));
if(_param_change_counter>PARAM_CHANGE_LEVEL)
{
panic();
controllers.refresh();
}
//TRACE("Bye");
*/
;
}

@ -21,6 +21,7 @@
#ifndef DEXED_H_INCLUDED #ifndef DEXED_H_INCLUDED
#define DEXED_H_INCLUDED #define DEXED_H_INCLUDED
#include <Arduino.h>
#include "controllers.h" #include "controllers.h"
#include "dx7note.h" #include "dx7note.h"
#include "lfo.h" #include "lfo.h"
@ -54,7 +55,7 @@ enum DexedEngineResolution {
class Dexed class Dexed
{ {
public: public:
Dexed(uint16_t rate); Dexed(uint8_t rate);
~Dexed(); ~Dexed();
void activate(void); void activate(void);
void deactivate(void); void deactivate(void);
@ -63,7 +64,7 @@ class Dexed
bool isMonoMode(void); bool isMonoMode(void);
void setMonoMode(bool mode); void setMonoMode(bool mode);
void set_params(void); void set_params(void);
void GetSamples(uint32_t n_samples, int16_t* buffer); void GetSamples(uint16_t n_samples, int16_t* buffer);
bool ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2); bool ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2);
Controllers controllers; Controllers controllers;
@ -91,6 +92,8 @@ class Dexed
EngineOpl* engineOpl; EngineOpl* engineOpl;
float* outbuf_; float* outbuf_;
uint32_t bufsize_; uint32_t bufsize_;
float extra_buf_[_N_];
uint32_t extra_buf_size_;
private: private:
uint16_t _rate; uint16_t _rate;

@ -24,6 +24,7 @@
// It will continue to evolve a bit, as note-stealing logic, scaling, // It will continue to evolve a bit, as note-stealing logic, scaling,
// and real-time control of parameters live here. // and real-time control of parameters live here.
#include <Arduino.h>
#include "env.h" #include "env.h"
#include "pitchenv.h" #include "pitchenv.h"
#include "fm_core.h" #include "fm_core.h"

@ -17,6 +17,7 @@
#ifndef __FM_CORE_H #ifndef __FM_CORE_H
#define __FM_CORE_H #define __FM_CORE_H
#include <Arduino.h>
#include "aligned_buf.h" #include "aligned_buf.h"
#include "fm_op_kernel.h" #include "fm_op_kernel.h"
#include "synth.h" #include "synth.h"

Loading…
Cancel
Save