diff --git a/EngineMkI.cpp b/EngineMkI.cpp index 9588fa2..4924e33 100644 --- a/EngineMkI.cpp +++ b/EngineMkI.cpp @@ -21,7 +21,6 @@ * */ -#include #include "EngineMkI.h" #define _USE_MATH_DEFINES #include diff --git a/EngineMkI.h b/EngineMkI.h index f790e0f..586c732 100644 --- a/EngineMkI.h +++ b/EngineMkI.h @@ -18,6 +18,7 @@ #ifndef ENGINEMKI_H_INCLUDED #define ENGINEMKI_H_INCLUDED +#include #include "synth.h" #include "aligned_buf.h" #include "fm_op_kernel.h" diff --git a/MicroDexed.ino b/MicroDexed.ino index be78a1f..6b99be9 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -6,6 +6,7 @@ #define RATE 128 #define TEENSY 1 #define TEST_MIDI 1 +#define TEST_NOTE 32 #ifdef TEENSY #include @@ -42,7 +43,7 @@ void setup() AudioMemory(8); sgtl5000_1.enable(); - sgtl5000_1.volume(0.2); + sgtl5000_1.volume(0.3); // Initialize processor and memory measurements //AudioProcessorUsageMaxReset(); @@ -59,10 +60,10 @@ void setup() dexed->activate(); #ifdef TEST_MIDI - dexed->ProcessMidiMessage(0x90, 64, 100); + dexed->ProcessMidiMessage(0x90, TEST_NOTE, 100); + //dexed->ProcessMidiMessage(0x90, 66, 127); #endif - Serial.println(dexed->getEngineType(), DEC); Serial.println("Go"); } @@ -70,8 +71,18 @@ void loop() { 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 audio_buffer = queue1.getBuffer(); + if (audio_buffer == NULL) + { + Serial.println("audio_buffer allocation problems!"); + return; + } #endif // process midi->audio @@ -79,40 +90,29 @@ void loop() { 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++) { + 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.print(" "); } 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 - // play the current buffer - while (!queue1.available()) - Serial.println("Block"); queue1.playBuffer(); #endif - delay(500); } diff --git a/controllers.h b/controllers.h index b8179e2..1f23ab6 100644 --- a/controllers.h +++ b/controllers.h @@ -17,10 +17,10 @@ #ifndef __CONTROLLERS_H #define __CONTROLLERS_H +#include #include "synth.h" #include #include -#include "trace.h" #ifdef _WIN32 #define snprintf _snprintf @@ -48,17 +48,14 @@ struct FmMod { void setRange(uint8_t r) { range = r < 0 && r > 127 ? 0 : r; - TRACE("range=%d",range); } void setTarget(uint8_t assign) { - TRACE("Target: %d", assign); assign=assign < 0 && assign > 7 ? 0 : assign; pitch=assign&1; // AMP amp=assign&2; // PITCH 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) { float range = 0.01 * mod.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) amp_mod = max(amp_mod, total); diff --git a/dexed.cpp b/dexed.cpp index a324d85..7335ebc 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -18,6 +18,7 @@ */ +#include "synth.h" #include "dexed.h" #include "EngineMkI.h" #include "EngineOpl.h" @@ -26,12 +27,11 @@ #include "sin.h" #include "freqlut.h" #include "controllers.h" -//#include "PluginFx.h" +#include "trace.h" #include #include -#include -Dexed::Dexed(uint16_t num_samples) +Dexed::Dexed(uint8_t rate) { uint8_t i; @@ -39,18 +39,31 @@ Dexed::Dexed(uint16_t num_samples) Tanh::init(); Sin::init(); - _rate = num_samples; - - Freqlut::init(_rate); - Lfo::init(_rate); - PitchEnv::init(_rate); - Env::init_sr(_rate); - //fx.init(_rate); + Freqlut::init(rate); + Lfo::init(rate); + PitchEnv::init(rate); + Env::init_sr(rate); engineMkI = new EngineMkI; engineOpl = new EngineOpl; 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++) { voices[i].dx7_note = new Dx7Note; voices[i].keydown = false; @@ -58,6 +71,11 @@ Dexed::Dexed(uint16_t num_samples) voices[i].live = false; } + /* for(i=0;i(data[i]); + }*/ + max_notes = 16; currentNote = 0; controllers.values_[kControllerPitch] = 0x2000; @@ -69,6 +87,11 @@ Dexed::Dexed(uint16_t num_samples) controllers.aftertouch_cc = 0; controllers.masterTune = 0; controllers.opSwitch = 0x3f; // enable all operators + //controllers.opSwitch=0x00; + + bufsize_ = 256; + + outbuf_ = new float[bufsize_]; lfo.reset(data + 137); @@ -76,33 +99,25 @@ Dexed::Dexed(uint16_t num_samples) sustain = false; + extra_buf_size_ = 0; + memset(&voiceStatus, 0, sizeof(VoiceStatus)); - setEngineType(DEXED_ENGINE_MARKI); + setEngineType(DEXED_ENGINE_MODERN); } Dexed::~Dexed() { + delete [] outbuf_; + currentNote = -1; for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; ++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; - } + delete voices[note].dx7_note; - if (engineMsfa) - delete(engineMkI); - if (engineOpl) - delete(engineMkI); - if (engineMkI) - delete(engineMkI); + delete(engineMsfa); + delete(engineOpl); + delete(engineMkI); } void Dexed::activate(void) @@ -114,12 +129,12 @@ void Dexed::activate(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) { for (i = 0; i < max_notes; i++) { @@ -130,42 +145,65 @@ void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer) refreshVoice = false; } - for (i = 0; i < n_samples; i += _N_) { - AlignedBuf audiobuf; - float sumbuf[_N_]; + // flush first events + for (i = 0; i < n_samples && i < extra_buf_size_; i++) { + buffer[i] = extra_buf_[i]; + } - for (uint32_t j = 0; j < _N_; ++j) { - audiobuf.get()[j] = 0; - sumbuf[j] = 0.0; + // remaining buffer is still to be processed + if (extra_buf_size_ > n_samples) { + 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 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 lfodelay = lfo.getdelay(); - - 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) { + int32_t lfovalue = lfo.getsample(); + int32_t lfodelay = lfo.getdelay(); + + for (uint8_t note = 0; note < max_notes; ++note) { + if (voices[note].live) { + voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); + for (uint8_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; + /* float f = static_cast(clip_val >> 1) / static_cast(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]; - val = val >> 4; - int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; - float f = static_cast(clip_val >> 1) / 0x8000; - if (f > 1) f = 1; - if (f < -1) f = -1; - sumbuf[j] += f; - audiobuf.get()[j] = 0; + uint16_t jmax = n_samples - i; + for (uint8_t j = 0; j < _N_; ++j) { + if (j < jmax) + { + //buffer[i + j] = static_cast(sumbuf[j]*0x8000); + buffer[i + j] = sumbuf[j]; + Serial.println(buffer[i + j], DEC); } + else + extra_buf_[j - jmax] = sumbuf[j]; } } - for (uint32_t j = 0; j < _N_; ++j) { - buffer[j + (i * _N_)] = sumbuf[j]; - } + extra_buf_size_ = i - n_samples; } - // mark unused voice as not live if (++_k_rate_counter % 32 && !monoMode) { 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! 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 op_amp++; } @@ -198,8 +238,10 @@ void Dexed::GetSamples(uint32_t n_samples, int16_t* buffer) voices[i].live = false; voices[i].sustained = 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) { case 0x80 : - // TRACE("MIDI keyup event: %d",buf[1]); + //TRACE("MIDI keyup event: %d", data1); keyup(data1); return (false); break; case 0x90 : + //TRACE("MIDI keydown event: %d %d", data1, data2); keydown(data1, data2); return (false); break; case 0xb0 : { - switch (data1) { + uint8_t ctrl = data1; + uint8_t value = data2; + + switch (ctrl) { case 1: - // TRACE("MIDI modwheel event: %d %d",ctrl,value); - controllers.modwheel_cc = data2; + //TRACE("MIDI modwheel event: %d %d", ctrl, value); + controllers.modwheel_cc = value; controllers.refresh(); break; case 2: - // TRACE("MIDI breath event: %d %d",ctrl,value); - controllers.breath_cc = data2; + //TRACE("MIDI breath event: %d %d", ctrl, value); + controllers.breath_cc = value; controllers.refresh(); break; case 4: - // TRACE("MIDI footsw event: %d %d",ctrl,value); - controllers.foot_cc = data2; + //TRACE("MIDI footsw event: %d %d", ctrl, value); + controllers.foot_cc = value; controllers.refresh(); break; case 64: - // TRACE("MIDI sustain event: %d %d",ctrl,value); - sustain = data2 > 63; + //TRACE("MIDI sustain event: %d %d", ctrl, value); + sustain = value > 63; if (!sustain) { for (uint8_t note = 0; note < max_notes; note++) { if (voices[note].sustained && !voices[note].keydown) { @@ -246,12 +292,12 @@ bool Dexed::ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2) } break; case 120: - // TRACE("MIDI all-sound-off: %d %d",ctrl,value); + //TRACE("MIDI all-sound-off: %d %d", ctrl, value); panic(); return (true); break; case 123: - // TRACE("MIDI all-notes-off: %d %d",ctrl,value); + //TRACE("MIDI all-notes-off: %d %d", ctrl, value); notes_off(); return (true); break; @@ -265,22 +311,28 @@ bool Dexed::ProcessMidiMessage(uint8_t cmd, uint8_t data1, uint8_t data2) // channel aftertouch case 0xd0 : + //TRACE("MIDI aftertouch 0xd0 event: %d %d", data1); controllers.aftertouch_cc = data1; controllers.refresh(); break; // pitchbend case 0xe0 : + //TRACE("MIDI pitchbend 0xe0 event: %d %d", data1, data2); controllers.values_[kControllerPitch] = data1 | (data2 << 7); break; default: + //TRACE("MIDI event unknown: cmd=%d, val1=%d, val2=%d", cmd, data1, data2); break; } + TRACE("Bye"); return (false); } void Dexed::keydown(uint8_t pitch, uint8_t velo) { + TRACE("Hi"); + TRACE("pitch=%d, velo=%d\n", pitch, velo); if ( velo == 0 ) { keyup(pitch); return; @@ -331,9 +383,13 @@ void Dexed::keydown(uint8_t pitch, uint8_t velo) { } voices[note].live = true; + TRACE("Bye"); } void Dexed::keyup(uint8_t pitch) { + TRACE("Hi"); + TRACE("pitch=%d\n", pitch); + pitch += data[144] - 24; uint8_t note; @@ -346,6 +402,7 @@ void Dexed::keyup(uint8_t pitch) { // note not found ? if ( note >= max_notes ) { + TRACE("note-off not found???"); 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[target].live = true; voices[target].dx7_note->transferState(*voices[note].dx7_note); @@ -371,59 +428,81 @@ void Dexed::keyup(uint8_t pitch) { } else { 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; - 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++; - if(param_num==144 || param_num==134 || param_num==172) + if (param_num == 144 || param_num == 134 || param_num == 172) panic(); - refreshVoice=true; - data[param_num]=static_cast(param_val); - data_float[param_num]=param_val; + refreshVoice = true; + data[param_num] = static_cast(param_val); + data_float[param_num] = param_val; - switch(param_num) + switch (param_num) { case 155: - controllers.values_[kControllerPitchRange]=data[param_num]; + controllers.values_[kControllerPitchRange] = data[param_num]; break; case 156: - controllers.values_[kControllerPitchStep]=data[param_num]; + controllers.values_[kControllerPitchStep] = data[param_num]; break; case 157: - // TRACE("wheel.setRange(%d)",data[param_num]); controllers.wheel.setRange(data[param_num]); + controllers.wheel.setTarget(data[param_num + 1]); + controllers.refresh(); break; case 158: + controllers.wheel.setRange(data[param_num - 1]); controllers.wheel.setTarget(data[param_num]); + controllers.refresh(); break; case 159: controllers.foot.setRange(data[param_num]); + controllers.foot.setTarget(data[param_num + 1]); + controllers.refresh(); break; case 160: + controllers.foot.setRange(data[param_num - 1]); controllers.foot.setTarget(data[param_num]); + controllers.refresh(); break; case 161: controllers.breath.setRange(data[param_num]); + controllers.breath.setTarget(data[param_num + 1]); + controllers.refresh(); break; case 162: + controllers.breath.setRange(data[param_num - 1]); controllers.breath.setTarget(data[param_num]); + controllers.refresh(); break; case 163: controllers.at.setRange(data[param_num]); + controllers.at.setTarget(data[param_num + 1]); + controllers.refresh(); break; case 164: + controllers.at.setRange(data[param_num - 1]); controllers.at.setTarget(data[param_num]); + controllers.refresh(); break; case 165: - tune=param_val*0x4000; - controllers.masterTune=(tune<<11)*(1.0/12); + tune = param_val * 0x4000; + controllers.masterTune = (tune << 11) * (1.0 / 12); break; case 166: case 167: @@ -431,12 +510,14 @@ void Dexed::keyup(uint8_t pitch) { case 169: case 170: 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; case 172: - max_notes=data[param_num]; - break; + max_notes = data[param_num]; + 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) { + TRACE("settings engine %d", tp); + if (engineType == tp && controllers.core != NULL) return; switch (tp) { case DEXED_ENGINE_MARKI: + TRACE("DEXED_ENGINE_MARKI:%d", DEXED_ENGINE_MARKI); controllers.core = engineMkI; break; case DEXED_ENGINE_OPL: + TRACE("DEXED_ENGINE_OPL:%d", DEXED_ENGINE_OPL); controllers.core = engineOpl; break; default: + TRACE("DEXED_ENGINE_MODERN:%d", DEXED_ENGINE_MODERN); controllers.core = engineMsfa; tp = DEXED_ENGINE_MODERN; break; @@ -499,223 +585,227 @@ void Dexed::notes_off(void) { } } -/* - void Dexed::set_params(void) - { - _param_change_counter=0; +void Dexed::set_params(void) +{ + /* //TRACE("Hi"); - bool polymono=bool(*p(p_polymono)); - 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); + _param_change_counter=0; - // Dexed-Unisono - if(isMonoMode()!=polymono) - setMonoMode(polymono); + bool polymono=bool(*p(p_polymono)); + 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-Engine - if(controllers.core==NULL || getEngineType()!=engine) - { - setEngineType(engine); - refreshVoice=true; - } + // Dexed-Unisono + if(isMonoMode()!=polymono) + setMonoMode(polymono); - // Dexed-Filter - if(fx.uiCutoff!=f_cutoff) - { - fx.uiCutoff=f_cutoff; - refreshVoice=true; - } - if(fx.uiReso!=f_reso) - { - fx.uiReso=f_reso; - refreshVoice=true; - } - if(fx.uiGain!=f_gain) - { - fx.uiGain=f_gain; - refreshVoice=true; - } + // Dexed-Engine + if(controllers.core==NULL || getEngineType()!=engine) + { + setEngineType(engine); + refreshVoice=true; + } - // OP6 - onParam(0,*p(p_op6_eg_rate_1)); - onParam(1,*p(p_op6_eg_rate_2)); - onParam(2,*p(p_op6_eg_rate_3)); - onParam(3,*p(p_op6_eg_rate_4)); - onParam(4,*p(p_op6_eg_level_1)); - onParam(5,*p(p_op6_eg_level_2)); - onParam(6,*p(p_op6_eg_level_3)); - onParam(7,*p(p_op6_eg_level_4)); - onParam(8,*p(p_op6_kbd_lev_scl_brk_pt)); - onParam(9,*p(p_op6_kbd_lev_scl_lft_depth)); - onParam(10,*p(p_op6_kbd_lev_scl_rht_depth)); - onParam(11,*p(p_op6_kbd_lev_scl_lft_curve)); - onParam(12,*p(p_op6_kbd_lev_scl_rht_curve)); - onParam(13,*p(p_op6_kbd_rate_scaling)); - onParam(14,*p(p_op6_amp_mod_sensitivity)); - onParam(15,*p(p_op6_key_vel_sensitivity)); - onParam(16,*p(p_op6_operator_output_level)); - onParam(17,*p(p_op6_osc_mode)); - onParam(18,*p(p_op6_osc_freq_coarse)); - onParam(19,*p(p_op6_osc_freq_fine)); - onParam(20,*p(p_op6_osc_detune)+7); - // OP5 - onParam(21,*p(p_op5_eg_rate_1)); - onParam(22,*p(p_op5_eg_rate_2)); - onParam(23,*p(p_op5_eg_rate_3)); - onParam(24,*p(p_op5_eg_rate_4)); - onParam(25,*p(p_op5_eg_level_1)); - onParam(26,*p(p_op5_eg_level_2)); - onParam(27,*p(p_op5_eg_level_3)); - onParam(28,*p(p_op5_eg_level_4)); - onParam(29,*p(p_op5_kbd_lev_scl_brk_pt)); - onParam(30,*p(p_op5_kbd_lev_scl_lft_depth)); - onParam(31,*p(p_op5_kbd_lev_scl_rht_depth)); - onParam(32,*p(p_op5_kbd_lev_scl_lft_curve)); - onParam(33,*p(p_op5_kbd_lev_scl_rht_curve)); - onParam(34,*p(p_op5_kbd_rate_scaling)); - onParam(35,*p(p_op5_amp_mod_sensitivity)); - onParam(36,*p(p_op5_key_vel_sensitivity)); - onParam(37,*p(p_op5_operator_output_level)); - onParam(38,*p(p_op5_osc_mode)); - onParam(39,*p(p_op5_osc_freq_coarse)); - onParam(40,*p(p_op5_osc_freq_fine)); - onParam(41,*p(p_op5_osc_detune)+7); - // OP4 - onParam(42,*p(p_op4_eg_rate_1)); - onParam(43,*p(p_op4_eg_rate_2)); - onParam(44,*p(p_op4_eg_rate_3)); - onParam(45,*p(p_op4_eg_rate_4)); - onParam(46,*p(p_op4_eg_level_1)); - onParam(47,*p(p_op4_eg_level_2)); - onParam(48,*p(p_op4_eg_level_3)); - onParam(49,*p(p_op4_eg_level_4)); - onParam(50,*p(p_op4_kbd_lev_scl_brk_pt)); - onParam(51,*p(p_op4_kbd_lev_scl_lft_depth)); - onParam(52,*p(p_op4_kbd_lev_scl_rht_depth)); - onParam(53,*p(p_op4_kbd_lev_scl_lft_curve)); - onParam(54,*p(p_op4_kbd_lev_scl_rht_curve)); - onParam(55,*p(p_op4_kbd_rate_scaling)); - onParam(56,*p(p_op4_amp_mod_sensitivity)); - onParam(57,*p(p_op4_key_vel_sensitivity)); - onParam(58,*p(p_op4_operator_output_level)); - onParam(59,*p(p_op4_osc_mode)); - onParam(60,*p(p_op4_osc_freq_coarse)); - onParam(61,*p(p_op4_osc_freq_fine)); - onParam(62,*p(p_op4_osc_detune)+7); - // OP3 - onParam(63,*p(p_op3_eg_rate_1)); - onParam(64,*p(p_op3_eg_rate_2)); - onParam(65,*p(p_op3_eg_rate_3)); - onParam(66,*p(p_op3_eg_rate_4)); - onParam(67,*p(p_op3_eg_level_1)); - onParam(68,*p(p_op3_eg_level_2)); - onParam(69,*p(p_op3_eg_level_3)); - onParam(70,*p(p_op3_eg_level_4)); - onParam(71,*p(p_op3_kbd_lev_scl_brk_pt)); - onParam(72,*p(p_op3_kbd_lev_scl_lft_depth)); - onParam(73,*p(p_op3_kbd_lev_scl_rht_depth)); - onParam(74,*p(p_op3_kbd_lev_scl_lft_curve)); - onParam(75,*p(p_op3_kbd_lev_scl_rht_curve)); - onParam(76,*p(p_op3_kbd_rate_scaling)); - onParam(77,*p(p_op3_amp_mod_sensitivity)); - onParam(78,*p(p_op3_key_vel_sensitivity)); - onParam(79,*p(p_op3_operator_output_level)); - onParam(80,*p(p_op3_osc_mode)); - onParam(81,*p(p_op3_osc_freq_coarse)); - onParam(82,*p(p_op3_osc_freq_fine)); - onParam(83,*p(p_op3_osc_detune)+7); - // OP2 - onParam(84,*p(p_op2_eg_rate_1)); - onParam(85,*p(p_op2_eg_rate_2)); - onParam(86,*p(p_op2_eg_rate_3)); - onParam(87,*p(p_op2_eg_rate_4)); - onParam(88,*p(p_op2_eg_level_1)); - onParam(89,*p(p_op2_eg_level_2)); - onParam(90,*p(p_op2_eg_level_3)); - onParam(91,*p(p_op2_eg_level_4)); - onParam(92,*p(p_op2_kbd_lev_scl_brk_pt)); - onParam(93,*p(p_op2_kbd_lev_scl_lft_depth)); - onParam(94,*p(p_op2_kbd_lev_scl_rht_depth)); - onParam(95,*p(p_op2_kbd_lev_scl_lft_curve)); - onParam(96,*p(p_op2_kbd_lev_scl_rht_curve)); - onParam(97,*p(p_op2_kbd_rate_scaling)); - onParam(98,*p(p_op2_amp_mod_sensitivity)); - onParam(99,*p(p_op2_key_vel_sensitivity)); - onParam(100,*p(p_op2_operator_output_level)); - onParam(101,*p(p_op2_osc_mode)); - onParam(102,*p(p_op2_osc_freq_coarse)); - onParam(103,*p(p_op2_osc_freq_fine)); - onParam(104,*p(p_op2_osc_detune)+7); - // OP1 - onParam(105,*p(p_op1_eg_rate_1)); - onParam(106,*p(p_op1_eg_rate_2)); - onParam(107,*p(p_op1_eg_rate_3)); - onParam(108,*p(p_op1_eg_rate_4)); - onParam(109,*p(p_op1_eg_level_1)); - onParam(110,*p(p_op1_eg_level_2)); - onParam(111,*p(p_op1_eg_level_3)); - onParam(112,*p(p_op1_eg_level_4)); - onParam(113,*p(p_op1_kbd_lev_scl_brk_pt)); - onParam(114,*p(p_op1_kbd_lev_scl_lft_depth)); - onParam(115,*p(p_op1_kbd_lev_scl_rht_depth)); - onParam(116,*p(p_op1_kbd_lev_scl_lft_curve)); - onParam(117,*p(p_op1_kbd_lev_scl_rht_curve)); - onParam(118,*p(p_op1_kbd_rate_scaling)); - onParam(119,*p(p_op1_amp_mod_sensitivity)); - onParam(120,*p(p_op1_key_vel_sensitivity)); - onParam(121,*p(p_op1_operator_output_level)); - onParam(122,*p(p_op1_osc_mode)); - onParam(123,*p(p_op1_osc_freq_coarse)); - onParam(124,*p(p_op1_osc_freq_fine)); - onParam(125,*p(p_op1_osc_detune)+7); - // Global for all OPs - onParam(126,*p(p_pitch_eg_rate_1)); - onParam(127,*p(p_pitch_eg_rate_2)); - onParam(128,*p(p_pitch_eg_rate_3)); - onParam(129,*p(p_pitch_eg_rate_4)); - onParam(130,*p(p_pitch_eg_level_1)); - onParam(131,*p(p_pitch_eg_level_2)); - onParam(132,*p(p_pitch_eg_level_3)); - onParam(133,*p(p_pitch_eg_level_4)); - onParam(134,*p(p_algorithm_num)-1); - onParam(135,*p(p_feedback)); - onParam(136,*p(p_oscillator_sync)); - onParam(137,*p(p_lfo_speed)); - onParam(138,*p(p_lfo_delay)); - onParam(139,*p(p_lfo_pitch_mod_depth)); - onParam(140,*p(p_lfo_amp_mod_depth)); - onParam(141,*p(p_lfo_sync)); - onParam(142,*p(p_lfo_waveform)); - onParam(143,*p(p_pitch_mod_sensitivity)); - onParam(144,*p(p_transpose)); - // 10 bytes (145-154) are the name of the patch - // Controllers (added at the end of the data[]) - onParam(155,*p(p_pitch_bend_range)); - onParam(156,*p(p_pitch_bend_step)); - onParam(157,*p(p_mod_wheel_range)); - onParam(158,*p(p_mod_wheel_assign)); - onParam(159,*p(p_foot_ctrl_range)); - 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(); - } - } -*/ + // Dexed-Filter + if(fx.uiCutoff!=f_cutoff) + { + fx.uiCutoff=f_cutoff; + 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 + onParam(0,*p(p_op6_eg_rate_1)); + onParam(1,*p(p_op6_eg_rate_2)); + onParam(2,*p(p_op6_eg_rate_3)); + onParam(3,*p(p_op6_eg_rate_4)); + onParam(4,*p(p_op6_eg_level_1)); + onParam(5,*p(p_op6_eg_level_2)); + onParam(6,*p(p_op6_eg_level_3)); + onParam(7,*p(p_op6_eg_level_4)); + onParam(8,*p(p_op6_kbd_lev_scl_brk_pt)); + onParam(9,*p(p_op6_kbd_lev_scl_lft_depth)); + onParam(10,*p(p_op6_kbd_lev_scl_rht_depth)); + onParam(11,*p(p_op6_kbd_lev_scl_lft_curve)); + onParam(12,*p(p_op6_kbd_lev_scl_rht_curve)); + onParam(13,*p(p_op6_kbd_rate_scaling)); + onParam(14,*p(p_op6_amp_mod_sensitivity)); + onParam(15,*p(p_op6_key_vel_sensitivity)); + onParam(16,*p(p_op6_operator_output_level)); + onParam(17,*p(p_op6_osc_mode)); + onParam(18,*p(p_op6_osc_freq_coarse)); + onParam(19,*p(p_op6_osc_freq_fine)); + onParam(20,*p(p_op6_osc_detune)+7); + // OP5 + onParam(21,*p(p_op5_eg_rate_1)); + onParam(22,*p(p_op5_eg_rate_2)); + onParam(23,*p(p_op5_eg_rate_3)); + onParam(24,*p(p_op5_eg_rate_4)); + onParam(25,*p(p_op5_eg_level_1)); + onParam(26,*p(p_op5_eg_level_2)); + onParam(27,*p(p_op5_eg_level_3)); + onParam(28,*p(p_op5_eg_level_4)); + onParam(29,*p(p_op5_kbd_lev_scl_brk_pt)); + onParam(30,*p(p_op5_kbd_lev_scl_lft_depth)); + onParam(31,*p(p_op5_kbd_lev_scl_rht_depth)); + onParam(32,*p(p_op5_kbd_lev_scl_lft_curve)); + onParam(33,*p(p_op5_kbd_lev_scl_rht_curve)); + onParam(34,*p(p_op5_kbd_rate_scaling)); + onParam(35,*p(p_op5_amp_mod_sensitivity)); + onParam(36,*p(p_op5_key_vel_sensitivity)); + onParam(37,*p(p_op5_operator_output_level)); + onParam(38,*p(p_op5_osc_mode)); + onParam(39,*p(p_op5_osc_freq_coarse)); + onParam(40,*p(p_op5_osc_freq_fine)); + onParam(41,*p(p_op5_osc_detune)+7); + // OP4 + onParam(42,*p(p_op4_eg_rate_1)); + onParam(43,*p(p_op4_eg_rate_2)); + onParam(44,*p(p_op4_eg_rate_3)); + onParam(45,*p(p_op4_eg_rate_4)); + onParam(46,*p(p_op4_eg_level_1)); + onParam(47,*p(p_op4_eg_level_2)); + onParam(48,*p(p_op4_eg_level_3)); + onParam(49,*p(p_op4_eg_level_4)); + onParam(50,*p(p_op4_kbd_lev_scl_brk_pt)); + onParam(51,*p(p_op4_kbd_lev_scl_lft_depth)); + onParam(52,*p(p_op4_kbd_lev_scl_rht_depth)); + onParam(53,*p(p_op4_kbd_lev_scl_lft_curve)); + onParam(54,*p(p_op4_kbd_lev_scl_rht_curve)); + onParam(55,*p(p_op4_kbd_rate_scaling)); + onParam(56,*p(p_op4_amp_mod_sensitivity)); + onParam(57,*p(p_op4_key_vel_sensitivity)); + onParam(58,*p(p_op4_operator_output_level)); + onParam(59,*p(p_op4_osc_mode)); + onParam(60,*p(p_op4_osc_freq_coarse)); + onParam(61,*p(p_op4_osc_freq_fine)); + onParam(62,*p(p_op4_osc_detune)+7); + // OP3 + onParam(63,*p(p_op3_eg_rate_1)); + onParam(64,*p(p_op3_eg_rate_2)); + onParam(65,*p(p_op3_eg_rate_3)); + onParam(66,*p(p_op3_eg_rate_4)); + onParam(67,*p(p_op3_eg_level_1)); + onParam(68,*p(p_op3_eg_level_2)); + onParam(69,*p(p_op3_eg_level_3)); + onParam(70,*p(p_op3_eg_level_4)); + onParam(71,*p(p_op3_kbd_lev_scl_brk_pt)); + onParam(72,*p(p_op3_kbd_lev_scl_lft_depth)); + onParam(73,*p(p_op3_kbd_lev_scl_rht_depth)); + onParam(74,*p(p_op3_kbd_lev_scl_lft_curve)); + onParam(75,*p(p_op3_kbd_lev_scl_rht_curve)); + onParam(76,*p(p_op3_kbd_rate_scaling)); + onParam(77,*p(p_op3_amp_mod_sensitivity)); + onParam(78,*p(p_op3_key_vel_sensitivity)); + onParam(79,*p(p_op3_operator_output_level)); + onParam(80,*p(p_op3_osc_mode)); + onParam(81,*p(p_op3_osc_freq_coarse)); + onParam(82,*p(p_op3_osc_freq_fine)); + onParam(83,*p(p_op3_osc_detune)+7); + // OP2 + onParam(84,*p(p_op2_eg_rate_1)); + onParam(85,*p(p_op2_eg_rate_2)); + onParam(86,*p(p_op2_eg_rate_3)); + onParam(87,*p(p_op2_eg_rate_4)); + onParam(88,*p(p_op2_eg_level_1)); + onParam(89,*p(p_op2_eg_level_2)); + onParam(90,*p(p_op2_eg_level_3)); + onParam(91,*p(p_op2_eg_level_4)); + onParam(92,*p(p_op2_kbd_lev_scl_brk_pt)); + onParam(93,*p(p_op2_kbd_lev_scl_lft_depth)); + onParam(94,*p(p_op2_kbd_lev_scl_rht_depth)); + onParam(95,*p(p_op2_kbd_lev_scl_lft_curve)); + onParam(96,*p(p_op2_kbd_lev_scl_rht_curve)); + onParam(97,*p(p_op2_kbd_rate_scaling)); + onParam(98,*p(p_op2_amp_mod_sensitivity)); + onParam(99,*p(p_op2_key_vel_sensitivity)); + onParam(100,*p(p_op2_operator_output_level)); + onParam(101,*p(p_op2_osc_mode)); + onParam(102,*p(p_op2_osc_freq_coarse)); + onParam(103,*p(p_op2_osc_freq_fine)); + onParam(104,*p(p_op2_osc_detune)+7); + // OP1 + onParam(105,*p(p_op1_eg_rate_1)); + onParam(106,*p(p_op1_eg_rate_2)); + onParam(107,*p(p_op1_eg_rate_3)); + onParam(108,*p(p_op1_eg_rate_4)); + onParam(109,*p(p_op1_eg_level_1)); + onParam(110,*p(p_op1_eg_level_2)); + onParam(111,*p(p_op1_eg_level_3)); + onParam(112,*p(p_op1_eg_level_4)); + onParam(113,*p(p_op1_kbd_lev_scl_brk_pt)); + onParam(114,*p(p_op1_kbd_lev_scl_lft_depth)); + onParam(115,*p(p_op1_kbd_lev_scl_rht_depth)); + onParam(116,*p(p_op1_kbd_lev_scl_lft_curve)); + onParam(117,*p(p_op1_kbd_lev_scl_rht_curve)); + onParam(118,*p(p_op1_kbd_rate_scaling)); + onParam(119,*p(p_op1_amp_mod_sensitivity)); + onParam(120,*p(p_op1_key_vel_sensitivity)); + onParam(121,*p(p_op1_operator_output_level)); + onParam(122,*p(p_op1_osc_mode)); + onParam(123,*p(p_op1_osc_freq_coarse)); + onParam(124,*p(p_op1_osc_freq_fine)); + onParam(125,*p(p_op1_osc_detune)+7); + // Global for all OPs + onParam(126,*p(p_pitch_eg_rate_1)); + onParam(127,*p(p_pitch_eg_rate_2)); + onParam(128,*p(p_pitch_eg_rate_3)); + onParam(129,*p(p_pitch_eg_rate_4)); + onParam(130,*p(p_pitch_eg_level_1)); + onParam(131,*p(p_pitch_eg_level_2)); + onParam(132,*p(p_pitch_eg_level_3)); + onParam(133,*p(p_pitch_eg_level_4)); + onParam(134,*p(p_algorithm_num)-1); + onParam(135,*p(p_feedback)); + onParam(136,*p(p_oscillator_sync)); + onParam(137,*p(p_lfo_speed)); + onParam(138,*p(p_lfo_delay)); + onParam(139,*p(p_lfo_pitch_mod_depth)); + onParam(140,*p(p_lfo_amp_mod_depth)); + onParam(141,*p(p_lfo_sync)); + onParam(142,*p(p_lfo_waveform)); + onParam(143,*p(p_pitch_mod_sensitivity)); + onParam(144,*p(p_transpose)); + // 10 bytes (145-154) are the name of the patch + // Controllers (added at the end of the data[]) + onParam(155,*p(p_pitch_bend_range)); + onParam(156,*p(p_pitch_bend_step)); + onParam(157,*p(p_mod_wheel_range)); + onParam(158,*p(p_mod_wheel_assign)); + onParam(159,*p(p_foot_ctrl_range)); + 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"); + */ + ; +} diff --git a/dexed.h b/dexed.h index 25bae4d..eda9d51 100644 --- a/dexed.h +++ b/dexed.h @@ -21,6 +21,7 @@ #ifndef DEXED_H_INCLUDED #define DEXED_H_INCLUDED +#include #include "controllers.h" #include "dx7note.h" #include "lfo.h" @@ -54,7 +55,7 @@ enum DexedEngineResolution { class Dexed { public: - Dexed(uint16_t rate); + Dexed(uint8_t rate); ~Dexed(); void activate(void); void deactivate(void); @@ -63,7 +64,7 @@ class Dexed bool isMonoMode(void); void setMonoMode(bool mode); 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); Controllers controllers; @@ -91,6 +92,8 @@ class Dexed EngineOpl* engineOpl; float* outbuf_; uint32_t bufsize_; + float extra_buf_[_N_]; + uint32_t extra_buf_size_; private: uint16_t _rate; diff --git a/dx7note.h b/dx7note.h index da0120e..e221d40 100644 --- a/dx7note.h +++ b/dx7note.h @@ -24,6 +24,7 @@ // It will continue to evolve a bit, as note-stealing logic, scaling, // and real-time control of parameters live here. +#include #include "env.h" #include "pitchenv.h" #include "fm_core.h" diff --git a/fm_core.h b/fm_core.h index 22e64fd..7c0f2cc 100644 --- a/fm_core.h +++ b/fm_core.h @@ -17,6 +17,7 @@ #ifndef __FM_CORE_H #define __FM_CORE_H +#include #include "aligned_buf.h" #include "fm_op_kernel.h" #include "synth.h"