Bas's answer is great, but doesn't actually give an analytic solution, so here's that part...
As far as I can tell, you want something like sin(Aexp(Bt))
where A
and B
are constants. I'll assume time starts at 0
and continues to C
(if it starts at some other time, subtract that from both).
Then, as Bas said, I think, if we have sin(g(t))
frequency f
is such that 2 * pi * f = dg / dt
. And we want that to be f0
at time 0
and fC
at time C
.
If you go through the maths, which is easy (it really is - last year of school level), you get:
B = 1/C * log(fC/f0)
A = 2 * pi * f0 / B
and here's some code that goes from 1 to 10Hz in 5 seconds using 1000 samples:
from math import pi, sin, log, exp
def sweep(f_start, f_end, interval, n_steps):
b = log(f_end/f_start) / interval
a = 2 * pi * f_start / b
for i in range(n_steps):
delta = i / float(n_steps)
t = interval * delta
g_t = a * exp(b * t)
print t, 3 * sin(g_t)
sweep(1, 10, 5, 1000)
which gives:
(and you can add in a constant - sin(g_t + k)
- to get the starting phase wherever you want).
Update
To show that the issue you are seeing is an artefact of sampling, here's a version that does oversampling (if you set it as an argument):
from math import pi, sin, log, exp
def sweep(f_start, f_end, interval, n_steps, n_oversample=1):
b = log(f_end/f_start) / interval
a = 2 * pi * f_start / b
for i in range(n_steps):
for oversample in range(n_oversample):
fractional_step = oversample / float(n_oversample)
delta = (i + fractional_step) / float(n_steps)
t = interval * delta
g_t = a * exp(b * t)
print t, 3 * sin(g_t)
sweep(16000.0, 16500.0, 256.0/48000.0, 256) # looks strange
sweep(16000.0, 16500.0, 256.0/48000.0, 256, 4) # looks fine with better resolution
If you check the code you'll see that all that setting n_oversample
to 4 does (the second call) is add a higher resolution to the timesteps. In particular, the code when oversample = 0
(ie fractional_step = 0
) is identical to before, so the second plot includes the points in the first plot, plus extra ones that "fill in" the missing data and make everything look much less surprising.
Here's a close-up of the original and the oversampled curve near the start, showing what is happening in detail:
Finally, this kind of thing is completely normal and does not indicate any kind of error. When an analogue signal is generated from the digital waveform you'll get "the right" result (assuming the hardware is working right). This excellent video will explain things if they are not clear.