避免浮点运算

Tho*_*ing 3 iphone signal-processing fixed-point core-audio integer-division

我为 iPhone 编写了一个小型软件合成器。为了进一步调整性能,我使用 Shark 测量了我的应用程序,发现我在转换方面损失了大量时间float/SInt16

因此,我重写了一些部分,通过预先计算返回“即用型”SInt16样本的查找表来绕过转换。到目前为止效果很好。

目前,我正在尝试重写一些过滤器和我的 ADSR 包络实现,以仅使用整数算术,但我可以使用一些关于如何在没有浮点数的情况下执行乘法/除法的技巧。
我的目标是iPhone 规范格式

  • 线性PCM
  • 16 位整数样本

在不使用浮子的情况下将振幅应用于最终样本的好方法是什么?

编辑:
到目前为止我唯一想到的是,我可以通过右移当前样本来除以 2 的幂。

inBuffer[frame] = wavetable[i % cycleLengthInSamples] >> 4;
Run Code Online (Sandbox Code Playgroud)

但我想不出任何优雅的方法来创建平滑的 ADSR 信封。

Edit2: 感谢您的所有精彩回答!
我目前的做法:

  • 将我所有的 ADSR 包络值带入正SInt16范围
  • 乘以波表中的当前值(将中间值存储为SInt32
  • 将结果右移16

这似乎有效:)

pat*_*ros 5

定点很好,因为在本例中您使用的是 16 位。最简单的方法是根据您需要的精度乘以 10 的幂。如果您可以使用 32 位整数作为中间值,您应该能够获得不错的精度。最后,您可以根据需要转换回 16 位 int、四舍五入或截断。

编辑:您想要向左移动,以使值更大。将移位结果存储为更精确的类型(32 或 64 位,具体取决于您的需要)。如果您使用签名类型,简单的移位将不起作用

请注意是否要对两个定点数进行乘法或除法。相乘得到 (a*n) * (b n) 并且你会得到 a b n^2 而不是 a b n。除法是 (a n) / (b n),即 (a/b) 而不是 ((a n)/b)。这就是为什么我建议使用 10 的幂,如果你不熟悉定点,可以很容易地发现你的错误。

完成计算后,您将向右移回 16 位 int。如果你想变得更花哨,你也可以在移动之前进行四舍五入。

如果您确实对实现高效定点感兴趣,我建议您阅读一些内容。http://www.digitalsignallabs.com/fp.pdf