What is the most efficient way to generate a signed float array of arbitrary length containing the amplitude (represented from 1 to -1) of a sine wave in C?
If you want no runtime overhead, write yourself a little program that prints out all your values as a C array declaration/initialization, and then #include
that file into your program.
As Carl Smotricz pointed out in his answer, you can easily write a simple C program to build a hard-coded array for you.
The following code would do the trick:
int main(int argc, char * argv[])
{
const int tableSize = 10;
const char * fileName = "sin_table.txt";
int x;
FILE * file;
file = fopen(fileName, "w");
if (file == NULL) { printf("unable to open file\n"); return -1; }
fprintf(file, "float sin_table[%d] =\n{\n ", tableSize);
for (x = 0; x < tableSize; x++)
{
fprintf(file, "\t%f,\n", sinf(x*2*pi/tableSize));
}
fprintf(file, "};\n");
fclose(file);
return 0;
}
And the output would look like this:
float sin_table[10] =
{
0.000000,
0.587785,
0.951057,
0.951056,
0.587785,
-0.000000,
-0.587785,
-0.951057,
-0.951056,
-0.587785,
};
If you want something very fast use a table (as already suggested).
Another approach is to simulate a little sine-oscillator and use it to generate your data-array.
Here is an example how to do this:
int main (int argc, char **args)
{
int i;
float data[1024];
float angle = 2.0f * 3.14 / 1024;
// start of the sine-wave:
float sinval = 0;
float cosval = 1;
// rotation per iteration
float delta_sin = sinf(angle);
float delta_cos = cosf(angle);
for (i=0; i<1024; i++)
{
// store current value:
data[i] = sinval;
// update the oscillator:
float s = sinval * delta_cos - cosval * delta_sin;
float c = sinval * delta_sin + cosval * delta_cos;
sinval = s;
cosval = c;
}
}
The trick behind this is, that we start with a fixed point in 2D-space, stored in 9sinval, cosval). Furthermore I precompute the parameters for a single rotation in (delta_cos, delta_sin).
All I do in the loop is to rotate the point 1024 times with the fixed rotation. This creates a sin/cos pair per iteration. (note: it's the same as a complex multiplication).
This method becomes unstable sooner or later and is not as exact as calling sin/cos in the loop.
So it's not a good idea to create huge tables with it, but if you can live with a slight error and smallish tables up to ten thousand elements it's quite usable. To get around that issue you could change the type to double, do proper rounding or re-normalize the result every n iterations.
Edit: Just tested the code with double and 1e9 iterations. Works for me. I have a slight drift in the phase, but the results are still more exact than using single precision sinf/cosf.