首页 > 解决方案 > 用于实时信号处理的快速 C++ 正弦和余弦替代方案

问题描述

我需要实现一个实时同步正交检测器。检测器接收输入数据流(来自 PCI ADC)并返回谐波幅度w。有简化的 C++ 代码:

double LowFreqFilter::process(double in)
{
   avg = avg * a + in * (1 - a);
   return avg;
}


class QuadroDetect
{
   double wt;
   const double wdt;

   LowFreqFilter lf1;
   LowFreqFilter lf2;

   QuadroDetect(const double w, const double dt) : wt(0), wdt(w * dt)
   {}

   inline double process(const double in)
   {
      double f1 = lf1.process(in * sin(wt));
      double f2 = lf2.process(in * cos(wt));
      double out = sqrt(f1 * f1 + f2 * f2);
      wt += wdt;
      return out;
   }
};

我的问题是,sin计算cos需要太多时间。有人建议我使用预先计算好的sin表格cos,但可用的 ADC 采样频率不是 的倍数w,因此存在片段拼接问题。是否有任何快速的替代方案sincos计算?我将不胜感激有关如何提高此代码性能的任何建议。

UPD 不幸的是,我的代码错了,去掉了过滤调用,代码就失去了意义。谢谢埃里克·波斯特皮希尔。

标签: c++optimizationsignal-processingtrigonometry

解决方案


我知道一个适合您的解决方案。回想一下关于角度和的正弦和余弦的学校公式:

sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)

假设这wdt是角度的一个小增量,那么我们得到下一次的和wt的递归计算公式:sincos

sin(wt + wdt) = sin(wt) * cos(wdt) + cos(wt) * sin(wdt)
cos(wt + wdt) = cos(wt) * cos(wdt) - sin(wt) * sin(wdt)

我们只需要计算一次sin(wdt)cos(wdt)值。对于其他计算,我们只需要加法和乘法运算。递归可以从任何时刻开始,因此我们可以用精确计算的值逐次替换,以避免无限期的错误累积。

有最终代码:

class QuadroDetect
{
   const double sinwdt;
   const double coswdt;
   const double wdt;

   double sinwt = 0;
   double coswt = 1;
   double wt = 0;

   QuadroDetect(double w, double dt) :
      sinwdt(sin(w * dt)),
      coswdt(cos(w * dt)),
      wdt(w * dt)
   {}

   inline double process(const double in)
   {
      double f1 = in * sinwt;
      double f2 = in * coswt;
      double out = sqrt(f1 * f1 + f2 * f2);

      double tmp = sinwt;
      sinwt = sinwt * coswdt + coswt * sinwdt;
      coswt = coswt * coswdt - tmp * sinwdt;

      // Recalculate sinwt and coswt to avoid indefinitely error accumulation
      if (wt > 2 * M_PI)
      {
         wt -= 2 * M_PI;
         sinwt = sin(wt);
         coswt = cos(wt);
      }

      wt += wdt;
      return out;
   }
};

请注意,这种递归计算提供的结果不如 准确sin(wt) cos(wt),但我使用了它并且效果很好。


推荐阅读