Event duration during acceleration

Can anyone point me towards a formula for calculating seconds from beats during gradual tempo changes?
Like, if a piece goes from 60 BPM to 70 BPM over 8 beats, and I want the beats to accelerate gradually and evenly, how many seconds will each beat have?
I believe this is ultimately calculus, but I’m just a little too lazy at my age to work it out.

1 Like

Your question misses an important information. At what rate do you want it to accelerate or are you looking for a linear interpolation? 8 Beats is an insufficient information. Do you want one event per beat, two per beat …

Interpolation(Start, End, Alpha): → start + (end - start) * alpha
Rate(Start, End, NumTotal): → (end - start) / NumTotal

This is my question. At what rate?
At what rate do DAWs accelerate? They don’t offer multiple options, and in my experience, they also don’t provide this information.
I believe the most intuitive for a listener would be a percentage acceleration per beat…
I.e., if it goes from 60 to 70 over 8 beats, then it would increase by (70/60)^(1/8) for each beat. But it doesn’t need to jump; event durations can be calculated so that this acceleration is a continuous curve. That is, you wouldn’t just assume it’s 60 BPM for the entire duration of the first beat; because that would sound odd if you had 32nd notes, where 8 notes would have the same length, and then suddenly 8 more notes with a different length.
So I suppose, if n=events per beat, I am looking for the limit as n approaches infinity.
In my sequencer, I’d just calculate the start and end times of notes, and of course other events; I wouldn’t bother trying to calculate start and end times for all beats or all subdivisions of beats. Just whatever notes the user adds.

But anyway, I’d also just like to know how most sequencers and DAWs calculate this, regardless of what I imagine it should be.

From the looks of it, Logic calculates it exactly the way I wrote. And seems like you can specify the granularity (last entry):

If you want to achieve a continues curve, you might be better off with an interpolation of a higher grade. JUCE has a few interpolation methods already implemented. JUCE: Interpolators Class Reference

But tbh I still don’t fully get your question. When you have a finite list of times you would like to stretch according to your start and end value, then the interpolation is the perfectly fine choice to find the values in the middle. Why do you think a DAW does that differently?

To calculate the start time of a note is trivial, but you cannot use the current tempo for the duration, as you already mentioned.
As an approximation I would update the duration each beat, so if you have a full note (4 beats) I would make it the sum of
a quarter at 60 bpm = 0.25
a quarter at 62.5 bpm = 0.24
a quarter at 65 bpm = 0.2308
a quarter at 67.5 bpm = 0.223
Sum: 0.94…

That is indeed a good suggestion, the above sum is the same as:
4 beats * 60 / ( (60 + 67.5) / 2)
= 120 / (60 + 67.5)
= 0.94…

This goes back to the anecdote of Gauss as a young student:

That is indeed an approximation. It’s also linear; it will seem to speed up more at the beginning and less at the end, because 2.5 is a smaller increase from 67.5 than it is from 60.
If I render one part, then, with quarter notes, it’d be 0.94; but if I render another part with 16th notes, I either have 4 16th notes with the same duration, then 4 more 16th notes with another duration, 4 more, etc.; that would lead to bursts of acceleration every 4 16th notes instead of constant acceleration. Maybe few people would notice, but I’m not convinced.

OR I increase the “granularity”, and the first 4 16th notes will not end at the same time as a quarter note in another part calculated per beat.

I don’t see how calculating start times is trivial.
I could either calculate all possible times up to a certain resolution or find the calculus equation. I think the latter will ultimately be less calculation.

But why don‘t you pipe the 16ths notes per quarter through the same equation. I wouldn‘t consider the duration a problem itself. The duration will be the result when you project the start and the end time with the function. This way, every „measurable“ point will be at the exact correct position according to your chosen function.

If the linear interpolation creates this problem for you, you can choose a different interpolation (=function). But the approaches stays the same.

It is surely a topic where you can spend some more thought in.

About the granularity: if you look at the formula, the quarter steps are gone there.

To stick to the example above incrreasing from 60 to 70 BPM over 8 bars you would have 65 BPM after 4 bars with 4/4 signature.
That gives the time of bar 5:
16 beats * 60 (seconds/minute) / ((60 BPM + 65 BPM) / 2) = 15.36 seconds
In comparison at fixed 60 BPM: 16 seconds and at 70 BPM: 13.71 seconds

The whole passage’s duration:
32 * 60 ((60 + 70) / 2) = 29.538 seconds

(Sorry for the calculation examples, was also for my own sanity, I am interested as well if it sums up)

If the tempo change is constant (ie, the tempo curve is linear) then this problem is equivalent to "how much time does it take to travel x distance under constant acceleration a at a beginning speed of v0" (displacement under constant acceleration).

The units are :

a:  beats per second per second 
v0: beats per second
x:  beats
t:  seconds
x = (1/2) at^2 + v0 t

Solving for t via the quadratic formula

0 = at^2 + 2v0t + x
t = (-2v0 +/- sqrt(4v0^2 - 4ax)) / (2a)

This is a little easier to work with than interpolation since you can pick blocks between tempo change points to sequence events in absolute time (seconds) then convert to samples, splitting into fixed size blocks.

Tempo lines are a lot better than discrete tempo points (what a lot of DAWs used to use), but you can also derive the formula for displacement under different acceleration curves.

The acceleration can be found only knowing initial tempo, final tempo, and distance covered using the formula

v1^2 = v0^2 + 2ax 

where x in this case is the distance you accelerate over (in your example, 8 beats), v0 is the initial tempo, and v1 is the final tempo.

edit: someone might want to double check my math, this looks right but the example is a bit wonky

1 Like

I don‘t quite understand how you came to the 2aat the end. Shouldn‘t the a be in the sqrt? In order to apply the quadratic Formular the quadratic factor needs to be one. So you would have to divide by 2a first, and then apply the Formular.

And I think (for completion purposes) you should add an x0 term, as the tempo change doesn‘t start at the beginning (is suppose).

I screwed up the formula when I wrote it up there, hopefully my edit caught it. I think you would only need x0 if you were sequencing events in the middle of the tempo change.

This is the matlab script I’m using to double check the reasoning :

v0 = 70 / 60
v1 = 80 / 60

% x = at^2 + 2v0 t 
% 0 = at^2 + 2v0 t - x
% x = 1 beat
a = (v1.^2 - v0.^2) / (16) % acceleration
b = 2 * v0                 
c = -1

roots([a, b, c])

which gives :

v0 =  1.1667
v1 =  1.3333
a =  0.026042
b =  2.3333
c = -1
ans =


And I don’t think that 0.4264 is correct.

Found it, off by one

v0 = 60 / 60  % bpm -> b/s
v1 = 80 / 60  % bpm -> b/s

% x = at^2 + 2v0 t 
% 0 = at^2 + 2v0 t - 2x
% x = 1 beat
a = (v1.^2 - v0.^2) / (16) % acceleration
b = 2 * v0                 
c = 2 * -1

max(roots([a, b, c])

the answer is :

v0 =  1
v1 =  1.3333
a =  0.048611
b =  2
c = -2
ans =  0.97681

I imagine it wouldn’t be. It would be a percentage of the current speed per time unit, no? So the change per beat would be the same percentage.
If you start at 60 BPM and ramp to 90 BPM linearly, the change from 60 to 65 is more significant than the change from 85 to 90; that means that the strongest sense of acceleration is at the beginning, and then it gradually gets faster. To my ear, that’s not how most bands speed up.

I was thinking that, after half of the beats, you’d be at t1*((t2/t1)^.5); not at t1+(t2-t1) Then, at the end, you’d have t1*(t2/t1), i.e. t2.

Here’s a Python function I came up with, but it doesn’t find the limit; it takes granularity as an argument (n). I find that n=200 gives almost the same value as n=200000, but it would still be faster to substitute the limit as n->infinity than to increment the duration 200 times.
t1 = start BPM
t2 = end BPM
b = number of beats between t1 and t2
n = number of actual tempo changes between t1 and t2

def findDur(t1, t2, b, n):
    k = 0
    dur = 0
    while k < n:
        dur += 60*b/(n*(t1*((t2/t1)**(k/n))))
    return dur

For any event between the two tempo changes, I can calculate what the BPM is at that time:
bpm(event) = t1 * (t2/t1)^((event.beat-t1.beat)/(t2.beat-t1.beat))
Time being in beats, of course. For instance, if t1=60, t2=240, and there are 4 beats between them, then at beat 2, the BPM should be 120; with linear interpolation, it would be 150.
With that information, I can run findDur using t1 and the event as arguments, instead of t1 and t2.
I am sure the limit of this sum as n->infinity is not that complicated, but my days of suddenly up and refreshing my calculus “just because” are behind me.

This problem is far from being obvious. Different DAWs do it in a different way. Let’s take your example with the tempo change from 60bpm to 240bpm over one bar containing 4 beats. From your calculations we have got the following tempi at the beginnings of the subsequent beats (beat 0 = initial beat, beat 4 = first beat of the next bar)

beat 0 = 60 bpm
beat 1 = 84.85 bpm
beat 2 = 120 bpm
beat 3 = 169.70 bpm
beat 4 = 240 bpm

In Reaper they do it as follows:

beat 0 = 60 bpm
beat 1 = 130.76 bpm
beat 2 = 174.93 bpm
beat 3 = 210 bpm
beat 4 = 240 bpm

In Ableton Live and Waveform (in Waveform with the tempo track curvature = 0, but it can be changed!), it’s just this simple proportion (btw. in Ableton 200bpm is the upper limit but the principle is the same):

beat 0 = 60 bpm
beat 1 = 105 bpm
beat 2 = 150 bpm
beat 3 = 195 bpm
beat 4 = 240 bpm

Now, the question is which calculation is the correct one and I think there is no such answer. The correct one is which makes a musical sense in a certain context. And if we have for example a bar with notes of different duration, then the question is how the tempo is expected to change in relation to note lengths and how many repetitions of a note group or a riff are during this tempo transition to get the (subjectively) best result.

Well said. This is why so few people ever ask the question.

I think at the end of the day what you want to do is take some curve and quantize it (to points, line segments, etc) that allows you to easily compute when an event occurs in time to schedule it in sample offsets.