Sending Raw MIDI

Discuss music production with Ableton Live.
Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Sending Raw MIDI

Post by Clint Goss » Sun Jul 14, 2024 9:56 am

I would like to send raw MIDI to an external device from MIDI clips in Live (both Workstation and Push 3S). All the tools I have found related to Live seem to be GUI-based tools to make it easy for a given device, but I really just want to author the MIDI in Hex. Most of it would be SysEx, but some are arbitrary strings of CC commands.

Before I flush days of time down the drain and end up (yet again) beating my head against the studio walls ...

Is there a preferred method for doing this?

Could I
  • use some external tool to author .MID files (Reaper?, MIDI-OX?),
  • drop them into clips in Live Session view (remember, I'm using Push 3S), and then
  • just play them to the device?

Would that work?

Or maybe there is some more straightforward way to author / edit raw MIDI clips in Live / Workstation and play them on my Push 3S?

Details: I need to configure the VL70-m I use to render many of my Sylphyo (WindSynth) sounds. It needs to be done live, since the Internal preset banks of the VL70-m do not actually save many of the more esoteric settings for the patches I use. I did it very successfully from Cantabile, which has an internal raw-mode MIDI editor that interprets strings such as ...

Code: Select all

x"F0431057" x"200025" 75 0xF7
... and sends them to the device.

Synthbuilder
Posts: 523
Joined: Thu Nov 10, 2005 8:42 am
Location: Cumbria, UK
Contact:

Re: Sending Raw MIDI

Post by Synthbuilder » Sun Jul 14, 2024 10:10 am

I use midi-ox and it does the job. I'm still using Win10 so I don't know if it works as well on Win11. I use a Mac to run Live, but I have an old laptop to do the midi sysex stuff separately.

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Sun Jul 14, 2024 10:34 am

Synthbuilder wrote:
Sun Jul 14, 2024 10:10 am
I use midi-ox and it does the job. ...
Cool. Thanks.

And you export from Midi-Ox to a .MID file, read that into a clip in Live, and have no issues sending that out to the device?

Synthbuilder
Posts: 523
Joined: Thu Nov 10, 2005 8:42 am
Location: Cumbria, UK
Contact:

Re: Sending Raw MIDI

Post by Synthbuilder » Sun Jul 14, 2024 11:16 am

Clint Goss wrote:
Sun Jul 14, 2024 10:34 am
And you export from Midi-Ox to a .MID file, read that into a clip in Live, and have no issues sending that out to the device?
Ah, sorry, I think I have misunderstood your original requirement. I don't think you can import midi clips with sysex in them. Live will just ignore any sysex info. Maybe you could do it in a M4L patch though.

When I was all on PC I would generally do this sort of thing by closing Live and opening midi-ox. Once the dump was done, I'd re-open Live. It might be possible to keep both programs open and have them both access the midi outputs. I used to use Ctrlr, a sysex programer app, at the same time as Live and both could access the same midi port and channel at the same time.

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Sun Jul 14, 2024 11:36 am

OK, Glad I asked. Thanks for that ...

I just succeeded at exporting a Program Change command from Cantabile to a .MID file, importing that .MID into an Ableton Clip in Session view, and sending it to my VL70-m. It worked to change the patch appropriately on the VL70-m.

I cannot seen anything about the contents of the MIDI clip in Live, but at least it worked. Not sure if other SysEx Commands will get though ... will have to test further ...

My real goal is to use this for HW configuration from Push 3S. If this Live can't do it, then I could add another MIDI controller, going into a Bome Box, into a MIDI Merge box, into my VL70-m ... I'm trying to avoid the additional 3 pieces of hardware just to properly switch and configure patches on my VL70-m.

chapelier fou
Posts: 6258
Joined: Mon May 15, 2006 12:15 pm

Re: Sending Raw MIDI

Post by chapelier fou » Sun Jul 14, 2024 6:04 pm

M4L can output any midi message, did you consider it ?
MacBook Pro 13" Retina i7 2.8 GHz OS 10.13, L10.0.1, M4L.
MacStudio M1Max 32Go OS 12.3.1

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Mon Jul 15, 2024 8:21 am

Digging into M4L now ... my first exposure to it. Thanks ...

Definitely the way to go for this issue. [sxformat] is made for this type of thing ...

chapelier fou
Posts: 6258
Joined: Mon May 15, 2006 12:15 pm

Re: Sending Raw MIDI

Post by chapelier fou » Mon Jul 15, 2024 11:59 am

Sxformat is just supposed to help you but usually I prefer not using it but it’s only a matter of preference. Tell me if you need help !
MacBook Pro 13" Retina i7 2.8 GHz OS 10.13, L10.0.1, M4L.
MacStudio M1Max 32Go OS 12.3.1

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Tue Jul 16, 2024 8:11 am

Thanks Chapelier ...

Wrestling a bit with the visual programming thing ... coming from 49 years of text based languages.

So SXformat is cool, except that it *requires* your content to be SysEx, and my hardware (VL70) calls for a mix SysEx and CC commands. Using Message instead for the MIDI content, but its substitution and expression capabilities are different, causing teeth gnashing.

Could not locate an appropriate example M4L device that simply reads a file with a MIDI stream spec of some sort (preferably text-based, with comments and capability to have both 0xFF as well as decimal, possibly with timing delay directives?) or has that MIDI stream spec embedded in the Device and ships it out to the output.

Edit: OK, just found the seq object ... I think I'm back on track now ...

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Tue Jul 16, 2024 2:34 pm

Moving forward. [seq] is the magic bullet. I've got it working on both Live / Workstation and Push 3S.

For my particular setup, I've hacked a small perl script to convert my ad hoc "TextMidi" format into the .txt format accepted by [seq]. Input looks like this:

Code: Select all

# Example of a .tmid (Text-based MIDI) file.
#
# TMidi format is Clint's ad hoc MIDI description language that allows comments, various input formats (hex) and
# control over the millisecond timing of the MIDI messages.
#
# These files are processed by the tmidi2txt.pl script into the bland .txt format read by Max4Live [seq] objects.
#
# Clint Goss <clint@goss.com> Copyright 2024 by Clint Goss, available under CC-BY 4.0

FIRST 10	# Initializes the timing counter (in Milliseconds) for the first emitted MIDI command (default 0).
STEP 30		# Sets the timing increment between MIDI commands (default 50).

192 10 x0A;		# Single hex values
192 11 xFFFE0012;	# Multiple hex values are allowed
+1 200 192 12;		# + or - at the start indicates a *modification* to the timing counter (carries forward)
-5 xA0			# The ';' at the end is optional.
192 12;

# ending comment
... and output of the perl script for the above is ...

Code: Select all

10 192 10 10;
40 192 11 255 254 0 18;
71 200 192 12;
96 160;
126 192 12;
Here is the perl script:

Code: Select all

# tmidi2txt.pl
#
# tmidi2txt Name
#
# Converts a file in Tmidi format (Clint's MIDI description langauge, which allows comments and various input formats)
# to the bland .txt format read by the Max4Live [seq] object.

use strict;		# Require declarations

use Getopt::Std;	# Options processing
use vars qw($opt_c);

if (!getopts('c')) {
	usage();
	exit;
}

my $numArgs = $#ARGV + 1;
if ($numArgs < 1) {
	usage();
	exit;
}

sub usage () {
    print <<EOM;

Usage: tmidi2txt.pl Name

Convert a file in Tmidi format (Clint's MIDI description langauge,
which allows comments and various input formats)
to the bland .txt format read by the Max4Live [seq] object.

EOM
}

my $Name = $ARGV[0];

my $inFileName = $Name . ".tmid";
my $outFileName = $Name . ".txt";

print "tmidi2txt: $inFileName => $outFileName\n";

open (INFILE, '<', $inFileName) || die "Cannot open $inFileName";
open (OUTFILE, '>', $outFileName) || die "Cannot open $outFileName";

my $inLine;

my $ms = 0;		# Current millisecond counter
my $step = 50;

my $lineCount = 0;

while ($inLine = <INFILE>) {

	my $outLine = "";

	$lineCount++;
	chomp ($inLine);

	$inLine =~ s/^[ \t]+//;

	# Directives that control the time counter

	if ($inLine =~ /^FIRST/) {
		# Initialize the millsecond counter
		$inLine =~ s/^FIRST[ \t]+//;
		$ms = int ($inLine);
		next;
	}
		

	if ($inLine =~ /^STEP/) {
		# Increment for the millsecond counter
		$inLine =~ s/^STEP[ \t]+//;
		$step = int ($inLine);
		next;
	}

	if ($inLine =~ /^[+-]/) {
		# Bias the running millisecond counter
		my $bias = substr ($inLine, 0, 1);
		$inLine =~ s/.//;		# Eat the plus or minus

		while ($inLine =~ /^[0-9]/) {
			my $ch1 = substr ($inLine, 0, 1);
			$inLine =~ s/.//;
			$bias .= $ch1;
		}
		
		$ms += int ($bias);

		$inLine =~ s/^[ \t]+//;
	}

	ThisLine: while (length ($inLine) > 0) {
		$inLine =~ s/^[ \t]+//;
		if ($inLine =~ /^#/) { last ThisLine; }

		if ($inLine =~ /^x/) {
			$inLine =~ s/.//; # Eat the "x"
			# Pairs of Hex digits
			while ($inLine =~ /^[0-9a-fA-F]/) {
				my $ch1 = substr ($inLine, 0, 1);
				my $ch2 = substr ($inLine, 1, 1);
				$inLine =~ s/..//;

				if ($ch2 !~ /[0-9a-fA-F]/) {
					print STDERR "ERROR: Line $lineCount: bad hex number\n";
					print STDERR "   remaining line: [$inLine], ch1: [$ch1], ch2: [$ch2]\n";
					last ThisLine;
				}
				$outLine .= hex ($ch1 . $ch2) . " ";
			}

		} elsif ($inLine =~ /^[0-9]/) {
			# A base-10 number

			while ($inLine =~ /^[0-9]/) {
				my $ch1 = substr ($inLine, 0, 1, "");
				$outLine .= $ch1;
			}

		} elsif ($inLine =~ /^;/) {
			# Ignore
			$inLine =~ s/.//; # Eat the ";"
		} else {
			print STDERR "ERROR: Line $lineCount: bad format / character unexpected\n";
			print STDERR "   remaining line: [$inLine]\n";
			last ThisLine;
		}
		
		$outLine .= " ";
	}

	# Tighten up out masterpiece

	while ($outLine =~ /  /) {
		$outLine =~ s/  / /g;
	}

	$outLine =~ s/ $//;

	# Skip blank lines

	if (length ($outLine) > 0) {
		printf "%d %s;\n", $ms, $outLine;
		printf OUTFILE "%d %s;\n", $ms, $outLine;
		$ms += $step;
	}
} 

close INFILE || die "Cannot close $inFileName";
close OUTFILE || die "Cannot close $outFileName";

1;
My actual M4L device responds to a MIDI Note-On with pitch 0, or a button push (which I don't see how to actuate on Push3). Not sure how to attach a .AMXD device on this forum ... maybe I don't have enough "trust points" here? But it's pretty simple, just using [seq] at the core.

Here's my actual beginnings of a patch for one VL70 preset:

Code: Select all

# TMID (Text-based MIDI) for the VL70-m Thai Reed preset
#
# TMidi format is Clint's ad hoc MIDI description language that allows comments, various input formats (hex) and
# control over the millisecond timing of the MIDI messages.
#
# These files are processed by the tmidi2txt.pl script into the bland .txt format read by Max4Live [seq] objects.
#
# See WindSynthRig.xlsx [VL70 Roster] worksheet for the values of all VL70 patches.
#
# Clint Goss <clint@goss.com> Copyright 2024 by Clint Goss, available under CC-BY 4.0

# FIRST 10	# Initializes the timing counter (in Milliseconds) for the first emitted MIDI command (default 0).
# STEP 30	# Sets the timing increment between MIDI commands (default 50).

# LB = Yamaha VL70 List Book dated 29Jul2003

xB0 0 33	# Select the Preset1/Preset2/Custom/Internal Bank. CC 0. LB page 26, #4
		# Done for each patch change "just in case" someone switched us out.

xB0 32 0	# Select the bank for this preset: 0=Pr1, 1=PR2, 2=Cst, 3=Int. CC 32. LB page 26, #4

xC0 106		# Program Change for our desired patch. LB page 26, #2

xB0 7 96	# Set the Volume - used to balance volumes across patches to minimized the need for volume 
		# adjustments when playing live. See WindSynthRig.xlsx [VL70 Roster]. CC 7.
		# LB p. 26 #4, right column, Main Volume.
		

chapelier fou
Posts: 6258
Joined: Mon May 15, 2006 12:15 pm

Re: Sending Raw MIDI

Post by chapelier fou » Tue Jul 16, 2024 3:02 pm

When editing the Max device, hit "Edit/Copy Compressed" and then you can paste the patch here in the form of compact text.

(there is no file sharing on this forum.....)

Also you might want to look at one of my devices : https://maxforlive.com/library/device/6 ... x-recorder
MacBook Pro 13" Retina i7 2.8 GHz OS 10.13, L10.0.1, M4L.
MacStudio M1Max 32Go OS 12.3.1

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Tue Jul 16, 2024 4:32 pm

I did look at your Recorder - nice stuff but it was beyond me when I first looked at it ... and my device is actually much simpler:

Code: Select all

<pre><code>
----------begin_max5_patcher----------
1055.3oc0X00aaaCE8YGf7efPurM.GCQJIKo9PA5vv.5CcsnqXuzMTPKwjvT
IRMQpNmVz+6ieH4nXKSojI2z8PbfnH88dNGdO7R+kyOag2F9VhvC7Lv6AKV7
E0HKLioGYQ2.K7JwayJvByD8x3kkDlzaY6KkjsRyKd20DvkzBBHiyjpYH.TA
PViYhRpTRxAbFnljQIUR.+Rvqd4u7RvuwkjWy.ugJytF3C9CRAOiJuE.u.hh
A7ZvlaAYEzrORYWAjp.roQJ4rU6hdAkQx3MLSJDzMZUMQnx.rjxYeXBSQkVR
KKrFsxeIHHT+ILJo6AveMz5zKA18BZtgE3at4hvcoWEVALUt2KBQqPQpuaTa
H7OLDZFMiWvqsKveUZJBFsNYMJNLxOMQsL8hLqDt+BuoQHoWRyNLAuTIKB5m
I5A0.qcXVSIkUPjh6MY0n7FY2v9lQ+54mo+u5eK+uua4GeK4heplfy+Slrci
yvhJZbQEMhnB8Mbdpg1hMhJJsOwooFFtzPMdunlhK7dH5MJvkf2F83fUQCGc
2x1So9nPdtoP8DJMQZBwJMQm.oA5RZRi6IMQ+eQZ9UUsB5Uzb5y.+tVfv.MA
kaMekbkOo03M6i+fvZy95FYUi7jIhgwFqnzdNZ2mFmhRAiG20L9nQ3D4YdZU
XF4eTH+PAVPJT.G3u6M1nIushXgm2FL6Juk.Ou6.Repzoej5vFEUFfLEdgAF
tzuOkbOPiFFznYGzO2Edo5MhCB0Tm02IqhUXEEiZ2wD8XvJb1w5UXI43f8HH
MYbQEY8Q+1Czi5U00Qm2PHB4T6fFPDZbUBscKsd+SF99oeFSKrCgRmx1ZibY
wXf+2IX7X6ZaXUpyTbWjtzUspyyhCirbgwiODNhsD7aksTo5b1JbsvU85x69
qGGb+QNBk3ORQslEfFxHEMRQ8QnjjGMkTRDB7UjC4Dca6f2cMl9VBIekbqza
jFDrmdGYbgSRNTZcYANkdGlPqCQF6jgB9o0Yzdg0wHHHzjXsc1D18oCFxzAv
CikhbdKEXngmT0eQCmBSYyF7tHTq5IURp+.gg2TPNUMJ82CuO7XdSt6ax803
hssJEaLqSBebFTAmDCJdul6O7BSfelWjOzQSnIf2t9DiODu8ObB5+Te5jlGn
rISCOfVLG2hFFaO0xedIo8ccreqlqus+OZmI0zuXOpSvapy5fXqUInW5kSTW
8gsy1386JD5Ooqo44D1H9fSNChdxyffojAH6jlgvouix3wS2e+bEvjIEvf4K
fAO.McNhmplD.GEfoya.mlDBmm.5Oo.BmODNo34OX7Z8kvUUehTKZWhMTJu6
ar+nLIKsOSY1mWaetl7IZ2RrMe4gqUtrRkEaSs09d651eQcuRdNol0P6bBzf
UGZywCZ6dg5JJ1EoOF47yTS3eAT4hsdC
-----------end_max5_patcher-----------
</code></pre>

Thanks for all the assistance!!

chapelier fou
Posts: 6258
Joined: Mon May 15, 2006 12:15 pm

Re: Sending Raw MIDI

Post by chapelier fou » Tue Jul 16, 2024 6:23 pm

Really nice for a first patch.

If you only have to read a .txt file and output its content, you should look at [coll] which is probably the most used object to store and recall data.
MacBook Pro 13" Retina i7 2.8 GHz OS 10.13, L10.0.1, M4L.
MacStudio M1Max 32Go OS 12.3.1

Clint Goss
Posts: 72
Joined: Mon Nov 06, 2023 12:03 pm

Re: Sending Raw MIDI

Post by Clint Goss » Thu Jul 25, 2024 4:52 pm

Major drawback to my scheme (and the whole use of the [seq] Max4Live object): Ableton's [Collect and Save] process does not pick up the .txt file associated with each M4L device.

This means that I cannot safely store my patch objects in my User Library, since the [Collect and Save] (which I need on each transfer from workstation to Push 3S) brings over only the .amxd file, not the associated .txt file.

Sigh.

chapelier fou
Posts: 6258
Joined: Mon May 15, 2006 12:15 pm

Re: Sending Raw MIDI

Post by chapelier fou » Thu Jul 25, 2024 6:14 pm

You could for instance use the [coll] object to store the data, with « store contents in patcher » enabled in the inspector. Sorry, no computer here for a few days.
MacBook Pro 13" Retina i7 2.8 GHz OS 10.13, L10.0.1, M4L.
MacStudio M1Max 32Go OS 12.3.1

Post Reply