UInt8Array Sysex format

Hello folks,

I am currently trying to read a file which contains Sysex data for an hardware patch, which I wrote with getting a dump from the hardware.

When I read the data to load the patch, I need to shape it back to the sysex format which is an Array of UInt8Arrays
I went through the help files but couldn’t really find a way to turn an Array to UInt8Array so thought I’d ask here.
Also, split function seem to be acting funny with “_” hence the replace/split.

	var sline = (~patchSYSFile.getLine.replace("_", " ").split(" "));
	~patchSYSArray.add(sline);

Any suggestions?

I use something like this to load a binary .syx file

(
var contents = File.new(sysexfilename, "rb");
var array = Int8Array();
contents.do({|el| array = array.add(el.ascii); });
midi_out.sysex(array);
)

I’m not sure it’s optimal, but it works for smaller sysex messages (up to a few KB).

Trying to send massive sysexes (with multi megabyte size, e.g. to perform an OS update on my synth) doesn’t seem to work (although it might be unrelated to using this approach, but rather caused by some underlying problem/limitation in the midi implementation. I think massive sysexes are best sent in successive smaller blocks but I have no clue how to do that in supercollider. Ideally the underlying midi implementation would do this behind the scenes. And perhaps it does and I’m just talking nonsense. Or maybe it just takes forever to create the array because of all the copying? I saw it fail empirically, but didn’t arrive at examining why yet.)

How do you save the sysex? I managed to get it working but G2 seem to be failing at loading some patches, could be the code that’s problematic. I am basically writing the patch as sysex dump (an Array of UInt8Array) in a text file and then parsing it back to the Sysex format.

Might make more sense to convert it all to binary tho.

 for (0 , 50 ,{arg i;

	var firstIndex = ~indS[i];
	var secondIndex = ~indS[i+1];
	~patchSYSArray = Array (512);
	if(secondIndex == nil, { secondIndex = ~patchSYSFile.size;});
	if(firstIndex == nil, {firstIndex  = ~patchSYSFile.size   });
	~lin =  (~patchSYSFile.asString[firstIndex..secondIndex].split($/));
	512.do({arg j;

		j.postln;
		if(~lin[j] != nil,{
			~patchSYSArray.add(~lin[j].asInt);});
	});
	~patchSYSArray= ~patchSYSArray.as(Int8Array);
	~patchMainArray.add(~patchSYSArray);

});

for (0, ~patchMainArray.size-1, { arg i;~nord.sysex(~patchMainArray[i])});

Until now I’ve never needed to save sysex. When I receive it, I immediately parse it into some datastructure (and I have some save/load code for that datastructure). After constructing a sysex msg, I just send it to my synth.

But the code you posted has a serious problem: you have to be careful when you add stuff to an Array to always assign the outcome of .add, otherwise it’s not guaranteed that the array contains the new information and things can randomly fail (oh the joys of debugging such situations :wink: )

So a line like this:

~patchSYSArray.add(~lin[j].asInt);})

should be

~patchSYSArray = ~patchSYSArray.add(~lin[j].asInt);})

and

~patchMainArray.add(~patchSYSArray);

should be

~patchMainArray = ~patchMainArray.add(~patchSYSArray);

Maybe that can already make a difference if things seem to randomly fail for you.

1 Like

Ah yes. good catch :slight_smile: I’ll test it out to see if it makes any changes.