How to end the script

So I have now successfully finished making a beat, but how do I now end the song? How do I make the instruments stop?

# Written by Sam Humphreys

#––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

# Setting BPM to 70
use_bpm 70

#––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

# Making variables:

# The clap is a single one-shot hit, that I repeat every two seconds on line 41
clap = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/Logic Pro X/Music Plug-Ins/Cymatics/Cymatics - Drill Essential Drum Kit/Drum One Shots/Claps/Cymatics - Wake Clap.wav"

# The hi hats is a loop that I created on Logic Pro, and then bounced out as a .aif file.
# I made the loop on Logic because I thought it would be too hard to make a good
# sounding hi hat loop on Sonic Pi because of my experience with it (absolutely zero).
hi_hats = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/2020/2021/TeKura/Music/SonicPi/bouncedLoops/Hi-hat-loop-for-Sonic-Pi.wav"

# The 808 is another loop I made on Logic, for the same reason as the hi hat loop. The 808s are
# way to complicated to make in Sonic Pi for someone with my knowledge of Ruby and Sonic Pi.
bass = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/2020/2021/TeKura/Music/SonicPi/bouncedLoops/SonicPiBass.wav"

# This is the kick. I was going to make this loop in Logic again but I thought that if I did too much in Logic, my grade would be lowered.
kick = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/Logic Pro X/Music Plug-Ins/Cymatics/Cymatics - Drill Essential Drum Kit/Drum One Shots/Kicks/Cymatics - Ultimate Kick - G.wav"

# This is the perc loop. Made on Logic again.
perc = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/2020/2021/TeKura/Music/SonicPi/bouncedLoops/Percloop.aif"

# This is a white noise up effect.
wn_u_fx = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/Logic Pro X/Music Plug-Ins/Cymatics/Cymatics - FX Essentials/White Noise/Up/Cymatics - FX Essentials White Noise Riser 18 - 140 BPM.wav"

# This is an impact effect.
impact = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/Logic Pro X/Music Plug-Ins/Cymatics/Cymatics - FX Essentials/Impacts/Cymatics - FX Essentials Impact 2.wav"

# This is a white noise down effect.
wn_d_fx = "/Users/samhumphreys/Library/Mobile Documents/com~apple~CloudDocs/Logic Pro X/Music Plug-Ins/Cymatics/Cymatics - FX Essentials/White Noise/Down/Cymatics - FX Essentials White Noise Downlifter 6.wav"

#––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

live_loop :habanera do
  use_synth :fm
  use_transpose -12
  play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
  sleep 0.25
end

with_fx :reverb do
  live_loop :space_light do
    with_fx :slicer, phase: 0.25 do
      synth :blade, note: :d, release: 8, cutoff: 100, amp: 2
    end
    sleep 8
  end
end

sleep 16

in_thread do
  sleep 1
  loop do
    sample clap, amp: 2
    sleep 2
  end
end

in_thread do
  loop do
    sample bass, amp: 1
    sleep 16
  end
end

sleep 8

in_thread do
  loop do
    sample wn_u_fx
    sleep 32
  end
end

sleep 8

in_thread do
  loop do
    sample hi_hats
    sleep 16
  end
end

in_thread do
  loop do
    sample kick, amp: 2
    sleep 0.25
    sample kick
    sleep 1.25
    sample kick
    sleep 1
    sample kick
    sleep 0.75
    sample kick
    sleep 0.75
    sample kick
    sleep 0.75
    sample kick
    sleep 0.75
    sample kick
    sleep 1
    sample kick
    sleep 1.5
  end
end

in_thread do
  loop do
    sample perc
    sleep 16
  end
end

in_thread do
  sample impact
end

in_thread do
  sample wn_d_fx
end

I have done it using the stop command inside the live loop. This can be triggered by a cue set by the control loop. See example here
The relevant line says

stop if (get :run)  == 0

Here an example from SPI’s tutorial with a control loop added to make it stop:

# Compus Beats

# Coded by Sam Aaron
# control loop added by Nechoj

use_sample_bpm :loop_compus, num_beats: 4

set :run, 1

live_loop :control do
  if tick == 12
    set :run, 0
    stop
  end
  sleep 1
end


live_loop :loopr do
  stop if (get :run) == 0
  sample :loop_compus, rate: [0.5, 1, 1, 1, 1, 2].choose unless one_in(10)
  sleep 4
end

live_loop :bass do
  stop if (get :run) == 0
  sample :bass_voxy_c, amp: rrand(0.1, 0.2), rate: [0.5, 0.5, 1, 1,2,4].choose if one_in(4)
  use_synth :mod_pulse
  use_synth_defaults mod_invert_wave: 1
  play :C1, mod_range: 12, amp: rrand(0.5, 1), mod_phase: [0.25, 0.5, 1].choose, release: 1, cutoff: rrand(50, 90)
  play :C2, mod_range: [24, 36, 34].choose, amp: 0.35, mod_phase: 0.25, release: 2, cutoff: 60, pulse_width: rand
  sleep 1
end

Yep. stop will end its enclosing thread (or run if it is not enclosed), and nothing else (so none of the thread’s sub-threads). Code accordingly.

In my latest project, I use a timed control live_loop to which every live_loop syncs on a regular basis. When a preset amount of time is up, the timed control live_loop stops, and the other live_loops are left hanging. (measureTime is the timed control live_loop.)

live_loop(:maintainLog) do
  …
  sync_bpm("time/measure")
end

live_loop(:maintainSpace, …) do
  …
  sync_bpm("time/measure")
end

live_loop(:measureTime, …) do
  activateMetronome()
end

live_loop(:maintainVoices, …) do
  …
  sync_bpm("time/measure")
end

thanks guys

how do I actually set :run to 0 automatically? I can’t find it in your code.

Do you see it in the example however?

tick automatically increments by 1 every time it’s accessed, so that after 12 loops of :control, the condition will be met, :run will be set to 0, and :control will stop.

(That’s a better solution than leaving threads hanging actually :sweat_smile: Looks like I have some more revising to do! In a project with many threads, sub-threads, sub-sub-threads, &c., it may be more trouble than it’s worth to stop everything. So long as the sound stops.)

2 Likes

thanks for explaining, ill give it a try.

1 Like

why didn’t y’all just tell me to do x.times do??? :joy: alg

That works in your situation, so it’s good you figured it out!

Hmm, from the tutorial, there’s this:

If you want something to repeat a lot of times, you might find yourself using really large numbers such as 1000.times do . In this case, you’re probably better off asking Sonic Pi to repeat forever (at least until you press the stop button!).

It’s true that you could create a global time limit and use a function to determine the number of repetitions needed for each loop based on its sleep duration. Otherwise, with a lot of threads, maintenance might get a bit tedious.

1 Like