Linearly changing tempo & control signals

Hi, I recently picked up SC and learned to use it again. Registered to the site to ask questions but ended up figuring them out while waiting. Therefore, I instead post what I learned.

I’m writing a music sequencer in Python. It uses OSC to communicate with SC. Everything’s fine until I realize I want varying tempo with beat-synchronized control signals that change linearly.

Initially I started with:

tempo(beat) = k*beat + c
saw_frequency(beat) = k'*beat + c'

So tempo would be a linear function over the ‘beat’ and saw frequency would be something similar. The problem here is that we get a (beat → time) and (time → beat) functions that has to be varied depending on whether k=0. It can be resolved by integrating over dt = (60 / (k*b + c)) db. You’ll get a logarithmic function t(b) = (60 / k)ln((c + kb) / c) and a simple t(b) = (60 / c) * b. To get (time → beat) you invert these functions, but we won’t go there.

In practice, tempo being linear over time would suffice and produce just fine results, and the resulting (time → beat) -function ends up being quadratic.

tempo(time) = m*time + T
saw_frequency(beat) = k'*beat + c'

db = (tempo(t) / 60) dt

beat(time) = (T/60)*t + (m/120)*t*t

This is neat because we can compose the (saw_frequency . beat) and the result is a quadratic function to control our signal, eg.

saw_frequency.beat (t) = k'*((T/60)*t + (m/120)*t*t) + c'
 = k'*T/60*t + k'*m/120*t*t + c'

It results in a neat synthdef! The additional ‘t’ parameter is to stop the synth from rolling along into uncharted territory if the new control signal doesn’t arrive in time.

SynthDef(\quadraticFunc, { |out, a=0.0, b=0.0, c=0.0, t=0.0|
	var x = Sweep.kr(\trig.tr(0)).min(t);
	var val = (a*x*x) + (b*x) + c;
	Out.kr(out, val);
}).add;

x = Synth(\quadraticFunc, [out: ~mysignal]);
x.set(\a, 0.0, \b, 1.0, \c 5.0, \t 5.0, \trig, 1);

But then there’s a problem that I would still prefer saying: “at beat 4, tempo must be 135”. Well, you can do that while having tempo that changes linearly over time.

We want to span db beats, have T0 startpoint, T1 endpoint, and we want to derive how many seconds it takes. The equation is:

m = (T1 - T0) / dt
dt = 120*db/(T0 + T1)

I didn’t work through the math myself, I got some help on that via AI. But most of it is fairly simple math.

Finally we got a bell that we want to struck at certain beat. How do we calculate (beat → time)? Well, we got a quadratic function so it suffices to find the root using a quadratic equation.

b = T0 / 60
a = m / 120

time(beat) = beat / s  {if m = 0, otherwise use the quadratic equation below}

time(beat) = (-b + sqrt(b*b - 4*a*c)) / (2*a)

There. If anybody else wants linear functions over beat in music, these equations should end up being very helpful!