# Introduction

When implementing digital oscillators or filters, a simple way of calculating for is needed. Efficiency, in terms of the number of CPU cycles or hardware complexity, is favoured above accuracy. Several methods are known that produce good approximations to . These methods can be divided into three categories: table-lookup algorithms, approximation functions and recursive resonator algorithms.

Table-lookup algorithms are cycle efficient and their accuracy can be easily increased by increasing the number of table entries. Accuracy can also be increased by introducing interpolation between table entries.

In some memory limited situations, such as small microcontroller and DSP targets, a table is undesirable and an approximation based on functions is preferred.

Here, I will show how to approximate based on a simple polynomial.

# Approximating sin(2*pi*x)

The well known Taylor series seems a good candidate for obtaining a polynomial that approximates well. However, the approximation gets worse the further away the function argument gets from the point from which the series was derived. This generates a discontinuity when “wraps around”. To avoid such discontinuities, the approximation must produce the same value for and .

An interesting candidate is the polynomial , which approximates quite well for . The other half of the sinusoid is simply generated by mirroring the polynomial and adjusting for the offset, resulting in .

# How good is it?

The approximation is accurate to within +/- 6% of the total amplitude as is shown by the graphs below:

In sound synthesis and radio applications it is desirable to have low spurious tones. The following graph shows the spectrum of the approximated sinusoidal wave. It was generated using an 65536-point FFT and 2129 sine wave periods.

The spectrum is free of all even harmonics as the approximation is point symmetrical and the “grass” is due to high frequency components aliasing to lower frequencies. The first major spurious response is the third harmonic, which is found at -28.6 dBc.

# Show me the code!

/* Fast sin(2*pi*x) approximation. The caller must make sure that the argument lies within [0..1). Note: this can be optimized further by using Horner's rule for evaluating polynomials, see: http://en.wikipedia.org/wiki/Horner%27s_method Omitted here for clarity. */ float fast_sin(float x) { if (x < 0.5f) { return -16.0f*x*x + 8.0f*x; } else { return 16.0f*x*x - 24.0f*x + 8.0f; } };

# Conclusion

This may not be the world’s best sin approximation, but it sure is simple. Next time we’ll look at a more accurate polynomial-based sin approximation.