c++ - 用于实时信号处理的快速 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
,因此存在片段拼接问题。是否有任何快速的替代方案sin
和cos
计算?我将不胜感激有关如何提高此代码性能的任何建议。
UPD 不幸的是,我的代码错了,去掉了过滤调用,代码就失去了意义。谢谢埃里克·波斯特皮希尔。
解决方案
我知道一个适合您的解决方案。回想一下关于角度和的正弦和余弦的学校公式:
sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
假设这wdt
是角度的一个小增量,那么我们得到下一次的和wt
的递归计算公式:sin
cos
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)
,但我使用了它并且效果很好。
推荐阅读
- wordpress - 找不到WordPress自定义MD5 slug页面
- r - R / Mongolite:如何$展开数据框?
- excel - 创建 Excel 费用跟踪器
- c# - Json.net ContractResolver
- java - 有没有办法转换 FindIterable
成 JSONArray 字符串? - azure - Azure API“忘记”默认组
- ruby-on-rails - ruby on rails - 问题 bundle install nokogiri 1.7.2 on ruby on rails 4.x
- javascript - 获取对象数组并排序为按字母顺序排序的较小数组
- angular - Angular2+ 渲染一个完全没有任何包装标签的组件
- wordpress - 无法将特色图像添加到自定义分类中