gpt4 book ai didi

c - 在不使用标准函数的情况下在 C 中生成正弦信号

转载 作者:太空狗 更新时间:2023-10-29 16:23:33 26 4
gpt4 key购买 nike

我想在不使用标准函数 sin() 的情况下在 C 中生成正弦信号,以便触发 LED 亮度的正弦形变化。我的基本想法是使用具有 40 个点和插值的查找表。

这是我的第一种方法:

const int sine_table[40] = {0, 5125, 10125, 14876, 19260, 23170, 26509, 29196,
31163, 32364, 32767, 32364, 31163, 29196, 26509, 23170, 19260, 14876, 10125,
5125, 0, -5126, -10126,-14877, -19261, -23171, -26510, -29197, -31164, -32365,
-32768, -32365, -31164, -29197, -26510, -23171, -19261, -14877, -10126, -5126};

int i = 0;
int x1 = 0;
int x2 = 0;
float y = 0;

float sin1(float phase)
{
x1 = (int) phase % 41;
x2 = x1 + 1;
y = (sine_table[x2] - sine_table[x1])*((float) ((int) (40*0.001*i*100) % 4100)/100 - x1) + sine_table[x1];
return y;
}

int main()
{
while(1)
{
printf("%f ", sin1(40*0.001*i)/32768);
i = i + 1;
}
}

不幸的是,这个函数有时会返回远大于 1 的值。此外,插值似乎不太好(我用它来创建 LED 的正弦形亮度变化,但这些非常不平滑)。

有人有更好的主意用 C 语言实现正弦发生器吗?

最佳答案

OP 的主要问题是为表查找生成索引。

OP 的代码尝试访问外部数组 sine_table[40] 导致 undefined behavior .至少解决这个问题。

const int sine_table[40] = {0, 5125, 10125, ...
...
x1 = (int) phase % 41; // -40 <= x1 <= 40
x2 = x1 + 1; // -39 <= x2 <= 41
y = (sine_table[x2] - sine_table[x1])*... // bad code, consider x1 = 40 or x2 = 40,41

建议的更改

    x1 = (int) phase % 40;   // mod 40, not 41
if (x1 < 0) x1 += 40; // Handle negative values
x2 = (x1 + 1) % 40; // Handle wrap-around
y = (sine_table[x2] - sine_table[x1])*...

存在更好的方法,但要关注 OP 的方法,请参见下文。

#include <math.h>
#include <stdio.h>

const int sine_table[40] = { 0, 5125, 10125, 14876, 19260, 23170, 26509, 29196,
31163, 32364, 32767, 32364, 31163, 29196, 26509, 23170, 19260, 14876, 10125,
5125, 0, -5126, -10126, -14877, -19261, -23171, -26510, -29197, -31164, -32365,
-32768, -32365, -31164, -29197, -26510, -23171, -19261, -14877, -10126, -5126 };

int i = 0;
int x1 = 0;
int x2 = 0;
float y = 0;

float sin1(float phase) {
x1 = (int) phase % 40;
if (x1 < 0) x1 += 40;
x2 = (x1 + 1) % 40;
y = (sine_table[x2] - sine_table[x1])
* ((float) ((int) (40 * 0.001 * i * 100) % 4100) / 100 - x1)
+ sine_table[x1];
return y;
}

int main(void) {
double pi = 3.1415926535897932384626433832795;
for (int j = 0; j < 1000; j++) {
float x = 40 * 0.001 * i;
float radians = x * 2 * pi / 40;
printf("%f %f %f\n", x, sin1(x) / 32768, sin(radians));
i = i + 1;
}
}

输出

         OP's     Reference sin()
0.000000 0.000000 0.000000
0.040000 0.006256 0.006283
0.080000 0.012512 0.012566
...
1.960000 0.301361 0.303035
2.000000 0.308990 0.309017
2.040000 0.314790 0.314987
...
39.880001 -0.020336 -0.018848
39.919998 -0.014079 -0.012567
39.959999 -0.006257 -0.006283

更好的代码不会将值 i, x1, x2, y 作为全局变量传递,而是作为函数参数或函数变量传递。也许这是 OP 调试的产物。


Does anybody have a better idea to implement a sine generator in C?

这是相当广泛的。在速度、精度、代码空间、可移植性或可维护性方面更好? sine() 函数很容易制作。高质量的需要更多的努力。

虽然模糊,但 OP 使用小型查找表是一个好的开始 - 虽然我认为它可以在没有任何 float 学的情况下完成。我建议 OP 构建一个经过测试且有效的解决方案并将其发布在 Code Review 中寻求改进意见。

关于c - 在不使用标准函数的情况下在 C 中生成正弦信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47906401/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com