Page 1 of 1

Receiving sysex

Posted: 08 Mar 2015 11:56
by strophlex
Hello

I am making a template for controlling the Ex-800 with HAWK800 mod. I can now control all parameters, but I'd like to be able to read and dump complete patches too. When reading a patch a specific syx message is sent to the synth and the patch dump is sent back. I all works, but trouble arrises when reading the received dump. It worked as expected as long as I had implemented just the first parameters, but then lemur crashed and I think it was because of the limit of script length. I then researched if there is a way to call a script with parameters (the received syx dump) but it doesn't seem like that. Instead I made a second script that also receives syx (On MIDI, F0 - system exclusive, none, 0 to 127, 1 to 1). The second script starts reading where the first script left off. But now when I receive the sysex dump, Lemur crashes. Is it possible to do like I do? Is there some way around this? The array of sysex is 256 I think, but I read about 240.

Script 1
(On MIDI, F0 - system exclusive, none, 0 to 127, 1 to 1)

Code: Select all

decl i = 4;
DCO1_oct.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO1_wave.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO1_harmonics.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
DCO1_harm_modulation_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO1_harm_modulation_source.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO1_harm_modulation_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
DCO1_volume.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_mode.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];

DCO2_oct.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO2_wave.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO2_harmonics.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
DCO2_harm_modulation_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO2_harm_modulation_source.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO2_harm_modulation_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
DCO2_volume.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
i += 2;
DCO2_interval.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/12;
DCO2_detune.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/3;
Noise_level.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 10;
Frequency.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/99;
Freq_keyboard_track.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Freq_EG_Invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Freq_EG_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
EG3_retrigger.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
i += 4;
Chorus.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO1_attack.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_decay.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_breakpoint.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_slope.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_sustain.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO1_release.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
i += 4;
DCO2_attack.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO2_decay.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO2_breakpoint.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO2_slope.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO2_sustain.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
DCO2_release.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
i += 4;
EG3_attack.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
EG3_decay.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
EG3_breakpoint.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
EG3_slope.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
EG3_sustain.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
EG3_release.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/31;
i += 4;
Velocity_OP1_intensity.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/4;
Velocity_OP1_invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Velocity_OP1_target.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Velocity_OP2_intensity.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/4;
Velocity_OP2_invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Velocity_OP2_target.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Freq_velocity.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/6;
Freq_vel_resp_shape.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Script 2
(On MIDI, F0 - system exclusive, none, 0 to 127, 1 to 1)

Code: Select all

decl i = 65*2+4;
LFO1_frequency.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
LFO1_delay_timer.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
LFO1_free_runing.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO1_delay_invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO1_PWM_phase.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/62;
LFO1_LFO3_modulation_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO1_LFO3_modulation_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
LFO2_frequency.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
LFO2_delay_timer.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
LFO2_free_runing.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO2_delay_invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO2_PWM_phase.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/62;
LFO2_LFO4_modulation_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
LFO2_LFO4_modulation_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
DCO_pitch_modulation_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO_pitch_modulation_source.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO_pitch_modulation_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
DCO_pitch_modulation_eg_invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
DCO_pitch_modulation_depth_eg.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
DCO_pitch_modulation_mode.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_freq_LFO_waveform1.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_freq_LFO_source1.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_freq_LFO_depth1.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
VCF_freq_LFO_waveform2.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_freq_LFO_source2.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_freq_LFO_depth2.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
Filter_mode.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Resonance.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/99;
VCF_res_LFO_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_res_LFO_source.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
VCF_res_LFO_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
Res_EG_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
Res_EG_Invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
Aggressive_resonance.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
FM800_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/99;
FM800_LFO_waveform.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
FM800_LFO_source.selection = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
FM800_LFO_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
i += 2;
FM800_EG_depth.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
FM800_EG_Invert.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
i += 2;
SLFO3_frequency.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
SLFO3_phase.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/62;
SLFO3_free_runing.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];
SH_rate.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/99;
SLFO4_frequency.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/15;
SLFO4_phase.x = (MIDI_ARGS[i++]*16 + MIDI_ARGS[i++])/62;
SLFO4_free_runing.x = MIDI_ARGS[i++]*16 + MIDI_ARGS[i++];

Re: Receiving sysex

Posted: 09 Mar 2015 09:39
by oldgearguy
A couple quick suggestions.
First - set Lemur aside.
Second - use MIDI-Ox/Sysex Librarian/other tool to manually send the dump request to the EX-800 and save off the returned sysex stream.
Third - manually count the bytes received, F0->F7 inclusive. If the number is 256 or less, continue working on your template. If it is more, stop and do something else, currently it *will not* work with the lemur no matter how many receive scripts you write.

If you are continuing,
MIDI_ARGS is the complete sysex buffer received. You can use a modification of the program attached to display each byte of MIDI data in the buffer (change midiArgs to MIDI_ARGS and add your sysex receive routine) to verify you are getting everything. Then you can figure out how to break it all apart.

Re: Receiving sysex

Posted: 09 Mar 2015 11:57
by strophlex
I checked the reference documents and according to that the sysex is 256 bytes of patch data plus six bytes of head/tail which means it is 262 bytes in total. Does that mean this project is doomed or is it possible to read the first 256 bytes? It is a bit strange that all worked well when receiving the first about 160 bytes or something (the first script only)...

Re: Receiving sysex

Posted: 09 Mar 2015 13:03
by oldgearguy
strophlex wrote:I checked the reference documents and according to that the sysex is 256 bytes of patch data plus six bytes of head/tail which means it is 262 bytes in total. Does that mean this project is doomed or is it possible to read the first 256 bytes? It is a bit strange that all worked well when receiving the first about 160 bytes or something (the first script only)...

256 total for Lemur. Any data received beyond that causes weirdness/corruption/crashing. So even though it is 256 of actual data, Lemur doesn't distinguish data from wrapper. This hard limit has doomed more than one patch editor/librarian project.

Given how embedded the number 8 is in all the Lemur stuff (referencing 0-255 only requires 8 bits/1 byte of data), my guess is that it would be a significant rewrite to expand that buffer size.

Unless you can get the EX-800 to send the data in smaller blocks with a significant time gap between the blocks (so that Lemur clocks over to the next frame and does a fresh read) you'll just be chasing your tail trying to get it to work reliably.

Re: Receiving sysex

Posted: 09 Mar 2015 14:27
by strophlex
Thanks for the insight. I will just ditch this template and do it from scratch in MAX / MIRA then.