[sdiy] Approximating sine with plain integer math
John Ames
commodorejohn at gmail.com
Thu Apr 7 04:57:29 CEST 2016
On 4/6/16, rsdio at audiobanshee.com <rsdio at audiobanshee.com> wrote:
> Your code is fine from -180 degrees to +180 degrees, which sort of solves
> the 270-degree overflow. It seems to be valid for exactly one period of the
> ramp wave input, from negative peak to positive peak, then it falls apart.
Yes, I suppose I should've been clearer on that. If you graph the
function provided in the original post, it goes completely off the
rails outside of the -1 to +1 range, since the square of X gets larger
than 1. However, in application, the sawtooth input never exceeds that
range anyway.
(Also, the overflow would've been at +90 degrees in your reckoning, so
definitely an issue.)
On 4/6/16, Brian Willoughby <brianw at audiobanshee.com> wrote:
> I've been using a State Variable Filter (a.k.a. Quadrature Oscillator) with
> fixed resonance to generate sine waves at arbitrary frequencies. You should
> be able to implement the SVF in fixed point or integer math, avoiding
> floating point as you desire.
>
> Your latest code uses 3 multiply, 1 divide, 1 subtract, and 2 branches (the
> ?: operator).
> I believe that the SVF can be implemented with only 2 multiply and 1 add.
> It's rather significant that there are no branches in the SVF calculations,
> because most pipelined processors lose performance when branching. Some
> processor instruction sets, such as the PowerPC AltiVec, have single opcodes
> that can pick one of two results based on a condition, allowing things like
> "(saw < 0) ? -1 : 1" to be implemented without flushing the pipeline, but
> it's far easier to work with algorithms that don't branch at all, assuming
> you want performance.
>
> Granted, one of your multiply operations can be implemented as a 2-bit shift
> (i.e. * 4). However, that divide instruction could be expensive unless you
> use fixed point fractions and multiply by the equivalent of 1/INT_MAX. That
> makes your algorithm 3 multiple, 1 2-bit shift, 1 subtract, and 2 branches.
> Still a lot more than the SVF.
>
> My understanding is that using the SVF as a sine oscillator is fairly low
> distortion, but the distortion increases as the frequency approaches
> Nyquist. I have never measured the distortion of this code, but it would be
> vary interesting to compare to your 5% odd-harmonic distortion, especially
> if the distortion can be mapped versus frequency.
>
> I've used SVF sine generation for FM, but not for pure synthesis. Does
> anyone have experience with the SVF in this application? I optimized my code
> to remove all of the excess calculations needed to produce all 4 outputs of
> the SVF, since I only needed the 1 output.
Interesting. Do you have any more information on this technique? My
only attempt to use filtering to derive a sine wave (from a triangle)
had the unfortunate side-effect of decreasing the amplitude rather
drastically as the frequency approached Nyquist.
More information about the Synth-diy
mailing list