Every once in a while, I want to generate some pure sine waves for audio purposes, and I have to go digging around to find this simple technique, so I thought I would write it down here. Suppose that you are trying to generate a 440Hz (middle A, if memory serves) sine wave sampled at 44.1Khz. The expensive way would look like this:
double t = 0.0 ; /* time begins at zero */ double omega = 0.0 ; /* angle is zero */ double dt = 1.0 / 44100 ; /* each sample advances time by dt */ double domega = dt * 440.0 * 2.0 * M_PI ; /* the angle advances by domega */ for (;;) { output(sin(omega)) t += dt ; omega += domega ; }
(Yes, yes, astute readers will note that t
isn’t needed. So sue me.) This requires a single call to sin
for each sample. On my little Via box, a call to sin takes about .584 microseconds, so you can generate over 1.7 million samples per second with this technique. Not bad, but we can do better. Much better.
The key is to remember this recurrence relationship:
(Formula courtesy of Don Cross)
You can compute samples of simple sine waves very fast using this technique, since it takes only a multiply and a subtract per sample. On my machine, that turns down to about 7 nanoseconds per sample. That is a speedup of over 84x.
Unnecessary? Perhaps, but it is still cool.
Why am I looking at this? Stay tuned.