Once more I have to confess, that it has been a while since I had time to work in both programs (SC and Processing) at the same time. In the last months it was more of an either Supercollider or Processing – with definitely less time for the latter.
But… with no wind around the corner —no fun recording trees— the “only” thing left to do was putting together what I have learned during the last weeks. Well, of course not all the topics I have been pondering about, but at least fixing the communication problem between SC and Processing; here especially stopping the sound upon closing the sketch, as well as some minor code optimisations.
Sometimes I can only wonder — same code, some time later and it magically works?!
First insight: next to freeing the synths at the end in the function ‘void exit()’, the command ‘super.exit()’ seems to put an end to the synths; somehow freeing the nodes in Supercollider. I have also added a second sound to the sketch. Hitting the sides, SC executes the synth “Crash” via ‘t_trig’ — the magical code to send the trigger from outside to SC, neatly executing the EnvGen. The panning receives its values like in the last example (floating rectangles) easily through the ‘map’ function.
The movement of the ball is coded in the seemingly, slightly clumsy, but in my eyes still smart act of a makeshift: “adding steps or points (/pixels) to the x and y position”. The fancy and somewhat more elegant way would of course be to use the “PVector’ classes, which were also already introduced in the earlier example.
A topic I am still somewhat struggling with is the whole concept around ‘OscMessages’. Since my knowledge about OSC messages and Java is still in its children shoes so to say, the examples in the reference for both libraries (oscP5 and netP5) have not yet revealed their practical use to me. The examples work fine without implicitly creating objects or either oscP5 or netP5, however, explicitly naming the default ports prevents ‘oscEvent: /fail’ messages displayed after the established connection.
The next topic on my list are OSC and of course server messages in and around SC; so I’ll try to cover and test the communication between both programmes with help of server messages at last. Until then, object messaging does the job perfectly well so far. I have not hit any bigger obstacles, struggles or (ovbious) latency.
Before I list the code, a little reminder: use localhost as default server and run the sc patches first!
And here finally the code…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
/* ****************************
* *
* --- Bouncing Ball --- *
* --- feat. Theremin --- *
* --- feat. Crash --- *
* *
******************************/
/* --- IMPORT --- */
import supercollider.*;
import oscP5.*;
import netP5.*;
/* --- VARIABLES --- */
int ballSize = 20; // ball size
float x = random(ballSize, width-ballSize); // ball position x
float y = random(ballSize, height-ballSize); // ball position y
float minBallSize = ballSize * 0.5; // ...hitting the sides
int colBlue = int(random(80)); // colour changes
int colGreen = int(random(200)); // colour changes
int colRed = int(random(255)); // colour changes
float spdX = 4.0; // speed x
float spdY = 5.0; // speed y
int dirX = 1; // direction x
int dirY = 1; // direction y
Synth therem, crash; // synths
OscP5 oscP5; // holding the bundles for osc messages
NetAddress myRemoteLocation; // netaddress
/* --- SETUP & INITIATE --- */
void setup(){
size(400,400);
smooth();
background(0);
noStroke();
frameRate(24);
// initiate values for the synths:
therem = new Synth("Theremin");
therem.set("amp", 0.3);
therem.set("freq", 240+y);
therem.set("mod", 7);
therem.set("pan", 0);
therem.create();
crash = new Synth("Crash");
crash.set("t_trig", 0);
crash.set("panPos", x);
crash.set("ampCr", 2.2);
crash.create();
// communication processing & sc
oscP5 = new OscP5(this,12000); // processing port
myRemoteLocation = new NetAddress("127.0.0.1", 57110); // sc default port address
}
/* --- DRAW --- */
void draw(){
background(0);
fill(colRed, colGreen, colBlue);
ellipse(x, y, ballSize, ballSize);
x+=spdX * dirX;
y+=spdY * dirY;
therem.set("freq", y+240);
//hitting sides
if(x+minBallSize>=width || x<minBallSize){
dirX*= (-1);
colBlue = int(random(100));
spdX = random(3.5,8.5);
crash.set("t_trig", 1);
therem.set("mod", random(2,15));
};
if(y+minBallSize>=height || y<minBallSize){
dirY*= (-1);
colRed = int(random(255));
spdY = random(4.4,9.8);
crash.set("t_trig", 1);
therem.set("mod", random(2,15));
};
// panning
if(abs(x)<= width/2){
therem.set("pan", map(x, 0, width/2, -1, 0));
crash.set("panPos", map(x, 0, width/2, -1, 0));
}
else if(abs(x)>= (width/2)+1){
therem.set("pan", map(x, (width/2)+1, width, 0, 1));
crash.set("panPos", map(x, (width/2)+1, width, 0, 1));
};
}
// on pressing 'esc'
void exit(){
therem.free();
crash.free();
super.exit();
} |
The SynthDefs…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /* ****************************************************
* *
* --- Theremin adapted from SC Book examples --- *
* *
* ****************************************************/
/*
(
SynthDef(\Theremin, {
arg out = 0, mod = 7, freq=240, amp=0.5, pan=0;
var sig, panning;
sig = SinOsc.ar(freq + (freq * SinOsc.ar(mod,0,0.05)), mul: 0.5);
sig = Mix.ar(sig);
panning = Pan2.ar(sig, pan, amp);
Out.ar(out, panning);
}).add
)
// testing:
a = Synth(\Theremin);
a.set(\mod, 12);
a.free;
*/
/* ***************************************
* *
* --- Crash (hitting the sides) --- *
* *
* ***************************************/
/*
(
SynthDef(\Crash,{
arg out=0, t_trig=0, ampCr=0.5, panPos=0.1;
var noise, envp, sig, pan, pitchBPF, steepBPF;
pitchBPF = 613.641;
steepBPF = 1.11644;
noise = LFNoise0.ar(763.293, 0.25);
envp = EnvGen.kr(Env.perc(0.01,0.2,0.4,-4), t_trig, doneAction:0);
sig = BPF.ar(noise * envp, pitchBPF, steepBPF, 2.0);
pan = Pan2.ar(CombN.ar(sig, 0.01,0.4, 2.3), panPos, ampCr);
Out.ar(out, pan);
}).add;
)
// testing
x = Synth(\Crash, [\t_trig, 1]);
x.free;
*/ |
Or download the pde.
Comments, suggestions, further/other explanations or hints are of course and always most welcome!
Similar Posts:
- Floating Squares
- A Theremin and a Bouncing Ball
- Musical Shapes in Processing
- SuperCollider & Processing

