正弦近似

时间:2013-06-19 20:31:13

标签: c

我试图仅使用整数并且不使用表来近似sin函数。

为每个步骤调用该函数。我已经在matlab中成功地对它进行了近似,但是我的C代码出了点问题。由于某些原因,我得到错误的频率读数,并且该功能不适用于所有频率。

typedef volatile struct tone_s{
    int32_t impulse;
    int32_t acceleration; 
    int32_t rollover;
    int32_t velocity;
    int32_t phase;
    int32_t counter; 
    int32_t position_acc; 
    int32_t velocity_acc; 
}tone_t; 

static void Osc_Init(tone_t *osc, uint32_t frequency, uint32_t sample_rate){
    int32_t max_int = (1UL << 16); 
    frequency *= 4UL; 

    osc->impulse = (max_int * frequency);
    osc->acceleration = max_int/sample_rate * frequency * frequency;
    osc->rollover = (sample_rate * 2UL / frequency);
    osc->velocity = osc->impulse - (osc->acceleration / 2UL);
    osc->velocity_acc = osc->velocity; 
    osc->phase = -1UL;
    osc->counter = 0; 
    osc->position_acc = 0; 

}

#include <stdio.h>

static int16_t Osc_GenSample(tone_t *osc){
    if(osc->counter == osc->rollover){
        osc->velocity_acc = osc->velocity;
        osc->position_acc = 0;
        osc->phase = -osc->phase;
        osc->counter = 0; 
    }

    int32_t sample = (osc->position_acc / 4194304UL) * osc->phase;

    osc->position_acc += osc->velocity_acc;  
    osc->velocity_acc -= osc->acceleration; 

    osc->counter++; 

    //fprintf(stdout, "%d - %d %d %d %d %d %d %d\n", sample, osc->impulse, osc->acceleration, osc->velocity, osc->rollover, osc->position_acc, osc->velocity_acc, osc->counter); 
    return sample; 
}

也许我过于复杂了。

3 个答案:

答案 0 :(得分:3)

请参阅Hakmem items 149 to 152,了解以渐进方式绘制圆的方法(当然,这给出了正弦),算法很少。

答案 1 :(得分:1)

注意到所有常量都声明为UL,即无符号长,您可以尝试使用int64_t代替int32_t进行计算。 (只是一个猜测。)

答案 2 :(得分:0)

Steve Hollasch维护了一个关于使用sin/cos recurrence relations进行增量更新的页面。如果你坚持的话,我想你可以将它调整到16.16固定点;但如果您只是想避免sinf来电,则仍应使用float

我不清楚你的代码应该如何工作。乘法看起来很可疑 - 容易溢出;截断分区肯定会引入大错误,例如,

int32_t sample = (osc->position_acc / 4194304UL) * osc->phase;

如果:(position_acc % 4194304UL) == 4194304UL - 1,请考虑引入的错误。您可以通过关联性来缓解这种情况 - 首先乘以,然后除以 - 但int32_t会保持结果吗?也许你需要考虑int64_t来获得中间结果。

这是为什么平台?