Subject: Trick : Tone Generation From: Darrell <darrell@havoc.gtf.org> Date: 1999/04/19 Newsgroups: comp.dsp THIS WORK IS PLACED IN THE PUBLIC DOMAIN
Name: Sinusoidal tone generator
Category: Algorithm
Application: If they need to generate a continuous tone of specific frequency and amplitude.
Advantages: Fast and accurate.
Introduction:
I’ve seen this trick in a few different places, although never the (very simple) deriviation. It is based on the z-transform for sin(wn).
The Trick:
-1 sin(w)*z y(w) = F{sin(wn)} = ---------------------- [1, pg. 159] -1 -2 1 - cos(w)*z + z -1 -2 -1 y(w)*[1 - 2*cos(w)*z + z ] = sin(w)*z
Taking the inverse z-transform:
y[n] - 2*cos(w)*y[n-1] + y[n-2] = sin(w)*delta[n-1] = 0 y[n] = 2*cos(w)*y[n-1] - y[n-2]
Solving for the initial conditions (start at n=1 since y[0] and y[-1] are so trivial to compute):
y[0] = sin(0) = 0 Ft Ft y[-1] = sin(-w) = sin(-2*pi*--) = -sin(2*pi*--) Fs Fs
where Ft is the tone frequency and Fs is the sampling frequency. For example, to generate a 1 kHz tone with a sampling frequency of 8 kHz:
y[0] = 0 y[-1] = 1/sqrt(2) ~= 0.7071 cos(w) = 1/sqrt(2) ~= 0.7071 y[n] = 1.414*y[n-1] - y[n-2] n | y[n-2] | y[n-1] | y[n] ---+---------+---------+--------- 1 | 0.7071 | 0.0000 | -0.7071 2 | 0.0000 | -0.7071 | -1.0000 3 | -0.7071 | -1.0000 | -0.7071 4 | -1.0000 | -0.7071 | 0.0000 5 | -0.7071 | 0.0000 | 0.7071 6 | 0.0000 | 0.7071 | 1.0000 7 | 0.7071 | 1.0000 | 0.7071 8 | 1.0000 | 0.7071 | 0.0000
Note that all calculations were done with 64-bit floating point and rounded by hand.
The z-transform of this shows two poles on the unit circle at +/- pi/4 radians. I’ve never encountered stability issues but care should be taken to evaluate quantization effects on the system.
References:
[1] Discrete-Time Signal Processing [Opp89]