Changes for autothrottling max simulatinious note.

Changes for dexed setup format.
pull/32/head
Holger Wirtz 5 years ago
parent dcccc77712
commit 1533e6ba12
  1. 35
      MicroDexed.ino
  2. 10
      config.h
  3. 59
      dexed.cpp
  4. 3
      dexed_sysex.cpp
  5. 40
      doc/sysex-format_dexed-setup.txt

@ -177,25 +177,17 @@ AudioConnection * dynamicConnections[NUM_DEXED * 8];
#endif #endif
void create_audio_connections(AudioSourceMicroDexed &dexed, AudioEffectMonoStereo &mono2stereo, uint8_t instance_id) 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, microdexed_peak_mixer, instance_id);
dynamicConnections[nDynamic++] = new AudioConnection(dexed, 0, mono2stereo, 0); 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, 0, dexed_mixer_r, instance_id);
dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, dexed_mixer_l, 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, 0, chorus_send_mixer_r, instance_id);
dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, chorus_send_mixer_l, 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, 0, delay_send_mixer_r, instance_id);
dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, delay_send_mixer_l, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, delay_send_mixer_l, instance_id);
Serial.println(F(" -> Delay send"));
#if defined(USE_REVERB) #if defined(USE_REVERB)
dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, reverb_send_mixer_r, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 0, reverb_send_mixer_r, instance_id);
dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, reverb_send_mixer_l, instance_id); dynamicConnections[nDynamic++] = new AudioConnection(mono2stereo, 1, reverb_send_mixer_l, instance_id);
Serial.println(F(" -> Reverb send"));
#endif #endif
} }
@ -217,6 +209,7 @@ uint8_t active_voices[NUM_DEXED];
elapsedMillis cpu_mem_millis; elapsedMillis cpu_mem_millis;
#endif #endif
uint32_t cpumax = 0; uint32_t cpumax = 0;
elapsedMillis cpu_overload_throttle_timer;
uint32_t peak_dexed = 0; uint32_t peak_dexed = 0;
float peak_dexed_value = 0.0; float peak_dexed_value = 0.0;
uint32_t peak_r = 0; uint32_t peak_r = 0;
@ -538,23 +531,26 @@ void setup()
// set initial volume // set initial volume
set_volume(configuration.vol, configuration.mono); set_volume(configuration.vol, configuration.mono);
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
// Initialize processor and memory measurements // Initialize processor and memory measurements
AudioProcessorUsageMaxReset(); AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset(); AudioMemoryUsageMaxReset();
#endif
#ifdef DEBUG
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++) 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(F("Bank/Voice from EEPROM ["));
Serial.print(configuration.dexed[instance_id].bank, DEC); Serial.print(configuration.dexed[instance_id].bank, DEC);
Serial.print(F("/")); Serial.print(F("/"));
Serial.print(configuration.dexed[instance_id].voice, DEC); Serial.print(configuration.dexed[instance_id].voice, DEC);
Serial.println(F("]")); Serial.println(F("]"));
Serial.print(F("Polyphony: "));
Serial.println(configuration.dexed[instance_id].polyphony, DEC);
#ifdef DEBUG
show_patch(instance_id); show_patch(instance_id);
}
#endif #endif
}
Serial.print(F("AUDIO_BLOCK_SAMPLES=")); Serial.print(F("AUDIO_BLOCK_SAMPLES="));
Serial.print(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++) for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{ {
active_voices[instance_id] = MicroDexed[instance_id]->getNumNotesPlaying(); active_voices[instance_id] = MicroDexed[instance_id]->getNumNotesPlaying();
#ifdef CPU_OVERLOAD_THROTTLE #if defined(CPU_OVERLOAD_THROTTLE)
if (AudioProcessorUsageMax() > 99.9) if (AudioProcessorUsageMax() > CPU_OVERLOAD_THROTTLE && cpu_overload_throttle_timer >= CPU_OVERLOAD_THROTTLE_TIMER)
{ {
cpu_overload_throttle_timer = 0;
AudioProcessorUsageMaxReset(); AudioProcessorUsageMaxReset();
MicroDexed[instance_id]->keyup(-1); // kills the oldest note and decreases max_notes 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(MicroDexed[instance_id]->getMaxNotes(), DEC);
Serial.print(F(" for instance ")); Serial.print(F(" for instance "));
Serial.print(instance_id, DEC); Serial.print(instance_id, DEC);
Serial.println(F(".")); Serial.println(F("."));
configuration.dexed[instance_id].polyphony = MicroDexed[instance_id]->getMaxNotes();
eeprom_update(); // useful to do this???
} }
#endif #endif
} }
@ -1258,21 +1257,19 @@ void initial_values_from_eeprom(bool init)
init_configuration(); init_configuration();
else else
{ {
Serial.println(F("Loading inital data from EEPROM."));
EEPROM.get(EEPROM_START_ADDRESS, tmp_conf); EEPROM.get(EEPROM_START_ADDRESS, tmp_conf);
checksum = crc32((byte*)&tmp_conf + 4, sizeof(tmp_conf) - 4); checksum = crc32((byte*)&tmp_conf + 4, sizeof(tmp_conf) - 4);
#ifdef DEBUG
Serial.print(F("EEPROM checksum: 0x")); Serial.print(F("EEPROM checksum: 0x"));
Serial.print(tmp_conf.checksum, HEX); Serial.print(tmp_conf.checksum, HEX);
Serial.print(F(" / 0x")); Serial.print(F(" / 0x"));
Serial.println(checksum, HEX); Serial.println(checksum, HEX);
#endif
if (checksum != tmp_conf.checksum) if (checksum != tmp_conf.checksum)
{ {
#ifdef DEBUG
Serial.println(F("Checksum mismatch -> initializing EEPROM!")); Serial.println(F("Checksum mismatch -> initializing EEPROM!"));
#endif
init_configuration(); init_configuration();
} }
else else

@ -212,8 +212,8 @@
#define NUM_DEXED 1 #define NUM_DEXED 1
#define MAX_DEXED 2 #define MAX_DEXED 2
#define NORMALIZE_DX_VELOCITY 1 #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}; enum { DEXED, CHORUS, DELAY, REVERB};
// MIDI // MIDI
@ -231,9 +231,11 @@ enum { DEXED, CHORUS, DELAY, REVERB};
#define MIDI_DEVICE_USB_HOST 1 #define MIDI_DEVICE_USB_HOST 1
#if defined(USE_REVERB) #if defined(USE_REVERB)
#if defined(DEBUG) #if defined(DEBUG)
#define MAX_NOTES 11 //#define MAX_NOTES 12
#define MAX_NOTES 16
#else #else
#define MAX_NOTES 12 //#define MAX_NOTES 11
#define MAX_NOTES 16
#endif #endif
#else #else
#define MAX_NOTES 15 #define MAX_NOTES 15

@ -248,55 +248,52 @@ void Dexed::keydown(int16_t pitch, uint8_t velo) {
} }
void Dexed::keyup(int16_t pitch) { 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 if (pitch < 0) // for disabling the oldest note when cpu overload is detected
{ {
note = abs((currentNote + 1) % max_notes); voices[currentNote].keydown = false;
voices[note].keydown = false; if (--max_notes == currentNote)
if (max_notes == note)
currentNote = 0; currentNote = 0;
else
currentNote = note;
max_notes--;
} }
else else
{ {
uint8_t note;
pitch += data[144] - TRANSPOSE_FIX;
for (note = 0; note < max_notes; note++) { for (note = 0; note < max_notes; note++) {
if ( voices[note].midi_note == pitch && voices[note].keydown ) { if ( voices[note].midi_note == pitch && voices[note].keydown ) {
voices[note].keydown = false; voices[note].keydown = false;
break; break;
} }
} }
}
// note not found ? // note not found ?
if ( note >= max_notes ) { if ( note >= max_notes ) {
return; return;
} }
if ( monoMode ) { if ( monoMode ) {
int16_t highNote = -1; int16_t highNote = -1;
uint8_t target = 0; uint8_t target = 0;
for (int8_t i = 0; i < max_notes; i++) { for (int8_t i = 0; i < max_notes; i++) {
if ( voices[i].keydown && voices[i].midi_note > highNote ) { if ( voices[i].keydown && voices[i].midi_note > highNote ) {
target = i; target = i;
highNote = voices[i].midi_note; highNote = voices[i].midi_note;
}
} }
}
if ( highNote != -1 && voices[note].live ) { 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);
}
} }
}
if ( sustain ) { if ( sustain ) {
voices[note].sustained = true; voices[note].sustained = true;
} else { } else {
voices[note].dx7_note->keyup(); voices[note].dx7_note->keyup();
}
} }
} }

@ -409,7 +409,8 @@ bool get_sysex_setup(File sysex, config_t configuration)
return (false); return (false);
} }
sysex.seek(3); 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 #ifdef DEBUG
Serial.println(F("E : SysEx type not MicroDexed setup.")); Serial.println(F("E : SysEx type not MicroDexed setup."));

@ -7,16 +7,44 @@ SYSEX Message Controller-Set
11110000 F0 Status byte - start sysex 11110000 F0 Status byte - start sysex
0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed) 0iiiiiii 67 ID # (i=103; unofficial SYSEX-ID for MicroDexed)
0sssnnnn 00 Sub-status (s=0) & channel number (n=0; ch 1) 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 01 byte count MS byte
0bbbbbbb 1B byte count LS byte (b=38; 1 setup using 1 instance 0bbbbbbb 1B byte count LS byte (b=44; 1 instance
b=69; 1 setup using 2 instances) b=73; 2 instances
0ddddddd ** data byte 1 controller-set b=102; 3 instances
b=131; 4 instances)
0ddddddd ** data byte 1 setup config
| | | | | |
0ddddddd ** data byte 38 or 69 0ddddddd ** data byte 19
0eeeeeee ** checksum (masked 2's comp. of sum of 38 or 69 bytes) 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 11110111 F7 Status - end sysex
Data Structure: MicroDexed Setup Dump Data Structure: MicroDexed Setup Dump

Loading…
Cancel
Save