I am writing a music creation program where the user is allowed to change the tempo throughout the track.
If the user had a set tempo or only changed the tempo at discrete intervals I could easily calculate the time by taking the tempo, and the beat range occupied by that tempo, and dividing the range by the beats per second tempo value. If the tempo changed at some point I would apply the same thing to the next part and add that time on to the first part.
However, I'm struggling to wrap my head around how I would do this with interpolated tempo values. Say for the example the user wants a linear interpolated increase from beat 1.0 to beat 3.0 from 120 BPM to 140 BPM. How do I calculate exactly how long a linear change in tempo would take?
I know that at a steady 120 BPM (2 BPS), this would take a second. At 140 BPM (2.33 BPS) it would take just under that. But how do I work out how long it would take with a linear increase in tempo during that time from the first value to the second?
And what if I was to allow for different interpolation methods, such as some sort of fade in or fade out interpolation? Would things become more complicated?
The short answer: to arrive at a formula, write your tempo as a function of song location (e.g. beat number) and perform a definite integral of its multiplicative inverse.
A concrete example:
To make the math a little easier, let's number the beats of your whole song starting at $0$. Beat $0$ is the place in your song just before the very first bar. Beat $4$ would be the spot in between the first and second measure (if it's in 4/4, any way). Beat $8$ would be between the second and third measures, etc.
Let's write down a function, $T(b)$, for the tempo at beat number $b$. In your example, $T(0)$ is 120 beats per minute and $T(2)$ is 140 beats per minute. You said you wanted it linearly interpolated. I'll take that to mean "linearly over the beats" (as opposed to linearly over time). So between beats $0$ and $2$: $$ T(b) = 120 + 10b $$ This function takes a beat number, $b$, and tells you the tempo in beats per minute. The function $1/T(b)$ is "minutes per beat" at time $b$.
So to calculate how much time passes, compute this integral: $$ \begin{align} \int_{0}^{2} \frac 1 {T(b)} db &= \int_{0}^{2} \frac 1 {120 + 10b} db \\ &= \frac 1 {10} \log (12+b) \bigg|_0^2 \\ &\approx 0.0154 \end{align} $$ Since $T(b)$ uses time units of minutes, that means those two beats take 0.0154 minutes, or about 0.925 seconds.
More generally, say the tempo at beat $b_0$ is $T_0$ and the tempo at beat $b_1$ is $T_1$. Then between $b_0$ and $b_1$ the tempo value can be linearly interpolated as $$ T(b) = T_0 + \frac {T_1 - T_0} {b_1 - b_0} (b - b_0) $$ So the time that elapses between $b_0$ and $b_1$ is: $$ \begin{align} \int_{b_0}^{b_1} \frac 1 {T(b)} db &= \int_{b_0}^{b_1} \frac 1 {T_0 + \frac {T_1 - T_0} {b_1 - b_0} (b - b_0)} db \\ &= \frac {b_1-b_0} {T_1-T_0} \log (T_0 + \frac {T_1 - T_0} {b_1 - b_0} (b - b_0)) \bigg|_{b_0}^{b_1} \\ &= \frac {b_1-b_0} {T_1-T_0} \log \left(\frac{T_1}{T_0}\right) \end{align} $$ So just plug in $b = b_1$ and $b = b_0$ into that last expression, subtract, and you'll have the time duration (in minutes).
If you wanted different interpolation methods, it would just change what the function $T(b)$ looks like. This will in turn change the difficulty of performing the integral. But the general idea will remain the same.