Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding sin() calls in audio synth

A naive sine wave generator takes a set of n values and calls the sin function on each of them:

for i = 0; i < 2*pi ; i = i+step {
    output = append(output, sin(i) )
}

However, this makes a lot of calls to a potentially expensive sin function, and fails to take advantage of the fact that all the samples are sequential, have been calculated previously, and will be rounded to an integer (PCM). So, what alternatives are there?

I'm imagining something along the lines of Bresenham's circle algorithm or pre-computing a high-res sample, and then downsizing by taking every n'th entry, but if there's an 'industrial strength' solution to this problem, I'd love to hear it.

like image 311
Dan Anderson Avatar asked Oct 01 '22 10:10

Dan Anderson


1 Answers

You can calculate the vector z which gives you (cos theta, sin theta) when you add to (1,0), where theta = 2*pi/step. Then you add this vector to (1,0) and get the next sin value as the y-coordinate of the sum. Then you rotate z by angle theta (by multiplying by the rotation matrix through angle theta) and add this to your previous vector (cos theta, sin theta), to get the next sin value as the y-coordinate of the resultant sum vector. And so forth. This requires computing cos theta and sin theta just once, and then each update is given by a matrix multiplication of a 2x2 matrix with a 2-d vector, and then a simple addition, which is faster than computing sin() using the power series expansion.

like image 87
user2566092 Avatar answered Oct 05 '22 07:10

user2566092