我想生成一个具有时间相关频率的正弦信号,该信号在fmin
和fmax
之间定期变化,在C中频率为f0
。在数学上,这可以用
y(t)=1/2*(1+sin(2*Pi*(fmin*t + (fmax-fmin)*1/2*(t - 1/2/Pi/f0*cos(2*Pi*f0*t) + 1/2/Pi/f0))))
因为我想在微控制器上使用它,我想减少浮点数的使用,以节省内存并提高性能。
这也是我无法使用标准正弦函数的原因。为了计算正弦函数,我用抛物线近似它。因此,我使用以下代码:
输入范围[0R2πR]映射到[0到1024]。
输出范围[-1.0 1.0]映射到[-512 512]。
int_fast16_t sin_bam(int angle_bam) {
angle_bam %= 1024;
if (angle_bam < 0)
angle_bam += 1024;
uint_fast16_t sub_angle = angle_bam % (1024u / 2);
int_fast16_t sn = (uint32_t) (sub_angle*(1024/2 - sub_angle) / 128);
if (angle_bam & 512) {
sn = -sn;
}
return sn;
}
我实现上述信号的第一种方法是
y(i) = sin_bam(fmin*i+(fmax-fmin)*(i-2/f0*sin_bam((int) (f0*i+1024/4))+1024/f0))+512.
对于大约f0 >= 1
的值,这很有效,但是对于较小的值,我的代码似乎会破坏,例如对于f0 = 0.1
,每次达到最小频率时,生成的信号变得非常“不平滑”。
这里有一个示例输出:
我认为问题可能是正弦函数的整数实现,因为它读取的是f0 = 0.1
sin_bam((int) (0.1*i+1024/4)).
这意味着,例如,对于0到9之间的i值,sin_bam((int)(0.1 * i + 1024/4))提供相同的输出。
我解决这个问题的第一个想法是增加正弦函数的角分辨率,但不幸的是,这没有帮助。
我的算法中是否存在任何逻辑错误,或者是否有人有更好的想法来实现它?