[sdiy] Approximating sine with plain integer math

Jay Schwichtenberg jays at aracnet.com
Thu Apr 7 01:45:41 CEST 2016


I would agree that using a "lookup table" with linear interpolation would be
better.

You only need a table of 0-90 degrees if memory for the table is limited.
Also you could pre-compute slopes and offsets for the linear interpolation
equation.

Jay S.

-----Original Message-----
From: Synth-diy [mailto:synth-diy-bounces at dropmix.xs4all.nl] On Behalf Of
Richie Burnett
Sent: Wednesday, April 06, 2016 4:28 PM
To: John Ames; synthdiy diy
Subject: Re: [sdiy] Approximating sine with plain integer math

Neat.  It's got quite a high distortion for a sinewave as you said, and has 
only odd harmonics present.  The waveform you have actually generated is the

integral of a triangle waveform.

As a triangle is the integral of a squarewave and has a steeper spectral 
roll-off, your waveform is the integral of the triangle waveform, and has an

even steeper spectral roll-off:

Square has odd harmonics only and -6dB/oct rolloff
Triangle has odd harmonics only and -12dB/oct rolloff
"John Ames' sinewave approx" has odd harmonics only and -18dB/oct rolloff.

You can play similar tricks with generating successive integrals of a 
sawtooth waveform, to get from sawtooth to parabola and then to something 
that looks sine-like and has a -18dB/oct rolloff, but has both odd and even 
harmonics present.  Technically inferior to your approximation because the 
THD is higher, but might sound nicer with even harmonics present!?!?

Did you consider a lookup-table with linear interpolation? ...that would be 
my method of choice for sinewave generation if I wanted low distortion.  You

can also get excellent results with low-order polynomial approximations with

or without range-reduction techniques to exploit the inherent symmetries of 
the sine function.  These can all be implemented with fixed-point 
arithmetic.  No need to go to floating point.

Good luck with your project!

-Richie,


-----Original Message----- 
From: John Ames
Sent: Wednesday, April 06, 2016 11:55 PM
To: synthdiy diy
Subject: [sdiy] Approximating sine with plain integer math

I'm working on a softsynth for a project, and one of my goals is to
avoid floating-point math (no particular reason other than just to see
if I can, but there's still architectures out there where it makes a
significant difference, so what the hey.) Initially I had compromised
on that when I needed a sine waveform for my oscillators, but today,
while playing around with a way to make the sawtooth less of a plain
linear ramp, I stumbled onto a way to generate what I think is quite a
satisfactory sine waveform using only a few integer operations. Since
I'm rather pleased with it and it might prove useful to somebody,
here's the algorithm:

1. Generate a sawtooth in the range -max to +max (i.e. -32768 to 32767
for a 16-bit integer.)
2. Square it.
3. Divide by +max (i.e. 32767.)
4. Multiply by the sign of the original value.
5. Subtract the original value.
6. Multiply by 4.
7. The result is inverted (or 180 degrees out-of-phase, if you want to
look at it that way,) so re-invert it if this is a problem for you. Or
just multiply by -4 in step 6.

There's probably a few different ways to implement this depending on
what kind of architecture you're doing it on, but here's a basic C
implementation:

#include <stdlib.h>
#include <limits.h>

/* sawToSine - takes a sawtooth sample as a signed integer and returns
the equivalent sine sample. */

int sawToSine(int saw)
{
    return ((((saw * saw) / INT_MAX) * (saw / abs(saw))) - saw) * -4;
}

>From a quick check with a graphing calculator (paste:

\left(\left(\left(x^2\cdot
\operatorname{sign}\left(x\right)\right)-x\right)\cdot -4\right)-\sin
\left(x\cdot \pi \right)

into https://www.desmos.com/calculator to see,) it looks like has a
maximum distortion of ~5.5% compared to a true sine, and it's actually
a little "fuller" and rounder, which I like. From a quick code test,
it maintains almost full peak-to-peak range and never overflows.

Whether this is any faster than using floating-point probably depends
on how expensive integer multiplies and divides are on your target
architecture, but I just thought it was interesting and wanted to
share :)
_______________________________________________
Synth-diy mailing list
Synth-diy at synth-diy.org
http://synth-diy.org/mailman/listinfo/synth-diy


-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 2016.0.7497 / Virus Database: 4545/11975 - Release Date: 04/06/16 

_______________________________________________
Synth-diy mailing list
Synth-diy at synth-diy.org
http://synth-diy.org/mailman/listinfo/synth-diy



More information about the Synth-diy mailing list