Skip to content

Instantly share code, notes, and snippets.

@rbnpi
Created December 24, 2017 10:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbnpi/ba302fb6c4fa1036cc2b31a456b30649 to your computer and use it in GitHub Desktop.
Save rbnpi/ba302fb6c4fa1036cc2b31a456b30649 to your computer and use it in GitHub Desktop.
A visualisation of a four part round of Frere Jaques played by Sonic Pi 3 and a processing sketch, linked by OSC messages. They should both be run on the same computer. A video of the project is at https://youtu.be/w89G0dN2BM0
//Processing sketch to display Frere Jacques
//4 part round played in Sonic Pi 3
//control via OSC messages sent from Sonic Pi
//written by Robin Newman december 23rd 2017
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemotelocation;
//declare variables
int[] circle_colora = new int[3];
int[] circle_colorb = new int[3];
int[] circle_colorc = new int[3];
int[] circle_colord = new int[3];
float rada,radb,radc,radd;
int na,nb,nc,nd;
int chana,chanb,chanc,chand;
void setup() {
size(400,400);
frameRate(30);
oscP5 = new OscP5(this,8000); //set up osc connection, localhost port 8000
}
void draw() {
smooth();
background(0);
//set fill colour and draw ellipse for each part (channel)
fill(circle_colora[0],circle_colora[1],circle_colora[2]);
ellipse(200+chana*9,388-na,20*rada*2,20*rada*2);
fill(circle_colorb[0],circle_colorb[1],circle_colorb[2]);
ellipse(200+chanb*9,388-nb,20*radb*2,20*radb*2);
fill(circle_colorc[0],circle_colorc[1],circle_colorc[2]);
ellipse(200+chanc*9,388-nc,20*radc*2,20*radc*2);
fill(circle_colord[0],circle_colord[1],circle_colord[2]);
ellipse(200+chand*9,388-nd,20*radd*2,20*radd*2);
}
void mousePressed(){
}
void oscEvent(OscMessage theOscMessage){
if (theOscMessage.checkAddrPattern("/na")==true) //deal with osc "/na"
{
na = theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/colora")==true) //deal with osc "/colora"
{
circle_colora[0]= theOscMessage.get(0).intValue();
circle_colora[1]= theOscMessage.get(1).intValue();
circle_colora[2]= theOscMessage.get(2).intValue();
}
if (theOscMessage.checkAddrPattern("/rada")==true) //deal with osc "/rada"
{
rada= theOscMessage.get(0).floatValue();
}
if (theOscMessage.checkAddrPattern("/chana")==true) //deal with osc "/chana"
{
chana= theOscMessage.get(0).intValue();
}
//repeat osc parsing for channesl b,c and d
if (theOscMessage.checkAddrPattern("/nb")==true)
{
nb = theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/colorb")==true)
{
circle_colorb[0]= theOscMessage.get(0).intValue();
circle_colorb[1]= theOscMessage.get(1).intValue();
circle_colorb[2]= theOscMessage.get(2).intValue();
}
if (theOscMessage.checkAddrPattern("/radb")==true)
{
radb= theOscMessage.get(0).floatValue();
}
if (theOscMessage.checkAddrPattern("/chanb")==true)
{
chanb= theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/nc")==true)
{
nc = theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/colorc")==true)
{
circle_colorc[0]= theOscMessage.get(0).intValue();
circle_colorc[1]= theOscMessage.get(1).intValue();
circle_colorc[2]= theOscMessage.get(2).intValue();
}
if (theOscMessage.checkAddrPattern("/radc")==true)
{
radc= theOscMessage.get(0).floatValue();
}
if (theOscMessage.checkAddrPattern("/chanc")==true)
{
chanc= theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/nd")==true)
{
nd = theOscMessage.get(0).intValue();
}
if (theOscMessage.checkAddrPattern("/colord")==true)
{
circle_colord[0]= theOscMessage.get(0).intValue();
circle_colord[1]= theOscMessage.get(1).intValue();
circle_colord[2]= theOscMessage.get(2).intValue();
}
if (theOscMessage.checkAddrPattern("/radd")==true)
{
radd= theOscMessage.get(0).floatValue();
}
if (theOscMessage.checkAddrPattern("/chand")==true)
{
chand= theOscMessage.get(0).intValue();
}
}
#Frere jaques with visualization in Processing
#written by Robin Newman, December 23rd 2017
#info from Sonic Pi transmitted in OSC messages to drive the processing sketch
#A 4 part round is played, and each part is represented by a separate column
#the colour of each part varies with pitch as does the vertical postion of each note
#The radius of each "note" depends on its duration.
nmax=2 #number of iterations of Frère Jaques played
use_osc_logging true
#note and duration data for Frère Jaques
nf=[:c4,:d4,:e4,:c4]*2+[:e4,:f4,:g4]*2+[:g4,:a4,:g4,:f4,:e4,:c4]*2+[:c4,:g3,:c4]*2
df=[1,1,1,1,1,1,1,1,1,1,2,1,1,2,0.5,0.5,0.5,0.5,1,1,0.5,0.5,0.5,0.5,1,1,1,1,2,1,1,2]
use_bpm 180
with_fx :reverb,room: 0.8,mix: 0.6 do #add reverb for interest
use_osc "localhost",8000 #link to processing sketch on same machine. Can be on external machine too
live_loop :notes do #first part
use_synth :pulse #differnt synth for each part
use_bpm 180
nv = nf.ring.tick #select each note in turn
rel=df.ring.look #select corresponding duration
play nv,release: rel,amp: 0.2 #play note with release set by duration
osc "/chana",-18 #send channel position
osc "/na",(note(nv)-48)*16 #send scaled note info to set vertical pos
osc "/rada",rel.to_f #send rel value to set radius
osc "/colora",128,(note(nv)-48)*16,0 #send colour info related to pitch
sleep df.ring.look #sleep for durtation of note
stop if look >= (df.length*nmax-1)
end
#subesequent parts identical apart from synth, channel, color setting
live_loop :notes2,delay: 8 do #secnd part delayed 8 beats
use_synth :tri
use_bpm 180
nv = nf.ring.tick
rel=df.ring.look
play nv,release: rel,amp: 0.2
osc "/chanb",-6
osc "/nb",(note(nv)-48)*16
osc "/radb",rel.to_f
osc "/colorb",0,128,(note(nv)-48)*16
sleep df.ring.look
stop if look >= (df.length*nmax-1)
end
live_loop :notes3,delay: 16 do #third part delayed 16 beats
use_synth :prophet
use_bpm 180
nv = nf.ring.tick
rel=df.ring.look
play nv,release: rel,amp: 0.2
osc "/chanc",6
osc "/nc",(note(nv)-48)*16
osc "/radc",rel.to_f
osc "/colorc",(note(nv)-48)*16,0,128
sleep df.ring.look
stop if look >= (df.length*nmax-1)
end
live_loop :notes4,delay: 24 do #fourth part delayed 24 beats
use_synth :saw
use_bpm 180
nv = nf.ring.tick
rel=df.ring.look
play nv,release: rel,amp: 0.2
osc "/chand",18
osc "/nd",(note(nv)-48)*16
osc "/radd",rel.to_f
osc "/colord",(note(nv)-48)*16,128,0
sleep df.ring.look
stop if look >= (df.length*nmax-1)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment