不动点:out_Q15 = antilog( in_Q25 ) 计算,避免溢出?

Fixed-point: out_Q15 = antilog( in_Q25 ) calculation, avoiding overflow?

我正在使用第 3 方定点 antilog() 函数从分贝 out_mag = 10^( in_db/20 ) 计算幅度。 antilog()Q6.25 格式作为输入,并在输出时提供 Q16.15

问题是 antilog() 很快溢出一些更高的 dB 值,比如 100 dB:10^( 100/20 ) = 100000Q16.15 格式的最大值是 2^16-1=65535,因此 100000 不适合。

有没有避免溢出的技巧?不知何故预分频输入值?

我设法找到了解决方案。这有点棘手。

首先,需要一个保存输出结果的结构:

typedef struct
{
    q15   v; // Value (within the [MIN, MAX] range for Q16.15).
    int32 s; // Scalefactor.
} q15_t;

想法是提供结果作为带有比例因子的输出,其中

Output = 10^y
Scale  = 2^scalefactor

最终输出 Output 左移 scalefactor 次。

这是数学。​​

输入 Q31 格式是 dB 值缩放到 [-1,1],比例为 2^scalefactor。 我们需要计算:

Out = 10^(2^scalefactor * in/20.0)

    = 10^(p+y)                  // rewriting as sum
    = 10^p          * 10^y      // to enable exponent multiplication
    = 2^scalefactor * 10^y      // making it power of 2 to be able to just shift

这样我们就不受Q16.15最大值的限制了。

我们已经知道2^scalefactor,但需要找到y

2^scalefactor * in = p + y

10^p = 2^scalefactor   =>   p = scalefactor*log(2)   // rewrite as power of 2
2^scalefactor * in = scalefactor*log(2) + y          // replace p
y = 2^scalefactor*in - scalefactor*log(2)            // and find y

计算 y,并将其输入 antilog

如果输入是100 dB,那么输出幅度应该是100.000,这不符合Q16.15格式。使用上面的解决方案,Output = 50.000(这适合 Q16.15!)和 scalefactor = 1,意思是,最终输出是 50.000 移到左 1 的地方。这给出了 100.000 作为最终结果。根据您的实施,您可能会得到与 25.000scalefactor = 2 等相同的结果。这个想法就在那里。