【问题标题】:Options for detecting zero cross of audio用于检测音频过零的选项
【发布时间】:2015-12-23 19:48:22
【问题描述】:

我有实时音频进来,我需要检测过零。

this question 所述的更简单的算法不能满足我的需要。该算法通过取当前项与前一项相乘的符号来检测过零。

这是此方法失败的一个简单示例:

-1, -0.5, 0, 0, 0.32, 0.5...

连续两个零,算法将失败。

这个方法是这样实现的:

int sign(float value) {
  if (value < 0) {
    return -1;
  } else if (value > 0) {
    return 1;
  }
  return 0;
}

for (int i=0; i<numFrames-1; i++) {
    int signR = sign(data[i+1] * data[i]);        
    if (signR == 0) printf("zero cross");
    // but this will fail for data[i+1] = data[i] = 0, for example

}

我还需要哪些其他算法选项来检测过零?

【问题讨论】:

  • 只需跟踪最后一个非零样本的符号即可。如果符号发生变化,则您有过零。
  • 请注意,浮点值很少等于零。您应该与 epsilon 或容差值进行比较,例如 1E-06;小于这个值的任何东西都被认为是零。
  • 我这样做了,结果是连续出现一堆零,因此无法检测到零交叉。
  • 您可能需要考虑使用定点数学来获得更好的准确性。
  • 了解为什么您想要检测过零会很有趣。一个原因是这是切换输出路线的好时机,以避免突然的电平变化。如果是这样,则可以在信号接近零时完成,而不是在交叉时完成。

标签: c++ c zero


【解决方案1】:

记录最后一个非零样本的符号,并且仅在当前样本也非零时才考虑乘法的结果(零样本本身永远不会交叉)。

for (int i=0, previous=sign(data[0]); i<numFrames-1; i++) {
    if(int current = sign(data[i])) {
        if(sign(previous * current) == -1)
            printf("zero cross");
        previous = current;
    }
}

【讨论】:

  • 好的,我知道这个方法比另一种方法好,但是假设中间有很多零,比如-1、0、0、0、0、0、0, 0, 0, 0, 0, 1 它会在最后一个 1 上检测到零交叉,但是经过了很多时间,波可能是异相的……我只是说。
  • @SpaceDog 好吧,你不可能在最后一个样本之前检测到交叉,因为那是数字信号中最终与零交叉的样本。无法确定在原始信号的哪个时间点会越过零。我想最好的问题是中间零,但是为了弄清楚你当前是否处于中间零,你必须跟踪最后一个非零样本的索引并展望下一个需要的交叉点缓冲信号。
  • 为什么这种方法比公认的答案更好?
【解决方案2】:

忽略该值,仅使用符号检测交叉。

#include <math.h>

for (int i=0; i<numFrames-1; i++) {
  if (signbit(data[i+1]) != signbit(data[i])) printf("zero cross");
}

signbit 宏报告所有值的符号,包括无穷大、零和 NaN。

[编辑]

signbit() 当且仅当其参数值的符号为负时才返回非零值。因此,2 个不同的负值可能会返回不同的非零值。更好用:

  if (!signbit(data[i+1]) != !signbit(data[i])) printf("zero cross");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    相关资源
    最近更新 更多