Finding correct bpm of drum loops

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 :slight_smile:

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 :slight_smile:

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! :smile: (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?

Hi, sorry if this isnā€™t the right place for this, but on the topic of sample_duration, does SP know how many beats are in its samples, and their BPM?

I think I found a method that may return this, but that may be just the method used by the sample_duration command

I remember a changelog comment on a new sample and its intended BPM (130)

I peaked at the (flac?) Sample in Windows explorer but no metadata therein (and I doubt SP looks at that anyway)

Thanks!

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 :thinking:)

Thanks!