From 1533e6ba122956d69edcb9447c0d575bfc0f091d Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Thu, 12 Dec 2019 08:46:52 +0100 Subject: [PATCH] Changes for autothrottling max simulatinious note. Changes for dexed setup format. --- MicroDexed.ino | 35 +++++++++---------- config.h | 10 +++--- dexed.cpp | 59 +++++++++++++++----------------- dexed_sysex.cpp | 3 +- doc/sysex-format_dexed-setup.txt | 40 ++++++++++++++++++---- 5 files changed, 86 insertions(+), 61 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index a395c83..255951e 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -177,25 +177,17 @@ AudioConnection * dynamicConnections[NUM_DEXED * 8]; #endif void create_audio_connections(AudioSourceMicroDexed &dexed, AudioEffectMonoStereo &mono2stereo, uint8_t instance_id) { - Serial.print(F("Connecting Dexed ")); - Serial.print(instance_id, DEC); - Serial.println(F(":")); dynamicConnections[nDynamic++] = new AudioConnection(dexed, 0, microdexed_peak_mixer, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(dexed, 0, mono2stereo, 0); - Serial.println(F(" -> Peakmeter")); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, dexed_mixer_r, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, dexed_mixer_l, instance_id); - Serial.println(F(" -> Dexed mixer")); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, chorus_send_mixer_r, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, chorus_send_mixer_l, instance_id); - Serial.println(F(" -> Chorus send")); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, delay_send_mixer_r, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, delay_send_mixer_l, instance_id); - Serial.println(F(" -> Delay send")); #if defined(USE_REVERB) dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, reverb_send_mixer_r, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, reverb_send_mixer_l, instance_id); - Serial.println(F(" -> Reverb send")); #endif } @@ -217,6 +209,7 @@ uint8_t active_voices[NUM_DEXED]; elapsedMillis cpu_mem_millis; #endif uint32_t cpumax = 0; +elapsedMillis cpu_overload_throttle_timer; uint32_t peak_dexed = 0; float peak_dexed_value = 0.0; uint32_t peak_r = 0; @@ -538,23 +531,26 @@ void setup() // set initial volume set_volume(configuration.vol, configuration.mono); -#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) // Initialize processor and memory measurements AudioProcessorUsageMaxReset(); AudioMemoryUsageMaxReset(); -#endif -#ifdef DEBUG for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { + Serial.print(F("Dexed instance ")); + Serial.print(instance_id); + Serial.println(F(":")); Serial.print(F("Bank/Voice from EEPROM [")); Serial.print(configuration.dexed[instance_id].bank, DEC); Serial.print(F("/")); Serial.print(configuration.dexed[instance_id].voice, DEC); Serial.println(F("]")); + Serial.print(F("Polyphony: ")); + Serial.println(configuration.dexed[instance_id].polyphony, DEC); +#ifdef DEBUG show_patch(instance_id); - } #endif + } Serial.print(F("AUDIO_BLOCK_SAMPLES=")); Serial.print(AUDIO_BLOCK_SAMPLES); @@ -604,16 +600,19 @@ void loop() for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) { active_voices[instance_id] = MicroDexed[instance_id]->getNumNotesPlaying(); -#ifdef CPU_OVERLOAD_THROTTLE - if (AudioProcessorUsageMax() > 99.9) +#if defined(CPU_OVERLOAD_THROTTLE) + if (AudioProcessorUsageMax() > CPU_OVERLOAD_THROTTLE && cpu_overload_throttle_timer >= CPU_OVERLOAD_THROTTLE_TIMER) { + cpu_overload_throttle_timer = 0; AudioProcessorUsageMaxReset(); MicroDexed[instance_id]->keyup(-1); // kills the oldest note and decreases max_notes - Serial.print(F("!!!CPU overload!!! Automatic throttling max_notes to ")); + Serial.print(F("!!!CPU overload!!! Automatic throttling polyphony down to ")); Serial.print(MicroDexed[instance_id]->getMaxNotes(), DEC); Serial.print(F(" for instance ")); Serial.print(instance_id, DEC); Serial.println(F(".")); + configuration.dexed[instance_id].polyphony = MicroDexed[instance_id]->getMaxNotes(); + eeprom_update(); // useful to do this??? } #endif } @@ -1258,21 +1257,19 @@ void initial_values_from_eeprom(bool init) init_configuration(); else { + Serial.println(F("Loading inital data from EEPROM.")); + EEPROM.get(EEPROM_START_ADDRESS, tmp_conf); checksum = crc32((byte*)&tmp_conf + 4, sizeof(tmp_conf) - 4); -#ifdef DEBUG Serial.print(F("EEPROM checksum: 0x")); Serial.print(tmp_conf.checksum, HEX); Serial.print(F(" / 0x")); Serial.println(checksum, HEX); -#endif if (checksum != tmp_conf.checksum) { -#ifdef DEBUG Serial.println(F("Checksum mismatch -> initializing EEPROM!")); -#endif init_configuration(); } else diff --git a/config.h b/config.h index d8925c0..ae017ac 100644 --- a/config.h +++ b/config.h @@ -212,8 +212,8 @@ #define NUM_DEXED 1 #define MAX_DEXED 2 #define NORMALIZE_DX_VELOCITY 1 -#define CPU_OVERLOAD_THROTTLE 1 - +#define CPU_OVERLOAD_THROTTLE 95.0 // Level (in percent) when throttling should start +#define CPU_OVERLOAD_THROTTLE_TIMER 100 // timer (in ms) when next throttling is possible enum { DEXED, CHORUS, DELAY, REVERB}; // MIDI @@ -231,9 +231,11 @@ enum { DEXED, CHORUS, DELAY, REVERB}; #define MIDI_DEVICE_USB_HOST 1 #if defined(USE_REVERB) #if defined(DEBUG) -#define MAX_NOTES 11 +//#define MAX_NOTES 12 +#define MAX_NOTES 16 #else -#define MAX_NOTES 12 +//#define MAX_NOTES 11 +#define MAX_NOTES 16 #endif #else #define MAX_NOTES 15 diff --git a/dexed.cpp b/dexed.cpp index ec2f30d..2b931e2 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -248,55 +248,52 @@ void Dexed::keydown(int16_t pitch, uint8_t velo) { } void Dexed::keyup(int16_t pitch) { - pitch += data[144] - TRANSPOSE_FIX; - - uint8_t note; if (pitch < 0) // for disabling the oldest note when cpu overload is detected { - note = abs((currentNote + 1) % max_notes); - voices[note].keydown = false; - if (max_notes == note) + voices[currentNote].keydown = false; + if (--max_notes == currentNote) currentNote = 0; - else - currentNote = note; - max_notes--; } else { + uint8_t note; + + pitch += data[144] - TRANSPOSE_FIX; + for (note = 0; note < max_notes; note++) { if ( voices[note].midi_note == pitch && voices[note].keydown ) { voices[note].keydown = false; break; } } - } - // note not found ? - if ( note >= max_notes ) { - return; - } + // note not found ? + if ( note >= max_notes ) { + return; + } - if ( monoMode ) { - int16_t highNote = -1; - uint8_t target = 0; - for (int8_t i = 0; i < max_notes; i++) { - if ( voices[i].keydown && voices[i].midi_note > highNote ) { - target = i; - highNote = voices[i].midi_note; + if ( monoMode ) { + int16_t highNote = -1; + uint8_t target = 0; + for (int8_t i = 0; i < max_notes; i++) { + if ( voices[i].keydown && voices[i].midi_note > highNote ) { + target = i; + highNote = voices[i].midi_note; + } } - } - if ( highNote != -1 && voices[note].live ) { - voices[note].live = false; - voices[target].live = true; - voices[target].dx7_note->transferState(*voices[note].dx7_note); + if ( highNote != -1 && voices[note].live ) { + voices[note].live = false; + voices[target].live = true; + voices[target].dx7_note->transferState(*voices[note].dx7_note); + } } - } - if ( sustain ) { - voices[note].sustained = true; - } else { - voices[note].dx7_note->keyup(); + if ( sustain ) { + voices[note].sustained = true; + } else { + voices[note].dx7_note->keyup(); + } } } diff --git a/dexed_sysex.cpp b/dexed_sysex.cpp index bf2df52..3d0c5fe 100644 --- a/dexed_sysex.cpp +++ b/dexed_sysex.cpp @@ -409,7 +409,8 @@ bool get_sysex_setup(File sysex, config_t configuration) return (false); } sysex.seek(3); - if (sysex.read() != 0x4b) // check for sysex type (0x75=MicroDexed setup) + uint8_t dexed_sysex_setup_type = sysex.read(); + if (dexed_sysex_setup_type >= 0x42 && dexed_sysex_setup_type < 0x45) // check for sysex type (0x75=MicroDexed setup for one to four instances) { #ifdef DEBUG Serial.println(F("E : SysEx type not MicroDexed setup.")); diff --git a/doc/sysex-format_dexed-setup.txt b/doc/sysex-format_dexed-setup.txt index 7a474f1..8afef73 100644 --- a/doc/sysex-format_dexed-setup.txt +++ b/doc/sysex-format_dexed-setup.txt @@ -7,16 +7,44 @@ SYSEX Message Controller-Set 11110000 F0 Status byte - start sysex 0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed) 0sssnnnn 00 Sub-status (s=0) & channel number (n=0; ch 1) - 0fffffff 00 format number (f=75; 1 MicroDexed setup) + 0fffffff 00 format number (f=66..69; 1..4 MicroDexed setup(s)) 0bbbbbbb 01 byte count MS byte - 0bbbbbbb 1B byte count LS byte (b=38; 1 setup using 1 instance - b=69; 1 setup using 2 instances) - 0ddddddd ** data byte 1 controller-set + 0bbbbbbb 1B byte count LS byte (b=44; 1 instance + b=73; 2 instances + b=102; 3 instances + b=131; 4 instances) + 0ddddddd ** data byte 1 setup config | | | - 0ddddddd ** data byte 38 or 69 - 0eeeeeee ** checksum (masked 2's comp. of sum of 38 or 69 bytes) + 0ddddddd ** data byte 19 + 0ddddddd ** data byte 20 instance config 0 + + | | | + + 0ddddddd ** data byte 43 + /-Optional--------------------------------------------\ + 0ddddddd ** data byte 44 instance config 1 + + | | | + + 0ddddddd ** data byte 72 + \-----------------------------------------------------/ + /-Optional--------------------------------------------\ + 0ddddddd ** data byte 73 instance config 2 + + | | | + + 0ddddddd ** data byte 101 + \-----------------------------------------------------/ + /-Optional--------------------------------------------\ + 0ddddddd ** data byte 102 instance config 3 + + | | | + + 0ddddddd ** data byte 131 + \-----------------------------------------------------/ + 0eeeeeee ** checksum (masked 2's comp. of sum of ** bytes) 11110111 F7 Status - end sysex Data Structure: MicroDexed Setup Dump