Skip to content

Instantly share code, notes, and snippets.

@rbnpi
Last active August 11, 2017 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbnpi/5ec34a5fda41da67caf1c850ce96efb7 to your computer and use it in GitHub Desktop.
Save rbnpi/5ec34a5fda41da67caf1c850ce96efb7 to your computer and use it in GitHub Desktop.
Sonic PI3 drives a pi-topPULSE display, using an intermediary python oscserver to receive and process OSC messages. Full article at https://rbnrpi.wordpress.com/pi-toppulse-controlled-by-sonic-pi-3/ and video at https://youtu.be/z6Ykx2lI2Dk
#oscserver to communicate with Sonic Pi
#messages received control the leds on an attached pi-topPULSE
#run with: python3 oscserver.py
#or to use with a remote Sonic Pi computer use ip address of THIS PI
#instead of "localhost" 127.0.0.1 eg:
#python3 oscserver.py --ip <ip-address-of-his-raspberry-pi>
import argparse
from time import sleep
from ptpulse import ledmatrix
from pythonosc import dispatcher
from pythonosc import osc_server
delta = 0.04 #timing correction for RPi3 to sync leds and sound with PULSE
def handle_led(unused_addr,args, x,y,r,g,b):
sleep(delta)
print("Set Pixel",x,y,"to",r,g,b)
ledmatrix.set_pixel(x,y,r,g,b)
ledmatrix.show()
def handle_clear(unused_addr):
sleep(delta)
print("Clearing Leds")
ledmatrix.off()
def handle_setall(unused_addr,args, r,g,b):
sleep(delta)
print("Set All Leds",r,g,b)
ledmatrix.set_all(r,g,b)
ledmatrix.show()
def handle_bright(unused_addr,args, b):
sleep(delta)
print("Set Brightness %4.2f" % (b)) #adjust to 2 decimal places
ledmatrix.brightness(b)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip",
default="127.0.0.1", help="The ip to listen on")
parser.add_argument("--port",
type=int, default=8000, help="The port to listen on")
args = parser.parse_args()
dispatcher = dispatcher.Dispatcher()
dispatcher.map("/pulse/xyrgb",handle_led,"x","y","r","g","b")
dispatcher.map("/pulse/clear",handle_clear)
dispatcher.map("/pulse/setall",handle_setall,"r","g","b")
dispatcher.map("/pulse/bright",handle_bright,"b")
server = osc_server.ThreadingOSCUDPServer(
(args.ip, args.port), dispatcher)
print("Serving on {}".format(server.server_address))
server.serve_forever()
#Sonic Pi3 PULSE-leds workout by Robin Newman, August 2017
#requires the python script osc-server.py to be running to communicate with PULSE-leds
#This requires the python library python-osc to be loaded
#Which can be done with the command: sudo pip3 install python-osc
#Then run the server with python3 oscserver.py
#Finally start this program running in Sonic Pi3
#Each vertical column of LEDS corresponds to notes with a different synth
#The higher the pitch of the note, the higher up the column is the illuminated LED
#Every so often the LEDS are "cleared" to a different background colour
#The LEDs are controlled by the oscserver program, which receives OSC commands
#sent from Sonic Pi to tell it what to do.
#There are four such commands
#"/pulse/clear" which clear leds to current RGB colour
#"/pulse/xyrgb" which sends x,y and r,g,b values
#"/pulse/setall" which sets all LEDs to the r,g,b values specified
#"/pulse/bright" which sends the brightness value b to be used.
#All of these are sent to "localhost" at port 8000 which is where the python oscserver is listening
use_osc_logging true #show osc messages in the log
use_random_seed 2017 #change for different patterns
use_osc "localhost",8000
#use_real_time
osc "/pulse/clear"
sleep 0.004 #make sure LEDs cleared
load_sample :drum_bass_hard
load_sample :drum_snare_hard
load_sample :drum_cymbal_closed
set :stopflag, false
at [0,20,40,60],[1.0,0.5,0.25,0.125] do |delay|
set :t,delay
end
at 85 do
set :stopflag, true
end
live_loop :pulse do
#use_real_time
r=rrand_i(40,255)
g=rrand_i(40,255)
b=rrand_i(40,255)
a=(r+g+b)/200 - 1 #nb integer division here
bright=[0.6,0.8,1][a]
osc "/pulse/bright",bright
sleep 0.004 #make sure brightness sent first
x=rand_i(7);y=rand_i(7)
use_synth [:saw,:tri,:mod_pulse,:piano,:prophet,:pulse,:pluck][x]
tick
play 48+y*2,amp: (a+1).to_f/3,release: get(:t) if look%20!=0 or look == 0
osc "/pulse/xyrgb",x,y,r,g,b if look%20!=0 or look == 0
osc "/pulse/setall",r,g,b if look%20==0 and look > 0
sleep get(:t)-0.004 #compensate for brighness delay
osc "/pulse/clear" if look%80 == 0 and look > 0
if get(:stopflag) == true
osc "/pulse/clear"
cue :endphase #cue lastnotes and LED phase
stop #this live_loop
end
end
set :bass_rhythm, ring(9, 0, 9, 0, 0, 0, 0, 0, 9, 0, 0, 3, 0, 0, 0, 0)
set :snare_rhythm, ring(0, 0, 0, 0, 9, 0, 0, 2, 0, 1, 0, 0, 9, 0, 0, 1)
set :hat_rhythm, ring(5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0)
live_loop :drums, auto_sync: :pulse do
#use_real_time
sf = 0.05
sample :drum_bass_hard, amp: sf*get(:bass_rhythm).tick
sample :drum_snare_hard, amp: sf*get(:snare_rhythm).look
sample :drum_cymbal_closed,amp: sf*get(:hat_rhythm).look
tval= get(:t)
#puts tval
if tval <0.3
sleep tval
elsif tval <= 0.5
sleep tval/2
else
sleep tval/4
end
stop if get(:stopflag) == true #this liveloop
end
live_loop :lastnotes ,sync: :endphase do
#use_real_time
use_synth :pulse
n=scale(:c4,:minor_pentatonic,num_octaves:3).tick
if look<32
play n,release: 0.1
sleep 0.1
else
play [72,84,89,96],sustain: 1.8,release:0.1
sleep 1.9
end
stop if look==32 #this live look
end
#This section fades the LEDs up and down several times before
#leaving them all white for the final chord
#They fade out and are blanked when the music ends
sync :endphase
osc "/pulse/bright",1 #set full brightness
osc"/pulse/clear"
10.times do |x|
v=(255*x/10).to_i
osc "/pulse/setall",0,v,0
sleep 0.05
end
2.times do
10.times do |x|
v=(255*(x+1)/10).to_i
osc "/pulse/setall",v,255-v,v
sleep 0.05
end
10.times do |x|
v=(255*(9-x)/10).to_i
osc "/pulse/setall",v,255-v,v
sleep 0.05
end
end
10.times do |x|
v=(255*x/10).to_i
osc "/pulse/setall",0,255-v,0
sleep 0.05
end
osc "/pulse/setall",255,255,255 #set all white
sleep 2
100.times do |x|
osc "/pulse/bright",(99-x).to_f/100
sleep 0.01
osc "/pulse/setall",255,255,255
sleep 0.01
end
osc "/pulse/clear" #clear all LEDs
puts "FINISHED!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment