DSP Trick: Sinusoidal Tone Generator

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 and y[-1] are so trivial to compute):

y  = 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
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:

 Discrete-Time Signal Processing [Opp89]