I could use some help please and thank you


#1

I have created a doorbell chime. Is there a way to get it to play at the press of the space key? I have seen examples of code done in Ruby that uses letters and numbers but not the space key. I’m starting to get a little confused.

Thank you for your time,

Erika Gehm


#2

Hi Erika
I think you asked this question on youtube where I posted a program to use keys to control Sonic Pi back in April 2016!! I wasn’t sure exactly what you wanted to do, but this question makes it clearer.

I have added the facility to respond to the spacebar being pushed in the program.
The line cue :space if k.to_i.chr == " "

I have also added a live_loop called :dingdong which plays a doorbell sound. This will be triggered when you press the spacebar.
This program was written a long time ago, before Sonic Pi had the facility to respond to incoming OSC messages and incoming MIDI. It wrosk, but is rather slow to respond.
There are probably better (and simpler) ways to do this now, but this will get you going.
If you already have your own doorbell sound, you can replace the contents of the live_loop :dingdong. Just make sure you include the line sync :space so that the sound is not played until the cue :space message is received.
I’ll see if I can come up with something simpler for you to post here later.
In the meantime the two files are posted below.
First the progarm that runs in Sonic Pi

## The following two sections of code are utilities to clear and load all samples used in the program
## They should be used by uncommenting when running on a Pi as required, before using the main program
## The samples are required by live loop :sampfrenzy
##| sample_free_all
##| stop
##| sample_groups.each do |g|
##|   load_samples g.to_s   if g.to_s != "loop"
##| end
##| stop


#experimental program to control Sonic Pi from the keyboard
#written by Robin Newman, April 2016
#you can play notes direct, or initiate any of 10 liveloops
#keyboard polling routine by Alex Chaffee, http://stackoverflow.com/questions/174933/how-to-get-a-single-character-without-pressing-enter
#Some of the example live_loops used here require SP version 2.10,
#but with amended examples should work on earlier versions of SP
require 'socket'
use_synth :saw #used for directly played notes
#set up hash to contain notes
notes=Hash.new
#list of notes
l=[:c4,:cs4, :d4, :ds4, :e4, :f4, :fs4, :g4, :gs4, :a4, :as4, :b4, :c5, :cs5, :d5, :ds5, :e5, :f5, :fs5,  :g5]
#list of associated keys (may have to alter depending on your keyboard layout)
n=["a", "w", "s", "e",  "d", "f",  "t", "g",  "y", "h",  "u", "j", "k",  "o", "l", "p",  ";", "'",  "]", "#"]
20.times do |i| #loop to create the hash
  notes[n[i].ord]=l[i]
end
k=0 #set initial value of k, making it a global variable

live_loop :tcp do #loop to poll tcp input
  s = TCPSocket.new 'localhost', 2016 #create socket
  k= s.gets.to_f #get input
  s.close #close =socket
  cue :p if k !=0 # if value is not 0 cue play loop
  #puts k.to_i.chr
  cue :one if k.to_i.chr == "1"
  cue :two if k.to_i.chr == "2"
  cue :three if k.to_i.chr == "3"
  cue :four if k.to_i.chr == "4"
  cue :five if k.to_i.chr == "5"
  cue :six if k.to_i.chr == "6"
  cue :seven if k.to_i.chr == "7"
  cue :eight if k.to_i.chr == "8"
  cue :nine if k.to_i.chr == "9"
  cue :zero if k.to_i.chr == "0"
  cue :space if k.to_i.chr == " "
  sleep 0.075 #short sleep before repeating
end

live_loop :x do #loop to play the notes
  sync :p #wait for sync to say note is ready
  play notes[k.to_i],sustain: 0.5,release: 0.05,amp: 0.3 if k>0 #play note, looking up value from hash
  sleep 0.05 #short sleep
end

define :pl do |tune,dur| #loop to play a tune held in a notes and a durations list
  tune.zip(dur).each do |n,d|
    play n,sustain: d*0.9,release: d*0.1
    sleep d
  end
end

live_loop :dr do #plays loop_amen_full
  sync :one
  l= (sample_duration :loop_amen_full)
  with_fx :level,amp: 1 do |v|
    control v,amp_slide: 2*l,amp: 0
    2.times do
      sample :loop_amen_full
      sleep l
    end
  end
end

live_loop :dr2 do #plays loop_tabla
  sync :two
  with_fx :level,amp: 3 do |v|
    control v,amp_slide: (sample_duration :loop_tabla),amp: 0
    sample :loop_tabla
  end
end

live_loop :melody do #plays notes using :pluck synth
  use_synth :pluck
  sync :three
  with_fx :level, amp: 1 do |v|
    control v, amp_slide: 9.6, amp: 0
    n=scale(:a1,:minor_pentatonic,num_octaves: 2)
    96.times do
      play n.choose if spread(5,8).tick
      sleep 0.1
    end
  end
end

live_loop :woosh do #plays misc_cineboom
  sync :four
  4.times do
    sample :misc_cineboom,start: 0,finish: 0.4,beat_stretch: 4
    sleep 1.6
    sample :misc_cineboom,start: 0.5,finish: 0.8, beatstretch: 4
    sleep 1.2
  end
end

live_loop :rhythm do #plays notes with :tb303
  use_synth :tb303
  sync :five
  with_fx :level, amp: 1 do |v|
    control v, amp_slide: 9.6, amp: 0
    f=  (note_range :c2, :c5, pitches: (scale :c, :minor))
    96.times do
      play f.choose,release: 0.1 if spread(5,8).tick
      play (f.choose - 12),release: 0.1 if !spread(5,8).look
      sleep 0.1
    end
  end
end

live_loop :frere do #plays frere jaques round
  sync :six
  sq=0.1
  q=2*sq
  c=2*q
  tune=[:c4,:d4,:e4,:c4]*2+[:e4,:f4,:g4]*2+[:g4,:a4,:g4,:f4,:e4,:c4]*2+[:c4,:g3,:c4]*2
  dur=[q,q,q,q,q,q,q,q,q,q,c,q,q,c,sq,sq,sq,sq,q,q,sq,sq,sq,sq,q,q,q,q,c,q,q,c]
  in_thread do
    use_synth :tri
    pl(tune,dur)
  end
  sleep 4*c
  in_thread do
    use_synth :saw
    pl(tune,dur)
  end
  sleep 4*c
  in_thread do
    use_synth :prophet
    pl(tune,dur)
  end
end

live_loop :fanfare do #plays a three chord fanfare
  sync :seven
  use_synth :tri
  ch1=[:c4,:e4,:g4,:c5]
  ch2=[:c4,:d4,:f4,:a4,:c5]
  ch3=[:e4,:g4,:c5,:g5]
  q=0.2
  c=2*q
  cd=3*q
  m=4*q
  dur=[c,q,q,q,q,cd,q,m]
  tune=[ch1,ch2,ch2,ch2,ch2,ch1,ch1,ch3]
  pl(tune,dur) #play using pl function
end

live_loop :boom do #drum roll and bass drum thump
  sync :eight
  puts sample_duration :drum_roll
  sample :drum_roll,finish: 0.32
  sleep 2
  sample :drum_bass_hard
  sleep sample_duration :drum_bass_hard
end

live_loop :slider do #slides two notes around
  sync :nine
  with_fx :level,amp: 0,amp_slide: 1 do|v|
    use_synth :tb303
    s=play :a2,sustain: 8,note_slide: 1 #start the two notes with 8 sec sustains
    r=play :a3,sustain: 8,note_slide: 1
    4.times do
      control v,amp: 1 #slide the volume up
      
      control s, note: :a3 #slide the ptiches
      control r, note: :a2
      sleep 1
      control v,amp: 0 #slide the volume down
      control s, note: :a1 #slide the ptiches
      control r, note: :a3
      sleep 1
    end
  end
end

live_loop :sampfrenzy do #plays all samples (except loops) fast
  sync :zero
  sample_groups.each do |g|
    if g !=:loop
    then
      sample_names(g).each do |n|
        if sample_duration(n) > 0.2
          sample n,beat_stretch: 0.2
        else
          sample n
        end
        sleep 0.2
      end
    end
  end
end

live_loop :dingdong do
  sync :space
  use_synth :tri
  play 76
  sleep 1
  play 72
end




##| transmit program contained below for reference. It is normally downloadeed separately.
## Run this from a terminal window
##| then run SP program
##| then set focus to terminal and type in notes to play

##| #terminal ruby program to get and transmit key info
##| require 'io/wait'
##| require 'socket'

##| server = TCPServer.new 2016 #set up transmit tcp socket

##| def char_if_pressed #routine to scan for keyboard press (non-blocking)
##| begin

##| system("stty raw -echo") # turn raw input on
##| c = nil
##| if $stdin.ready?
##| c = $stdin.getc
##| end
##| c.chr if c
##| ensure
##| system "stty -raw echo" # turn raw input off
##| end
##| end

##| while true #main loop, runs until stoped by ctrl-c
##| k=0 #0 will be transmitted if no key pressed
##| c = char_if_pressed
##| k= "#{c}".ord if c #work out ascii value of key
##| client = server.accept    # Wait for a client to connect
##| client.puts k #transmit the keycode
##| client.close #close the client terminating input
##| sleep 0.02 #short gap
##| end

Now the second progarm which you run in a terminal window using ruby terminalcontroller.rb

#terminal ruby program to get and transmit key info
#written by Robin Newman, April 2016
# use in conjunction with SP-KeyboardController.rb running in Sonic Pi
require 'io/wait'
require 'socket'

server = TCPServer.new 2016 #set up transmit tcp socket

def char_if_pressed #routine to scan for keyboard press (non-blocking)
begin
system("stty raw -echo") # turn raw input on
c = nil
if $stdin.ready?
c = $stdin.getc
end
c.chr if c
ensure
system "stty -raw echo" # turn raw input off
end
end

while true #main loop, runs until stoped by ctrl-c
k=0 #0 will be transmitted if no key pressed
c = char_if_pressed
k= "#{c}".ord if c #work out ascii value of key
client = server.accept    # Wait for a client to connect
client.puts k #transmit the keycode
client.close #close the client terminating input
sleep 0.02 #short gap
end

For reference the youtube video is here: