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
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
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.
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
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
Hi Sam & everyone, I’ve been looking at bpm and beats stuff , to see if there’s information on intended/original bpm, and also beats in the sample.
I found reference to some bpms of some loops in the changelog - does sp know the bpm of samples, or doesn’t it matter?! I imagine this could be useful for loops (less so for FX and one shots), but couldn’t locate anything in the code
Similarly (#2) is there a record of the beats in a sample, or should we identify and record this, if desired/required?
I plan to playback and Count and record, perhaps as metadata… guess most loops are 4 beats, loop_amen_full is 8 - is that right?
Finally (#3) does the sound _in or any other sp recording provide any options for auto-trim silence?
I imagine sync start recording can be achieved, so maybe it’s just the end that have trailing silence - not sure if this already exists as an option, or if it’s feasible, and/or outside the scope of planned development (eg a job for another program, or gem )