【发布时间】:2012-03-06 08:35:21
【问题描述】:
我正在使用 Perry Cook 的合成工具包 (STK) 来生成锯齿波和方波。 STK 包括这个基于 BLIT 的锯齿波振荡器:
inline STKFloat BlitSaw::tick( void ) {
StkFloat tmp, denominator = sin( phase_ );
if ( fabs(denominator) <= std::numeric_limits<StkFloat>::epsilon() )
tmp = a_;
else {
tmp = sin( m_ * phase_ );
tmp /= p_ * denominator;
}
tmp += state_ - C2_;
state_ = tmp * 0.995;
phase_ += rate_;
if ( phase_ >= PI )
phase_ -= PI;
lastFrame_[0] = tmp;
return lastFrame_[0];
}
方波振荡器大体相似。在顶部,有这样的评论:
// A fully optimized version of this code would replace the two sin
// calls with a pair of fast sin oscillators, for which stable fast
// two-multiply algorithms are well known.
我不知道从哪里开始寻找这些“快速二乘算法”,我希望能得到一些指点。我可以改用查找表,但我很想了解这些“快速正弦振荡器”是什么。我也可以使用一个缩写的泰勒级数,但这不仅仅是两个乘法。尽管我确实找到了这个近似值,但搜索并没有发现太多东西:
#define AD_SIN(n) (n*(2.f- fabs(n)))
绘制出来表明它并不是-1到1范围之外的真正近似值,所以我认为当phase_在-pi到pi范围内时我不能使用它:
这里,正弦是蓝线,紫线是近似值。
分析我的代码显示,对sin() 的调用是最耗时的调用,所以我真的很想优化这部分。
谢谢
编辑感谢您提供详细而多样的答案。我将探索这些并在周末接受一个。
编辑 2 请匿名的近距离投票者解释他们在 cmets 中的投票吗?谢谢。
【问题讨论】:
-
我很惊讶锯齿振荡器需要三角函数计算。
-
奥利查尔斯沃思,他们不应该。理想的方齿和锯齿振荡器很容易用简单的代数建模。我的猜测是,他们可能正在尝试模拟不太理想的物理振荡器。对于锯齿,这通常作为正弦波的总和来完成。
-
@NathanErnst 使用这些函数的原因与物理振荡器建模无关。相反,这是因为“纯”锯波具有无限谐波。任何高于采样频率 (44100/2) 一半的谐波都会导致混叠效果,听起来非常可怕。这种技术在此处生成一个“频带受限”或抗混叠锯齿,其中谐波得到控制。
-
@Tim:只有在没有抗锯齿过滤器的情况下进行下采样时才会发生这种情况。根据定义,您不能生成高于奈奎斯特频率的谐波。
-
当然,可以生成高于“奈奎斯特”的频谱,例如对足够带限的高频信号进行欠采样(并通过反之重建)。然而,当不受频带限制时,这通常被称为噪声,理想的低通滤波三角波或方波试图消除它。
标签: c++ algorithm math signal-processing