SuperCollider/Processing Interaction, OSC messages from Pbind? (Complicated Question [for me])


#1

I’m trying to get SuperCollider to control animations in Processing 3 through OSC. Whenever a certain frequency is played from a synth, a shape appears in the Processing window, but when the frequency is not being played, the shape does not appear on the screen. The frequency would be controlling the color value of the shapes. For example, if a frequency of 220 is played, the color value will be 255. I’m wondering if I could send the frequencies from my Pbind as floating point number OSC messages to Processing 3 to control the animations? I’d really appreciate any help. I have found a useful example. Here’s code from the example I found, then below that is my code:

SuperCollider:

n = NetAddr("127.0.0.1", 47120);  // open 47120 on localhost server

(
SynthDef(\blip, { | freq = 440, amp = 0.85, att = 0.01, rel = 0.06, ffreq = 1000 |
    var sig, env, lfo;
    sig = SinOsc.ar(freq.asFloat, 0, amp);
    env = EnvGen.ar(Env.perc(att, rel), doneAction:2);
    lfo = SinOsc.kr(rel * ffreq);

    Out.ar(0, Pan2.ar(RHPF.ar(sig*env, ffreq), SinOsc.kr(211*lfo)))
}).play;
)

Synth(\blip);

(
f = fork {
    loop {
        256 do: { arg i;
            n.sendMsg("/sc3p5", i.asFloat); // send OSC message to P5
            Synth(\blip, [\freq, 440+i, \ffreq, 1000+i*2]);
            ((i+1).reciprocal*2).wait;
        }
    }
};
)

Processing:

import oscP5.*;
import netP5.*;
OscP5 oscP5;

float x; // global variable

void setup() {
  size(400, 300);
  frameRate(24);
  background(0);
  smooth();

  OscProperties properties = new OscProperties();
  properties.setListeningPort(47120); // osc receive port (from sc)
  oscP5 = new OscP5(this, properties);
}

void oscEvent(OscMessage msg) {
  if (msg.checkAddrPattern("/sc3p5")) {
    x = msg.get(0).floatValue(); // receive floats from sc
  }
}

void draw() {
  background(x, x, 0);
  println("POST: ", x);
  // draw rect
  stroke(256-x/2, 256-x*abs(sin(x)), 256-x/4);
  strokeWeight(4);
  fill(256-x/2, 256-x, 256-x*abs(sin(x)));
  translate(width/2, height/2);
  rotate(x%64);
  rect(x%64, x%64, x*abs(sin(x))%128, x*abs(sin(x))%128, 6);
}

The code I have:
SuperCollider:

n = NetAddr("127.0.0.1", 47120);  // open 47120 on localhost server


(
SynthDef.new(\synth, {
	arg freq, kbs;
	var env, sig;
	env = EnvGen.kr(Env([0,1,0], [0.01, 0.5]), doneAction:2);
	sig = Saw.ar(freq, 0.25)*env;
	Out.ar(0, sig.dup);
}).add;
)


(
    Pbind(
	\instrument, \synth,
    \freq, Pseq([220.00, 329.63, 523.25, 329.63, 523.25, 329.63, 146.83, 220.00, 349.23, 220.00, 349.23, 220.00, 174.71, 261.63, 440.00, 261.63, 440.00, 261.63].asFloat, inf),
	\dur, Pseq([1/8], inf),
	\stretch, 1.5,
	\out, 0,
).play;
)

Processing:

import oscP5.*;
import netP5.*;
OscP5 oscP5;

float color1 = 0.0;
float color2 = 0.0;
float color3 = 0.0;
float color4 = 0.0;
float color5 = 0.0;

void setup() {
  size(400, 300);
  frameRate(24);
  background(0);
  smooth();

  OscProperties properties = new OscProperties();
  properties.setListeningPort(47120); // osc receive port (from sc)
  oscP5 = new OscP5(this, properties);
}

void oscEvent(OscMessage msg) {
  if (msg.checkAddrPattern("/sc3p5")) {
    color1 = msg.get(0).floatValue(); // receive floats from sc
  }
    if (msg.checkAddrPattern("/sc3p5")) {
    color2 = msg.get(0).floatValue(); // receive floats from sc
  }
    if (msg.checkAddrPattern("/sc3p5")) {
    color3 = msg.get(0).floatValue(); // receive floats from sc
  }
    if (msg.checkAddrPattern("/sc3p5")) {
    color4 = msg.get(0).floatValue(); // receive floats from sc
  }
    if (msg.checkAddrPattern("/sc3p5")) {
    color5 = msg.get(0).floatValue(); // receive floats from sc
  }
}

void draw() {
    stroke(0, 255, 0);
    fill(color1);
    triangle(0, 0, 0, 50, 50,0); 
    stroke(0, 255, 0); 
    fill(color2); 
    triangle(0, 50, 50, 0, 50, 50); 
    stroke(0, 255, 0);
    fill(color3); 
    triangle(50, 0, 50, 50, 100, 0); 
    stroke(0, 255, 0); 
    fill(color4); 
    triangle(50, 50, 100, 0, 100, 50);
    stroke(0, 255, 0);
    fill(color5);
    triangle(100, 50, 100, 0, 150, 0); 
}

#2

Hi,

You are almost there. Can’t tell aboout Processing, but in Pbind you need something like

Pbind(
	\dur, ... ,
	\freq, ... ,
	
	// take over frequency
	\bla, Pfunc { |e| n.sendMsg(... , e[\freq] ) },
	
	...
	
	// maybe you want to send silenty, then do
	\type, \rest
).play

Daniel


#3

Hi, thanks for the help!

In the Pfunc, what do I put after the “n.sendMsg(” ?

You put an ellipses(…) there


#4

Well, you posted in your example


#5

Do I put the frequencies there?

(
    Pbind(
	\instrument, \synth,
    \freq, Pseq([220.00, 329.63, 523.25, 329.63, 523.25, 329.63, 146.83, 220.00, 349.23, 220.00, 349.23, 220.00, 174.71, 261.63, 440.00, 261.63, 440.00, 261.63], inf),
	// take over frequency
	\bla, Pfunc { |e| n.sendMsg(220.00, 329.63, 523.25, 329.63, 523.25, 329.63, 146.83, 220.00, 349.23, 220.00, 349.23, 220.00, 174.71, 261.63, 440.00, 261.63, 440.00, 261.63 , e[\freq] ) },
	// maybe you want to send silenty, then do
	\type, \rest
	\dur, Pseq([1/8], inf),
	\stretch, 1.5,
	\out, 0,
).play;
)

#6

To quote your own post :wink: just put the OSC message you want to send where the … appears.


#7

The Pfunc at the \bla key in your Pbind provides an argument which is the Event that’s composed within each iteration. As \freq is evaluated before \bla the Event already holds the new value for \freq:
\bla, Pfunc { |e| n.sendMsg(e[\freq]) }
Hope that makes sense…