Help with Infinite Loop Sending OSC and MIDI Program Change

Hi everyone,

I’m a beginner and I’m trying to write my first SuperCollider code for an audio installation.

My goal is to create an infinite loop that performs the following simple actions:

  • Send three control messages at the same time:
    • An OSC command to REAPER (e.g., jump to marker)
    • An OSC command to SPAT Revolution (e.g., recall snapshot)
    • A MIDI Program Change to a digital mixer (e.g., recall cue)
  • Then wait for 1 minute
  • Then send the same three messages again, but with different marker / snapshot / cue
  • Then wait for another 1 minute
  • Then loop back and repeat this cycle forever

I was able to send the OSC command with this line:

NetAddr("127.0.0.1", 8001).sendMsg("/snapshot/4/recall");

But I haven’t been able to send the MIDI Program Change…

Could anyone help me figure out how to do that?

Thanks a lot!

Ciao!
Mauro

See the MIDIOut class. It has a program method to send program change messages.

If it’s macOS, you’d need an IAC MIDI bus. In Windows, loopMIDI. In Linux, SC uses ALSA MIDI while Reaper uses JACK MIDI, so you’d need to go through a MIDI bridge port (which I’ve done before but I forget the exact name).

hjh

1 Like

Thanks a lot, hjh!

I think I got it working!
It seems to be running fine.

Here’s the code:

// Initialize MIDI
MIDIClient.init;
MIDIClient.destinations.postln;

// Create MIDIOut object
d = MIDIOut(2);  // or: MIDIOut.newByName("Rete", "IS2");

// Define NetAddr for OSC
s = NetAddr("127.0.0.1", 8001);  // SPAT
r = NetAddr("127.0.0.1", 8002);  // REAPER

(
Routine({
    loop {
        s.sendMsg("/snapshot/4/recall");
        r.sendMsg("/marker/1");
        d.program(0, 1);
        "Program Change 1 sent on IS2".postln;

        "Minuto 1".postln;
        6.wait;

        r.sendMsg("/marker/2");
        d.program(0, 2);
        "Program Change 2 sent on IS2".postln;

        "Minuto 2".postln;
        6.wait;

        r.sendMsg("/marker/3");
        d.program(0, 3);
        "Program Change 3 sent on IS2".postln;

        "Minuto 3".postln;
        6.wait;

        r.sendMsg("/marker/4");
        s.sendMsg("/snapshot/1/recall");
        d.program(0, 1);
        "Program Change 1 sent on IS2".postln;

        "Minuto 4".postln;
        6.wait;

        s.sendMsg("/snapshot/2/recall");
        d.program(0, 2);
        "Program Change 2 sent on IS2".postln;

        "Minuto 5".postln;
        6.wait;

        s.sendMsg("/snapshot/3/recall");
        d.program(0, 3);
        "Program Change 3 sent on IS2".postln;

        "Minuto 6".postln;
        6.wait;
    }
}).play;
)

Now I’ll test it in the real setup:

  • one computer will run the code,
  • it will control a second computer on the local network, running Reaper and SPAT (I’ll obviously need to set the correct IP addresses),
  • it will control a remote MIDI interface (mioXM — iConnectivity) via VPN, which will receive Program Change messages over RTP-MIDI - intended for a digital mixer that will switch CUEs accordingly.

Thanks again for the support.

Ciao!

Mauro