【发布时间】:2014-04-17 01:11:18
【问题描述】:
我正在尝试在 C# 中使用 IIR LP 滤波器。它是一个五阶巴特沃斯滤波器。 该代码在 64 位模式下工作,但在 32 位模式下中断。调试显示,参数略有不同,输出提高到无穷大/NAN。 我使用双打进行计算和存储。 正确的参数a[i],b[i]是:
-5 -4,9792522401964
10 9,91722403267282
-10 -9,87615728025693
5 4,91765142871949
-1 -0,979465940928259
32Bit 计算得到这些:
-5 -4,97925281524658
10 9,91722583770752
-10 -9,87615966796875
5 4,91765308380127
-1 -0,979466378688812
过滤代码:
public void FilterBuffer(float[] srcBuf, long srcPos, float[] dstBuf, long dstPos, long nLen)
{
const double kDenormal = 0.000000000000001;
double denormal = m_invertDenormal ? -kDenormal : kDenormal;
m_invertDenormal = !m_invertDenormal;
for (int sampleIdx = 0; sampleIdx < nLen; sampleIdx++)
{
double sum = 0.0f;
m_inHistory[m_histIdx] = srcBuf[srcPos + sampleIdx] + denormal;
for (int idx = 0; idx < m_aCoeff.Length; idx++)
sum += m_aCoeff[idx] * m_inHistory[(m_histIdx - idx) & kHistMask];
for (int idx = 1; idx < m_bCoeff.Length; idx++)
sum -= m_bCoeff[idx] * m_outHistory[(m_histIdx - idx) & kHistMask];
m_outHistory[m_histIdx] = sum;
m_histIdx = (m_histIdx + 1) & kHistMask;
dstBuf[dstPos + sampleIdx] = (float)sum;
}
}
历史记录是 32 个条目,因此 histMask 为“31”以避免模数/比较...
任何想法为什么这不起作用以及如何使其稳定?
【问题讨论】:
-
如果这样的精度很重要,您是否尝试过使用
decimal而不是float和double? -
我实际上不需要那么精确。双重承诺几个小数。但在这种情况下,大约 7 位有效数字之后就完全错误了。例如:Math.Tan(0.5 * Math.PI * f1 / m_fN) --> 括号中的值是 1,56759062000552(64Bit) 和 1,56759071350098(32Bit) 我担心使用小数会大大降低算法速度。同样在 64 位模式下也不需要...
-
您至少可以试一试,然后测试性能。您还可以根据架构使用预处理器指令交换
double/decimal(假设您正在构建特定于平台的可执行文件。 -
在上述代码(包括缓冲区)中使用小数确实有效。然而,在发布模式下性能下降了 100 倍(实际上 64 位比 32 位要差一些)所以这不是一个选项。还有其他想法吗?
标签: c# signal-processing lowpass-filter