I have been playing around with ways to use break beats and drum loops without having to use beat_stretch or variables for sleep values in order to have other sounds or sample line up correctly. I came up with a function that will take any loop and return the correct bpm. You just need to provide the number of beats in the loop.
Here is an example of it in use with the Amen break:
define :bpm do |samp, subDiv| # samp = loop you want to use, subDiv = number of beats in that loop
t = sample_duration samp #variable to store duration of loop
bps = t/subDiv # beats per second found by dividing loop duration by the number of beats in the loop
beatsPerMin = 60/bps #converts beats per second to beats per minute
return beatsPerMin # returns bpm of loop
end
use_bpm bpm :loop_amen, 4 #setting bpm to the correct bpm of the loop by using the function
live_loop :amen do
sample :loop_amen #play sample
sleep 4 #sleep for the same number of beats in the loop of the sample, most likely 2, 4 or 8
end
live_loop :bass, sync: :amen do
play (octs, :d1, 3).choose, release: 0.5
sleep 0.5 #Any accompanying synths or samples can use evenly divided sleep values and should align perfectly with loop
end
2 Likes
hi how would I use this with my own loops thanks 
Hi Soundwarrior, Iâve edited the original code a bit. Hopefully this is what youâre looking for.
define :getBpm do |samp, beats| # samp = loop you want to use, subDiv = number of beats in that loop
t = sample_duration samp # variable to store duration of loop
bps = t/beats # beats per second found by dividing loop duration by the number of beats in the loop
beatsPerMin = 60/bps # converts beats per second to beats per minute
return beatsPerMin # returns bpm of loop
end
sample = "C:/Users/l_bridge/OneDrive/Sonic Pi/Samples/Classic Breaks/Hot Pantz 162.wav"
beats = 16 # The 'Hot Pantz 162' break is 16 beats over 4 bars (and 162bpm). If you had a 1 bar loop beats would = 4.
puts getBpm(sample, beats)
# returns 162.00020663291662 for me
SInce writing this post, I have discovered that there is a command in Sonic Pi which does what this function set out to do.
It is called use_sample_bpm and takes an additional argument for how many beats you want there to be in the loop
use_sample_bpm :loop_amen, num_beats: 4
live_loop :looped do
sample :loop_amen
sleep 4
end
To use your own samples in this code, I would suggest assigning the sample path to a variable and then using that variable as the first argument in the command
yourSample =" C:/User/path/to/your/sample.wav"
use_sample_bpm yourSample, num_beats: 4
live_loop :looped do
sample yourSample
sleep 4
end
3 Likes
Note that this assumes that the sample duration matches the length of the bar. It doesnât do any fancy beat detection analysis on the audio. If thereâs any accidental silence at the beginning or end of the sample then this will not necessarily produce desirable results. However, most decent loop samples are appropriately trimmed so this shouldnât be an issue in general.
2 Likes
Hi and thanks for having me, excuse the possibly silly question but, How do you get âuse_sample_bpmâ to play nice and speed up. Itâs been a long time since Iâve done any coding.
# doesn't work
amen_sped_up = :loop_amen, rate: 1.1
use_sample_bpm amen_sped_up, num_beats: 4
live_loop :looped do
sample :loop_amen, rate: 1.1
sleep 4
end
# nor does
use_sample_bpm :loop_amen, num_beats: 4
live_loop :looped do
sample :loop_amen, rate: 1.1
sleep 4
end
# nor
use_sample_bpm :loop_amen, rate: 1.1, num_beats: 4
live_loop :looped do
sample :loop_amen, rate: 1.1
sleep 4
end
Hello @Lukey_Moonshine 
Thereâs a couple of things going on here.
The first one doesnât work due to the limitations of the structure of Sonic Pi code. For the line amen_sped_up = :loop_amen, rate: 1.1
- Sonic Pi attempts to interpret the line, but when it gets to the comma it doesnât expect the rate: 1.1
to be the sort of thing that follows - it just sees some unexpected label it doesnât know how to handle). Itâs as if we were trying to assign two separate things to amen_sped_up
at the same time, separated by a comma - thatâs not going to work!
(to actually do such a thing, weâd need to enclose the two items in square brackets so that we were assigning a single item which is really an array containing two elements. However, even if we were to do such a thing here, it doesnât solve the problem still).
The middle one doesnât work because use_sample_bpm :loop_amen, num_beats: 4
says âtreat the length of the :loop_amen
sample at the default rate (1) to last for 4 beats.â However, we then ask the live_loop to play the :loop_amen
sample at a slightly higher rate - so it will complete in less than 4 beats.
Regarding the last one however - in what way does that one not work? when I test it, the sample appears to play at slightly higher than normal rate, and the loop repeats exactly according to the beat.
Thanks for the reply and explanation. Interesting, the third is the one I tried first, when I run it it does the same as the second, completing in less than 4 beats so there is a pause between playing the sample and playing it again.
worked out a way of getting the result I desired, Iâll re-format the code tomorrow to make it more elegant but this seams to work,
use_sample_bpm :loop_amen, rate: 1.1, num_beats: 4
live_loop :looped do
sample :loop_amen, rate: 1.1
sleep 4/1.1
end
Quite odd. That one you share above loops before the sample has completed for me.
Which version of Sonic Pi are you using?