简体   繁体   English

如何在C中生成固定波形表?

[英]How do I generate a fixed-waveform table in C?

生成包含C中正弦波幅度(由1到-1表示)的任意长度的有符号浮点数组的最有效方法是什么?

As Carl Smotricz pointed out in his answer , you can easily write a simple C program to build a hard-coded array for you. 正如Carl Smotricz在他的回答中指出的那样,你可以轻松编写一个简单的C程序来为你构建一个硬编码数组。

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). 这背后的诀窍是,我们从2D空间中的一个固定点开始,存储在9sinval,cosval)。 Furthermore I precompute the parameters for a single rotation in (delta_cos, delta_sin). 此外,我预先计算了(delta_cos,delta_sin)中单个旋转的参数。

All I do in the loop is to rotate the point 1024 times with the fixed rotation. 我在循环中所做的就是用固定的旋转将点旋转1024次。 This creates a sin/cos pair per iteration. 这会在每次迭代时创建一个sin / cos对。 (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. 这种方法迟早会变得不稳定,并不像在循环中调用sin / cos那样精确。

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. 要解决该问题,您可以将类型更改为double,进行适当的舍入或每n次迭代重新规范化结果。


Edit: Just tested the code with double and 1e9 iterations. 编辑:刚用双重和1e9迭代测试代码。 Works for me. 适合我。 I have a slight drift in the phase, but the results are still more exact than using single precision sinf/cosf. 我在相位上略有漂移,但结果仍然比使用单精度sinf / cosf更精确。

如果你不想要运行时开销,请自己编写一个程序,将所有值打印出来作为C数组声明/初始化,然后#include该文件到你的程序中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM