diff --git a/MicroDexed.ino b/MicroDexed.ino index 5f8f453..7613736 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -37,8 +37,9 @@ #include "dexed_sysex.h" #include "effect_modulated_delay.h" #include "PluginFx.h" +#include "SoftenValue.hpp" -AudioPlayQueue dexed1; +AudioPlayQueue queue1; AudioAnalyzePeak peak1; AudioEffectDelay delay1; #ifdef USE_REVERB @@ -59,15 +60,15 @@ AudioAmplifier volume_l; #ifdef MIDI_DEVICE_USB AudioOutputUSB usb1; #endif -AudioConnection patchCord0(dexed1, peak1); -AudioConnection patchCord1(dexed1, 0, chorus_mixer, 0); -AudioConnection patchCord3(dexed1, 0, delay_mixer, 0); -AudioConnection patchCord4(dexed1, 0, delay_fb_mixer, 0); +AudioConnection patchCord0(queue1, peak1); +AudioConnection patchCord1(queue1, 0, chorus_mixer, 0); +AudioConnection patchCord3(queue1, 0, delay_mixer, 0); +AudioConnection patchCord4(queue1, 0, delay_fb_mixer, 0); #ifdef USE_REVERB -AudioConnection patchCord5(dexed1, 0, reverb_mixer_r, 0); -AudioConnection patchCord6(dexed1, 0, reverb_mixer_l, 0); +AudioConnection patchCord5(queue1, 0, reverb_mixer_r, 0); +AudioConnection patchCord6(queue1, 0, reverb_mixer_l, 0); #endif -AudioConnection patchCord7(dexed1, 0, modchorus, 0); +AudioConnection patchCord7(queue1, 0, modchorus, 0); AudioConnection patchCord8(modulator, 0, modchorus, 1); #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT AudioConnection patchCord9(modchorus, modchorus_filter); @@ -112,7 +113,8 @@ AudioConnection patchCord29(volume_r, 0, pt8211_1, 0); AudioConnection patchCord30(volume_l, 0, pt8211_1, 1); #endif -Dexed* dexed = new Dexed(SAMPLE_RATE); +Dexed* MicroDexed[NUM_DEXED]; + bool sd_card_available = false; uint32_t xrun = 0; uint32_t overload = 0; @@ -128,6 +130,9 @@ uint8_t midi_timing_counter = 0; // 24 per qarter elapsedMillis midi_timing_timestep; uint16_t midi_timing_quarter = 0; elapsedMillis long_button_pressed; +//SoftenValue effect_filter_volume[NUM_DEXED](SOFTEN_VALUE_CHANGE_STEPS); +//SoftenValue soften_filter_res[NUM_DEXED](SOFTEN_VALUE_CHANGE_STEPS); +//SoftenValue soften_filter_cut[NUM_DEXED](SOFTEN_VALUE_CHANGE_STEPS); uint8_t effect_filter_cutoff = 0; uint8_t effect_filter_resonance = 0; uint8_t effect_delay_time = 0; @@ -193,6 +198,13 @@ void setup() Serial.println(F("NO LCD DISPLAY ENABLED!")); #endif + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + Serial.print(F("Creating MicroDexed engine ")); + Serial.println(i, DEC); + MicroDexed[i] = new Dexed(SAMPLE_RATE); + } + delay(220); Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed")); @@ -334,9 +346,12 @@ void setup() reverb_mixer_r.gain(1, 0.0); reverb_mixer_l.gain(1, 0.0); - dexed->fx.Gain = 1.0; - dexed->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS; - dexed->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS; + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + MicroDexed[i]->fx.Gain = 1.0; + MicroDexed[i]->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS; + MicroDexed[i]->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS; + } // set initial volume and pan (read from EEPROM) set_volume(configuration.vol, configuration.pan); @@ -379,14 +394,17 @@ void loop() while (42 == 42) { // Main sound calculation - if (dexed1.available() && fill_audio_buffer > audio_block_time_us - 10) + if (queue1.available() && fill_audio_buffer > audio_block_time_us - 10) { fill_audio_buffer = 0; - audio_buffer = dexed1.getBuffer(); + audio_buffer = queue1.getBuffer(); elapsedMicros t1; - dexed->getSamples(AUDIO_BLOCK_SAMPLES, audio_buffer); + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + MicroDexed[i]->getSamples(AUDIO_BLOCK_SAMPLES, audio_buffer); + } if (t1 > audio_block_time_us) // everything greater 2.9ms is a buffer underrun! xrun++; if (t1 > render_time_max) @@ -400,7 +418,7 @@ void loop() for (uint8_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) audio_buffer[i] *= configuration.vol; #endif - dexed1.playBuffer(); + queue1.playBuffer(); } // EEPROM update handling @@ -430,7 +448,10 @@ void loop() control_rate = 0; // Shutdown unused voices - active_voices = dexed->getNumNotesPlaying(); + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + active_voices = MicroDexed[i]->getNumNotesPlaying(); + } // check for value changes if (soften_volume.steps > 0) @@ -451,29 +472,36 @@ void loop() { // soften filter resonance value soften_filter_res.steps--; - dexed->fx.Reso = dexed->fx.Reso + soften_filter_res.diff; + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + MicroDexed[i]->fx.Reso = MicroDexed[i]->fx.Reso + soften_filter_res.diff; + #ifdef DEBUG - Serial.print(F("Filter-Resonance: ")); - Serial.print(dexed->fx.Reso, 5); - Serial.print(F(" Filter-Resonance step: ")); - Serial.print(soften_filter_res.steps); - Serial.print(F(" Filter-Resonance diff: ")); - Serial.println(soften_filter_res.diff, 5); + Serial.print(F("Filter-Resonance: ")); + Serial.print(MicroDexed[i]->fx.Reso, 5); + Serial.print(F(" Filter-Resonance step: ")); + Serial.print(soften_filter_res.steps); + Serial.print(F(" Filter-Resonance diff: ")); + Serial.println(soften_filter_res.diff, 5); #endif + } } if (soften_filter_cut.steps > 0) { // soften filter cutoff value soften_filter_cut.steps--; - dexed->fx.Cutoff = dexed->fx.Cutoff + soften_filter_cut.diff; + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + MicroDexed[i]->fx.Cutoff = MicroDexed[i]->fx.Cutoff + soften_filter_cut.diff; #ifdef DEBUG - Serial.print(F("Filter-Cutoff: ")); - Serial.print(dexed->fx.Cutoff, 5); - Serial.print(F(" Filter-Cutoff step: ")); - Serial.print(soften_filter_cut.steps); - Serial.print(F(" Filter-Cutoff diff: ")); - Serial.println(soften_filter_cut.diff, 5); + Serial.print(F("Filter-Cutoff: ")); + Serial.print(MicroDexed[i]->fx.Cutoff, 5); + Serial.print(F(" Filter-Cutoff step: ")); + Serial.print(soften_filter_cut.steps); + Serial.print(F(" Filter-Cutoff diff: ")); + Serial.println(soften_filter_cut.diff, 5); #endif + } } } @@ -494,7 +522,7 @@ void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity) { if (checkMidiChannel(inChannel)) { - dexed->keydown(inNumber, inVelocity); + MicroDexed[0]->keydown(inNumber, inVelocity); } } @@ -502,7 +530,7 @@ void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity) { if (checkMidiChannel(inChannel)) { - dexed->keyup(inNumber); + MicroDexed[0]->keyup(inNumber); } } @@ -525,16 +553,16 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) } break; case 1: - dexed->controllers.modwheel_cc = inValue; - dexed->controllers.refresh(); + MicroDexed[0]->controllers.modwheel_cc = inValue; + MicroDexed[0]->controllers.refresh(); break; case 2: - dexed->controllers.breath_cc = inValue; - dexed->controllers.refresh(); + MicroDexed[0]->controllers.breath_cc = inValue; + MicroDexed[0]->controllers.refresh(); break; case 4: - dexed->controllers.foot_cc = inValue; - dexed->controllers.refresh(); + MicroDexed[0]->controllers.foot_cc = inValue; + MicroDexed[0]->controllers.refresh(); break; case 7: // Volume configuration.vol = float(inValue) / 0x7f; @@ -548,23 +576,23 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) configuration.bank = inValue; break; case 64: - dexed->setSustain(inValue > 63); - if (!dexed->getSustain()) { - for (uint8_t note = 0; note < dexed->getMaxNotes(); note++) { - if (dexed->voices[note].sustained && !dexed->voices[note].keydown) { - dexed->voices[note].dx7_note->keyup(); - dexed->voices[note].sustained = false; + MicroDexed[0]->setSustain(inValue > 63); + if (!MicroDexed[0]->getSustain()) { + for (uint8_t note = 0; note < MicroDexed[0]->getMaxNotes(); note++) { + if (MicroDexed[0]->voices[note].sustained && !MicroDexed[0]->voices[note].keydown) { + MicroDexed[0]->voices[note].dx7_note->keyup(); + MicroDexed[0]->voices[note].sustained = false; } } } break; case 103: // CC 103: filter resonance effect_filter_resonance = map(inValue, 0, 127, 0, ENC_FILTER_RES_STEPS); - dexed->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS; + MicroDexed[0]->fx.Reso = 1.0 - float(effect_filter_resonance) / ENC_FILTER_RES_STEPS; break; case 104: // CC 104: filter cutoff effect_filter_cutoff = map(inValue, 0, 127, 0, ENC_FILTER_CUT_STEPS); - dexed->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS; + MicroDexed[0]->fx.Cutoff = 1.0 - float(effect_filter_cutoff) / ENC_FILTER_CUT_STEPS; break; case 105: // CC 105: delay time effect_delay_time = map(inValue, 0, 127, 0, ENC_DELAY_TIME_STEPS); @@ -579,19 +607,19 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) ////delay_mixer_l.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delay tap1 signal (with added feedback) break; case 120: - dexed->panic(); + MicroDexed[0]->panic(); break; case 121: - dexed->resetControllers(); + MicroDexed[0]->resetControllers(); break; case 123: - dexed->notesOff(); + MicroDexed[0]->notesOff(); break; case 126: - dexed->setMonoMode(true); + MicroDexed[0]->setMonoMode(true); break; case 127: - dexed->setMonoMode(false); + MicroDexed[0]->setMonoMode(false); break; } } @@ -599,13 +627,13 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue) void handleAfterTouch(byte inChannel, byte inPressure) { - dexed->controllers.aftertouch_cc = inPressure; - dexed->controllers.refresh(); + MicroDexed[0]->controllers.aftertouch_cc = inPressure; + MicroDexed[0]->controllers.refresh(); } void handlePitchBend(byte inChannel, int inPitch) { - dexed->controllers.values_[kControllerPitch] = inPitch + 0x2000; // -8192 to +8191 --> 0 to 16383 + MicroDexed[0]->controllers.values_[kControllerPitch] = inPitch + 0x2000; // -8192 to +8191 --> 0 to 16383 } void handleProgramChange(byte inChannel, byte inProgram) @@ -695,26 +723,26 @@ void handleSystemExclusive(byte * sysex, uint len) if (((sysex[3] & 0x7c) >> 2) == 0) { - dexed->notesOff(); - dexed->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter - dexed->doRefreshVoice(); + MicroDexed[0]->notesOff(); + MicroDexed[0]->data[sysex[4] + ((sysex[3] & 0x03) * 128)] = sysex[5]; // set parameter + MicroDexed[0]->doRefreshVoice(); data_index = sysex[4] + ((sysex[3] & 0x03) * 128); } else { - dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set function parameter - dexed->controllers.values_[kControllerPitchRange] = dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; - dexed->controllers.values_[kControllerPitchStep] = dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; - dexed->controllers.wheel.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); - dexed->controllers.wheel.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); - dexed->controllers.foot.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); - dexed->controllers.foot.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); - dexed->controllers.breath.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); - dexed->controllers.breath.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); - dexed->controllers.at.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); - dexed->controllers.at.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); - dexed->controllers.masterTune = (dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); - dexed->controllers.refresh(); + MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set function parameter + MicroDexed[0]->controllers.values_[kControllerPitchRange] = MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; + MicroDexed[0]->controllers.values_[kControllerPitchStep] = MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; + MicroDexed[0]->controllers.wheel.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); + MicroDexed[0]->controllers.wheel.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); + MicroDexed[0]->controllers.foot.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); + MicroDexed[0]->controllers.foot.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); + MicroDexed[0]->controllers.breath.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); + MicroDexed[0]->controllers.breath.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); + MicroDexed[0]->controllers.at.setRange(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); + MicroDexed[0]->controllers.at.setTarget(MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); + MicroDexed[0]->controllers.masterTune = (MicroDexed[0]->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); + MicroDexed[0]->controllers.refresh(); data_index = DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]; } #ifdef DEBUG @@ -783,8 +811,8 @@ void handleSystemExclusive(byte * sysex, uint len) } // load sysex-data into voice memory - dexed->loadVoiceParameters(&sysex[6]); - //dexed->initGlobalParameters(); + MicroDexed[0]->loadVoiceParameters(&sysex[6]); + //MicroDexed[0]->initGlobalParameters(); // manipulate UI names and numbers strncpy(voice_name, (char *)&sysex[151], sizeof(voice_name) - 1); @@ -862,9 +890,9 @@ void handleSystemReset(void) #ifdef DEBUG Serial.println(F("MIDI SYSEX RESET")); #endif - dexed->notesOff(); - dexed->panic(); - dexed->resetControllers(); + MicroDexed[0]->notesOff(); + MicroDexed[0]->panic(); + MicroDexed[0]->resetControllers(); } /****************************************************************************** @@ -901,7 +929,7 @@ void set_volume(float v, float p) configuration.vol = v; configuration.pan = p; - dexed->fx.Gain = v; + MicroDexed[0]->fx.Gain = v; uint16_t tmp = v * 1023.0 + 0.5; float tmp2 = configuration.pan; @@ -1061,81 +1089,81 @@ void show_patch(void) Serial.print(6 - i, DEC); Serial.println(F(": ")); Serial.println(F("R1 | R2 | R3 | R4 | L1 | L2 | L3 | L4 LEV_SCL_BRK_PT | SCL_LEFT_DEPTH | SCL_RGHT_DEPTH")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_R1], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R1], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_R2], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R2], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_R3], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R3], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_R4], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_R4], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_L1], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L1], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_L2], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L2], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_L3], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L3], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_EG_L4], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_EG_L4], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_LEV_SCL_BRK_PT], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_LEV_SCL_BRK_PT], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_SCL_LEFT_DEPTH], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_LEFT_DEPTH], DEC); Serial.print(F(" ")); - Serial.println(dexed->data[(i * 21) + DEXED_OP_SCL_RGHT_DEPTH], DEC); + Serial.println(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_RGHT_DEPTH], DEC); Serial.println(F("SCL_L_CURVE | SCL_R_CURVE | RT_SCALE | AMS | KVS | OUT_LEV | OP_MOD | FRQ_C | FRQ_F | DETUNE")); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_SCL_LEFT_CURVE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_LEFT_CURVE], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_SCL_RGHT_CURVE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_SCL_RGHT_CURVE], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_OSC_RATE_SCALE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_RATE_SCALE], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_AMP_MOD_SENS], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_AMP_MOD_SENS], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_KEY_VEL_SENS], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_KEY_VEL_SENS], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_OUTPUT_LEV], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OUTPUT_LEV], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_OSC_MODE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_MODE], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_FREQ_COARSE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_FREQ_COARSE], DEC); Serial.print(F(" ")); - Serial.print(dexed->data[(i * 21) + DEXED_OP_FREQ_FINE], DEC); + Serial.print(MicroDexed[0]->data[(i * 21) + DEXED_OP_FREQ_FINE], DEC); Serial.print(F(" ")); - Serial.println(dexed->data[(i * 21) + DEXED_OP_OSC_DETUNE], DEC); + Serial.println(MicroDexed[0]->data[(i * 21) + DEXED_OP_OSC_DETUNE], DEC); } Serial.println(F("PR1 | PR2 | PR3 | PR4 | PL1 | PL2 | PL3 | PL4")); Serial.print(F(" ")); for (i = 0; i < 8; i++) { - Serial.print(dexed->data[DEXED_VOICE_OFFSET + i], DEC); + Serial.print(MicroDexed[0]->data[DEXED_VOICE_OFFSET + i], DEC); Serial.print(F(" ")); } Serial.println(); Serial.print(F("ALG: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_ALGORITHM], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_ALGORITHM], DEC); Serial.print(F("FB: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_FEEDBACK], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_FEEDBACK], DEC); Serial.print(F("OKS: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC], DEC); Serial.print(F("LFO SPD: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SPEED], DEC); Serial.print(F("LFO_DLY: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_DELAY], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_DELAY], DEC); Serial.print(F("LFO PMD: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_DEP], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_DEP], DEC); Serial.print(F("LFO_AMD: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_AMP_MOD_DEP], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_AMP_MOD_DEP], DEC); Serial.print(F("LFO_SYNC: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_SYNC], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_SYNC], DEC); Serial.print(F("LFO_WAVEFRM: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_WAVE], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_WAVE], DEC); Serial.print(F("LFO_PMS: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS], DEC); Serial.print(F("TRNSPSE: ")); - Serial.println(dexed->data[DEXED_VOICE_OFFSET + DEXED_TRANSPOSE], DEC); + Serial.println(MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_TRANSPOSE], DEC); Serial.print(F("NAME: ")); - strncpy(voicename, (char *)&dexed->data[DEXED_VOICE_OFFSET + DEXED_NAME], sizeof(voicename) - 1); + strncpy(voicename, (char *)&MicroDexed[0]->data[DEXED_VOICE_OFFSET + DEXED_NAME], sizeof(voicename) - 1); Serial.print(F("[")); Serial.print(voicename); Serial.println(F("]")); @@ -1143,7 +1171,7 @@ void show_patch(void) { Serial.print(i, DEC); Serial.print(F(": ")); - Serial.println(dexed->data[i]); + Serial.println(MicroDexed[0]->data[i]); } Serial.println(); diff --git a/SoftenValue.hpp b/SoftenValue.hpp new file mode 100644 index 0000000..7b52230 --- /dev/null +++ b/SoftenValue.hpp @@ -0,0 +1,106 @@ +/* + MicroDexed + + MicroDexed is a port of the Dexed sound engine + (https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield. + Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android + + (c)2018 H. Wirtz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef SOFTEN_VALUE_H_INCLUDED + +template +class SoftenValue +{ + public: + SoftenValue(uint16_t steps = 10); + SoftenValue(T from, T to, uint16_t steps = 10) + { + _from = from; + _to = to; + _steps = steps; + _diff = (from - to) / _steps; + + _calculate(); + } + + void update_to(T to) + { + _to = to; + _calculate(); + } + + void update_steps(uint16_t steps) + { + _steps = steps; + _calculate(); + } + + void tick(void) + { + if (_steps > 0) + { + _from -= _diff; + _steps--; + } + } + + bool running(void) + { + if (_steps > 0) + return (true); + else + return (false); + } + + uint16_t steps(void) + { + return (_steps); + } + + T value(void) + { + if (_steps == 0) + return (_to); + + if (std::is_same::value) + return (_from); + else + return (round(_from)); + } + + protected: + float _from; + float _to; + uint16_t _steps; + float _diff; + + void _calculate(void) + { + if (_from == _to || _steps <= 0) + { + _steps = 0; + _diff = 0.0; + } + else + _diff = (_from - _to) / _steps; + } +}; + +#endif diff --git a/config.h b/config.h index 7affa45..bd26179 100644 --- a/config.h +++ b/config.h @@ -177,6 +177,8 @@ //************************************************************************************************* //* DO NO CHANGE ANYTHING BEYOND IF YOU DON'T KNOW WHAT YOU ARE DOING !!! //************************************************************************************************* +#define NUM_DEXED 1 + // MIDI #ifdef MIDI_DEVICE_USB #define USBCON 1 diff --git a/dexed.cpp b/dexed.cpp index 1305326..b12eb77 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -492,7 +492,7 @@ bool Dexed::loadPackedVoiceParameters(uint8_t* new_data) doRefreshVoice(); //activate(); - strncpy(voice_name, (char *)&new_data[145], sizeof(voice_name) - 1); + strncpy(voice_name, (char *)&new_data[118], sizeof(voice_name) - 1); voice_name[10] = '\0'; #ifdef DEBUG Serial.print(F("Voice [")); diff --git a/dexed_sysex.cpp b/dexed_sysex.cpp index e277ee9..126af77 100644 --- a/dexed_sysex.cpp +++ b/dexed_sysex.cpp @@ -31,6 +31,8 @@ #include "dexed_sysex.h" #include "config.h" +extern Dexed* MicroDexed[NUM_DEXED]; + void create_sysex_filename(uint8_t b, char* sysex_file_name) { // init and set name for actual bank @@ -255,7 +257,7 @@ bool load_sysex(uint8_t b, uint8_t v) Serial.print(voice_names[v]); Serial.println(F("]")); #endif - return (dexed->loadPackedVoiceParameters(data)); + return (MicroDexed[0]->loadPackedVoiceParameters(data)); } #ifdef DEBUG else