10. Introduction to OSC

Overview

Open Sound Control, frequently referred to simply as OSC, is a communication protocol for sending information across a computer network of some sort. OSC is an incredibly important component of SC, as SC is comprised of two separate applications (sc-synth and sc-language) that communicate with each other over OSC via your computer's internal network. Fortunately one can communicate via OSC with any other computer on the same WIFI network provided we know that computer's IP Address. What follows is a brief example of sending a message from one computer to another followed by a quick sound making example.


OSCdef

Intro

To receive messages via OSC one typically uses one of two UGens in SC: OSCdef or OSCfunc. Note that the structure in SC that we looked at extensively last week, the SynthDef, has a similar ending to OSCdef. In both cases def is short for definition and refers to the ability to reference the Synth, or OSC, objects by name. This naming feature is an important tool for our organizational purposes so I strongly urge you to focus on OSCdef for all message receiving purposes over a network.

Format

OSCdef(\sine, { | msg, time, addr, recvPort|

    msg.postln;

    }, '/sin');

Above is the basic format for an OSCdef. Note the following:

  • Similar to a SynthDef, the first important piece of information we need to give to SC is the name of this OSCdef, which must be prepended with a \. In this example the name, or definition on the server, of the OSCdef is \sine
  • The name of the OSCdef is followed by a comma and then a function block (remember, anything between {...} is a function and we often refer to a complete function as a block) which defines what this particular OSCdef does when it receives a message. This structure still closely resembles the structure of a SynthDef.
  • Next we define arguments between bars. The argument to focus on here is msg, the others you probably will not need to actively use.
  • Currently the only thing that happens in the function block is a .postln statement. In other words, all this OSCdef does currently is display whatever message it received in the post window.
  • Finally we have the path, a symbol that defines the label for this particular message. Here our OSCdef will only respond to messages that begin with '/sin'. Note that the path contains both single quotes and a /.


NetAddr

Format

~x = NetAddr([IPADDRESS], 57120);
~x.sendMsg('/sin', '/play');

In the above example I define a NetAddr, or a destination computer on the network, and then send a message to it. Note that the values in parens are both strings prepended with a /. As we have it above, the full message will be: /sin/play.


Simple Network Communication

Get into groups of 2 for the next demos.

Demo 1: General Message Communication

// receives the message
OSCdef(\hello, { | msg, time, addr, recvPort|

    msg.postln;

    }, '/greeting');

// sends the message
~x = NetAddr([IP ADDRESS], 57120);

// try this one first
~x.sendMsg('/greeting', "hello");

// then try this one

~x.sendMsg('/greeting', '/hello');

// and finally this one (multiple times)

~x.sendMsg('/greeting', { rrand(20, 50).asFloat }.value);

Demo 2: Sound Control Over the Network

Receiver Example Code

// setup

s.boot;


// the example synth that will be controlled. note the standardized arguments: amp, freq, trig

SynthDef( \sin, { | amp = 0.0, freq = 440, out = 0, trig = 0 |
    var env, sig, finalSig;
    env = EnvGen.kr( Env.asr( 0.001, 0.9, 0.001 ), trig, doneAction: 0 );
    sig = SinOsc.ar( freq, 0.0, amp );
    finalSig = sig * env * 0.6;
    Out.ar( out, Pan2.ar(finalSig) );
}).add;


// run the synth (note that the envelope is still set to 0 so we hear nothing

~x = Synth( \sin, [ \freq, 400, \amp, 0.5]);


// receive messages from another computer to change Synth at ~x

OSCdef(\sinResponder, { | msg |

    msg.postln;

    switch( msg[1],
        '/play', {
            "play sin".postln;
            ~x.set(\trig, 1);
        },
        '/run', {
            ~x = Synth( \sin, [ \freq, 400, \amp, 0.5]);
        },
        '/stop', {
            "stop sin".postln;
            ~x.set(\trig, 0);
        },
        '/vol', {
            "vol"++msg[2].postln;
            ~x.set(\amp, msg[2].asFloat );
        });
}, '/sin');

Sender Example Code

s.boot;

/*

step 1: get the other computer's IP Address,
store it in a global variable (FYI these are
technically called Environment Variables in SC)

*/
~ip = "";

// pass the IP to a Net Address Object, store it to the variable ~x

~x = NetAddr(~ip, 57120);

// sending messages

~x.sendMsg('/sin', '/run');


// turn the other computer's sin on

~x.sendMsg('/sin', '/play');


// turn the other computer's sin off

~x.sendMsg('/sin', '/stop');


// change the other computer's sin's volume (try different numbers between 0.0 and 1.0)

~x.sendMsg('/sin', '/vol', 0.1 );