Idea : pause, restart sample - better than Ableton live :-)

Hi there,

Let me tell you a story : let suppose into Ableton live you want to launch a sample, pause it then restart from this stop position ? You think : "oh come on, there must be a feature to do this, no ? ". Well, it seems no. The Launch behaviour will always start from the beginning of the clip sample.

Ok now, what if sonic pi could do this !

function pause(sample), function restart(sample)

I’m looking for this behaviour to create a quizz musical system : 20 songs = 20 samples. A button to trigger the play and pause/restart (interface build with open-stage-control) ; this button would send an osc message to sonicpi on the good osc adress.

But and there is a big but :smile: i haven’t no clue how to get these two functions. Maybe it could be native functions in the future

So what do you thinf about that ?


Nicolas

You can get somewhere close to this with the built in functionality:

# Choose a sample
samp = :guit_harmonics

# Make a note of current time
t0 = current_time
# Start playing sample
x = sample samp

# Wait a bit
sleep 1

# Stop the sample
kill x
# Find out how much time has elapsed
t = current_time - t0

# Wait a bit so we can hear the break
sleep 1

# Restart sample where it left off
sample samp, start: t / sample_duration(samp)

thank you @emlyn for this code.

I can’t figure out to handle the conditions coming from osc. I guess i will need two osc messages /sample/start 1 to play
/sample/start 0 to pause
these are the states of the toggle button


# 13/07/2022
# start quizz musical project

puts 'welcome'

# some osc parameters
# the software openStageControl will be refered as o-s-c
use_osc_logging true;
# o-s-c port input for osc messages ios 7777, on the same machine at the moment
use_osc "127.0.0.1", "7777"

comment do # uncomment to test
  4.times do
    osc "/sample/start", 1
    sleep 2
    osc "/sample/start", 0
    sleep 2
  end
  stop
end


# Choose a sample

samp = :loop_amen_full


# if we receive an osc message from the address /sample/start with a value of 1
##| comment do
##|   live_loop :oscListener do
##|     flag1 = get "/osc*/sample/start"
##|     flag2 = get "/osc*/flag2"
##|     flag3 = get "/osc*/flag3"
##|     flag4 = get "/osc*/flag4"  #nothing sent to this address (by me!) so always nil
##|     if !(flag1==nil)
##|       set :playSample, flag1[0]
##|     end

##|     puts flag2[0] if !(flag2==nil)
##|     puts flag3[0] if !(flag3==nil)
##|     puts flag4[0] if !(flag4==nil)
##|     sleep 1
##|   end
##| end


##| live_loop :lecture do
##|   sync "/live_loop/oscListener"
##|   use_real_time
##|   puts(get :playsample)

##| end

set :alreadyPlayed, false

live_loop :toCatchTheState do
  
  use_real_time
  d = sync "/osc:127.0.0.1:7777/sample/start"
  # hello will be printed if spi received the osc message
  puts "hello"
  puts get[:alreadyPlayed]
  
  if d[0]==1 # 1 for the button on
    set :t0, current_time
    if get[:alreadyPlayed]===true
      
      # Restart sample where it left off
      sample samp, start: get[:t] / sample_duration(samp)
    else
      # Make a note of current time
      # Start playing sample
      x = sample samp
      set :alreadyPlayed, true
    end
    
    
  else
    # Stop the sample
    puts "Kill me"
    kill x
    # Find out how much time has elapsed
    boo = get[:t0]
    set :t , current_time - boo
    
    # Wait a bit so we can hear the break
  end
  sleep 0.1
end

If anybody has some paths to explore :slight_smile:

I had a little play around with it, and I think I got it working:

# 13/07/2022
# start quizz musical project

puts 'welcome'

# some osc parameters
# the software openStageControl will be refered as o-s-c
use_osc_logging true;
# o-s-c port input for osc messages ios 7777, on the same machine at the moment
use_osc "127.0.0.1", 4560

uncomment do # uncomment to test
  in_thread do
    4.times do
      osc "/sample/start", 1
      sleep 2
      osc "/sample/start", 0
      sleep 2
    end
  end
end

# Choose a sample
samp = :loop_amen_full

set :elapsed, 0.0

live_loop :toCatchTheState do
  use_real_time
  d = sync "/osc*/sample/start"
  
  if d[0]==1 # 1 for the button on
    elapsed = get[:elapsed]
    puts "Starting sample at", elapsed
    set :t0, current_time
    set :sample, (sample samp, start: elapsed / sample_duration(samp))
  else
    # Stop the sample
    kill get[:sample]
    # Find out how much time has elapsed
    elapsed = get[:elapsed] + current_time - get[:t0]
    set :elapsed, elapsed
    puts "Stopping sample at", elapsed
  end
end

Here’s some of the log output (a screenshot as I couldn’t copy the text):

1 Like

I had a little play with this too, and adjusted it to use ableton transport via link. I also adjusted it to run continuously, switching to a different sample (if required) once the first one had ended.

#extra code to allow ableton transport to control things via link
use_osc "localhost",4560
link
#the next two live loops convert /link start and stop to osc "/sample/start"
live_loop :start do
  use_real_time
  sync "/link/start"
  osc "/sample/start",1
end
live_loop :stop do
  use_real_time
  sync "/link/stop"
  osc "/sample/start",0
end
#end of extra code
# 13/07/2022
# start quizz musical project

puts 'welcome'

# some osc parameters
# the software openStageControl will be refered as o-s-c
use_osc_logging true;
# o-s-c port input for osc messages ios 7777, on the same machine at the moment
use_osc "127.0.0.1", 4560

comment do # uncomment to test
  in_thread do
    4.times do
      osc "/sample/start", 1
      sleep 2
      osc "/sample/start", 0
      sleep 2
    end
  end
end

# Choose a sample
samp = :loop_amen_full

set :elapsed, 0.0


live_loop :toCatchTheState do
  use_real_time
  d = sync "/osc*/sample/start"
  puts "d is ",d
  if d[0]==1 # 1 for the button on
    #rest if end of sample reached: can also choose new sample here
    if get(:elapsed) >= sample_duration(samp)
      set :elapsed,0
      #choose next sample to use
      samp =  ring(:loop_tabla,:loop_amen_full).tick
    end
    
    elapsed = get(:elapsed)
    puts "Starting sample at", elapsed
    set :t0, current_time
    set :sample, (sample samp, start: elapsed / sample_duration(samp))
  else
    # Stop the sample
    kill get[:sample]
    # Find out how much time has elapsed
    elapsed = get[:elapsed] + current_time - get[:t0]
    set :elapsed, elapsed
    puts "Stopping sample at", elapsed
  end
end
2 Likes

Hi there !

So it almost work :slight_smile:

I guess we need to handle the case when the sample has been fully played. If i push again the button it comes to

i’m stuck…

Look in my example above. You test that elapsed is not >= the sample duration and if so reset it to 0 to start again. Then when you work out start = elapsed/sample_duration(samp) it will never be > 1
I actually siwtched to a differnt eample at that point, but you could stay with the same one.