我在我的音频应用程序中应用Exponential Moving Average
作为平滑参数的过滤器:
a0 = 0.01
z += a0 * (input - z);
Here's代码和第一步50步:
#include <iostream>
int main ()
{
double a0 = 0.1;
double input = 0.8;
double z = 0.0;
std::cout << "init z: " << z << std::endl << std::endl;
for(int i=0; i < 50; i++) {
z += a0 * (input - z);
std::cout << z << std::endl;
}
std::cout << std::endl << "final z: " << z << std::endl;
}
我需要检查上一个平滑值是否与当前值相同,这意味着过滤器已经完成了#34;它的熏制过程,价值总是一样的。
但是z
总是会epsilon
与input
不同,所以我无法检查input == z
它始终是假的。 Here's一个例子,带有无限循环。
z
和input
之间的epsilon是什么?因此,如果它在该范围内,我可以检查并避免进一步的操作。
答案 0 :(得分:2)
考虑比率&#34; new z&#34;到&#34;老z&#34;,少1:
(z + a(i - z)) / z - 1
(显然简化为ia / z - a
)。如果这个数量小于1e-6
,那么接受完成。如果z
为零,则始终继续。将此乘法容差调整为适合您要求的容差。
(从科学角度来说,容差与数据流的标准偏差相关 - 我敢建议甚至比例 - 但我无法在不研究实际数据的情况下提供更多提示。 )
答案 1 :(得分:2)
对于音频应用程序,您需要考虑采样的位数,以了解结果何时无法听到。每个位表示2的幂。例如,16位将是2 16 或65536,因此适当的epsilon将是您的样本比例除以65536.对于20位,它是2 20 < / sup>或1048576。
这些限制明显大于大多数其他应用程序所需的限制。
答案 2 :(得分:1)
而是检查z
和input
之间的epsilon,您可以在z
的新值与前一个值之间进行检查。
答案 3 :(得分:-4)
在C ++中有
std::numeric_limits<double>::epsilon()
返回机器epsilon,即1.0和浮点类型T可表示的下一个值之间的差值。
修改后的代码:
#include <iostream>
int main()
{
int counter = 0;
double a0 = 0.1;
double input = 0.8;
double z = 0.0;
std::cout << "init z: " << z << std::endl << std::endl;
while (true) {
z += a0 * (input - z);
std::cout << counter++ << " | process: " << z << std::endl;
double eps = std::numeric_limits<double>::epsilon();
double diff = abs(z - input);
if (diff <= 2 * eps) {
break;
}
}
std::cout << std::endl << "final z: " << z << std::endl;
}