Something wrong using">="? nilclass?


p3 is an auto-refresh value that comes from a sonar attached to RPI.GPIO,anything wrong?

Hi there,

it looks like the current value of p3 is nil. Could you share the code where that is set?

# Sonic Pi init file
# Code in here will be evaluated on launch.

live_loop:listen do
  n1=sync "/osc/play_this1"
  n2=sync "/osc/play_this2"
  n3=sync "/osc/play_this3"
  p1=n1[0]
  p2=n2[0]
  p3=n3[0]
  '-----------------------'
  use_synth :beep
  if p1<=11 then
    play :C4
    sleep(0.1)
  elsif p1<21 then
    play :D4
    sleep(0.1)
  elsif p1<31 then
    play :E4
    sleep(0.1)
  elsif p1<41 then
    play :F4
    sleep(0.1)
  elsif p1<51 then
    play :G4
    sleep(0.1)
  end
  
  '-----------------------'
  use_synth :chipbass
  if p2<=11 then
    play :C4
    sleep(0.1)
  elsif p2<21 then
    play :D4
    sleep(0.1)
  elsif p2<31 then
    play :E4
    sleep(0.1)
  elsif p2<41 then
    play :F4
    sleep(0.1)
  elsif p2<51 then
    play :G4
    sleep(0.1)
  end
  '------------------'
  use_synth :piano
  if p3<=11 then
    play :C4
    sleep(0.1)
  elsif p3<21 then
    play :D4
    sleep(0.1)
  elsif p3<31 then
    play :E4
    sleep(0.1)
  elsif p3<41 then
    play :F4
    sleep(0.1)
  elsif p3<51 then
    play :G4
    sleep(0.1)
  end
end
    `

> indent preformatted text by 4 spaces

`

THANKS A LOT IF YOU COULD ALSO SEE OUR PYTHON CODE!!!

from time import sleep
from pythonosc import osc_message_builder
from pythonosc import udp_client
import RPi.GPIO as GPIO
import time

sender = udp_client.SimpleUDPClient(‘127.0.0.1’,4559)

def checkdist(trigger,echo):
GPIO.setmode(GPIO.BCM)
GPIO.setup(trigger,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(echo,GPIO.IN)
GPIO.output(trigger,GPIO.HIGH)
time.sleep(0.00015)
GPIO.output(trigger,GPIO.LOW)
while not GPIO.input(echo):
pass
t1 = time.time()
while GPIO.input(echo):
pass
t2 = time.time()
return (t2-t1)*340/2

while True:
print(‘Distance1:%0.2f m’%checkdist(3,2))
print(‘Distance2:%0.2f m’%checkdist(17,27))
print(‘Distance3:%0.2f m’%checkdist(24,23))

time.sleep(0.1)

pitch1=round(float(‘%0.2f’%checkdist(3,2))*100)
sender.send_message(‘/play_this1’,pitch1)

pitch2=round(float(‘%0.2f’%checkdist(17,27))*100)
sender.send_message(‘/play_this2’,pitch2)

pitch3=round(float(‘%0.2f’%checkdist(24,23))*100)
sender.send_message(‘/play_this3’,pitch3)

Interesting.

What happens if you add

puts "p3: #{p3}, n3: #{n3}"

prior to the line:

if p3<=11 then

What do you see in the log?

Have you very recently installed python-osc? There is a bug in the latest release version. You need to install with

sudo pip3 install python-osc==1.6.4

Version 1.6.5 has the bug which prevents values of 1 or 0 being sent as data in an OSC message.
I think it may affect sending some floats too.
The author is aware and hopes to release 1.6.6 soon

If you have version 1.6.5 installed just uninstall using sudo pip3 uninstall python-osc and then reinstall 1.6.4

Also looking at your code I’m not sure if three syncs one after the other will work. It will wait for the n1 sync then for the n2 sync then for the n3 sync. Do you not want a separate live loop for each one, OR use a wild card and work out which message was received, as I have done using my parse_sync_address function as featured in code

Just received notification that python-osc 1.6.6 has been released, so
sudo pip3 install python-osc should be OK to use again.

1 Like

As you can see, we’re working on a DIY theremin project but we met some problem, we have an video to describe our problem…Do you have WeChat (or other IM apps) number so that we can send it to u? <3

1 Like

Hi Micki
Not sure if you only want notes a tone apart, but a more sliding sound (like a theremin) is obtained with the following code. Also, treat each input separately in its own live loop.
I simulated your inputs using three sldiers on TouchOSC, hence the slightly different OSC addresses, but try removing the /test from three addresses and see if this code works with your system

# Sonic Pi init file
# Code in here will be evaluated on launch.


live_loop:listen1 do
  use_real_time
  b=sync "/osc/test/play_this1"
  p1=b[0]
  
  '-----------------------'
  use_synth :beep
  play 60+7*p1,attack: 0.05,release: 0.15,amp: 1.5
  sleep 0.1
end

live_loop:listen2 do
  use_real_time
  b=sync "/osc/test/play_this2"
  p2=b[0]
  
  '-----------------------'
  use_synth :chipbass
  play 60+7*p2,attack: 0.05,release: 0.2
  sleep 0.1
end

live_loop:listen3 do
  use_real_time
  b=sync "/osc/test/play_this3"
  p3=b[0]
  
  '-----------------------'
  use_synth :piano
  
  play 60+7*p3,attack: 0.05,hard: 0.3,vel: 0.12,amp: 1.5
  sleep 0.1
end

Also, do you need to put this in the init.rb file rather than run it in a normal buffer?

we used to set three loops, but the sound overlaps,that’s annoying

the contents printed on python is more easier to stop refreshing,too. we couldn’t find the reason

OK. Here is another version nearer to your original which works with TouchOSC input.
Try it on your system, altering the OSC addresses by removing /test
ie
n=sync "/osc/test/play_this*"
becomes
n=sync "/osc/play_this*"
and
res = parse_sync_address "/osc/test/play_this*" becomes
res = parse_sync_address "/osc/play_this*"

# Sonic Pi init file
# Code in here will be evaluated on launch.

define:parse_sync_address do |address| #gets info on wild cards used
  v= get_event(address).to_s.split(",")[6]
  if v != nil
    return v[3..-2].split("/")
  else
    return ["error"]
  end
end

live_loop:listen do
  use_real_time
  n=sync "/osc/test/play_this*" #remove the /test for your system
  
  nv=n[0].to_i
  res = parse_sync_address  "/osc/test/play_this*" #remove the /test for your system
  p=res[2][9..-1].to_i
  puts p,nv
  case p
  when 1
    use_synth :beep
  when 2
    use_synth :chipbass
  when 3
    use_synth :piano
  end
  
  if nv<=11 then
    play :C4
    
  elsif nv<21 then
    play :D4
    
  elsif nv<31 then
    play :E4
    
  elsif nv<41 then
    play :F4
    
  elsif nv<51 then
    play :G4
    
  end
  sleep(0.1)
end

I can’t really comment on the python code without access to suitable hardware. I have one ultrasound sensor, but unfortunately I think it is damaged. However I think you said that osc messages were being sent OK.


work on RPI3 sonic-pi-3.0.1…
thanks for your patience anyway…:heart:

ACTUALLY I FORGOT TO SAY YOU WILL HAVE TO CHANGE THE LINE WITH THE ERROR TO
p=res[1][9..-1].to_i
when you alter the OSC address line and remove the /test as you want to get data from the 2nd element not the third, and they number from 0.

i set some rhymes using 1.times do in each “in_thread” replace the former pitches.
so every 0.1s it will play the rhyme…it’s bad.

i am now wondering about how to play audio in particular range of distance,and stop the audio when the distance is out of a specific number…
does it have functions such as ‘stop all the audio’?

I use two techniques to switch live_loop audio on and off. The first stops the live loop and restarts it when required. The second leaves the live_loop running but controls its volume using an fx :level wrapper.

In the first example you could use osc messages to call doloop to start and to set :go,0 to stop.

In the second example you could use osc messages to adjust the value of :vol using set :vol,0 or set :vol,1

use_bpm 120

#technique 1 use stop to stop a live loop
#the function call will restart it next time it is called
define :doLoop do
  use_synth :tb303
  set :go,1
  live_loop :doodle do
    n=scale(:c3,:minor_pentatonic,num_octaves: 2).choose
    play n, cutoff: rrand(50,110),release: 0.1 if spread(5,8).tick
    sleep 0.2
    stop if get(:go)==0
  end
end
#illustrate starting and stopping the loop 4 times
4.times do
  doLoop
  sleep 4
  set :go,0
  sleep rrand_i(1,4)
end

#technique 2
# have a continously running live loop
#and embed it within fx :level
#control the level to switch the loop audio off and on
with_fx :level,amp: 1 do |v| #could start with amp: 0 if you want the loop to start silently
  in_thread do
    loop do
      control v,amp: get(:vol),amp_slide: 0.1
      sleep 0.1
    end
  end
  use_synth :tb303
  live_loop :doodle2 do
    n=scale(:c4,:minor_pentatonic,num_octaves: 2).tick
    play n, cutoff: rrand(50,110),release: 0.1 if spread(5,8).look
    sleep 0.2
  end
end
#illustrate controlling the volumn on and off 4 times
4.times do
  set :vol,1
  sleep 4
  set :vol,0
  sleep 4
end