此自相关公式是否正确编程?

时间:2018-07-15 23:13:34

标签: c# math formula equation

我正在尝试从一篇论文中实现音高检测算法,但是对于我来说,论文中的数学水平还有些高阶。

我只想确保我已正确理解它。

我还在代码中添加了注释,提出了一个使我感到困惑的问题。

可以在此处找到该论文:https://pdfs.semanticscholar.org/0124/09d447691fd74c49bc407b3818b4617641b2.pdf

该公式可以在第二页的右上角找到。 enter image description here

我的代码如下。

public int L = 0.1f;

public float calcAutocorrelation(float[] frame)

    int N = frame.Length; //frame size

    float result = 0f;
    for (var n = 0; n < N; n++){
        result += frame[n] * frame[n + L] //in programming this is not possible as L is a float but formula says this is needed???

        /* I could cast the L to an INT type but the paper states
         * that L should range between 0 and 1, and in-code we'll
         * probably end up with L rounded to 0 most of the time.
         */

    }

    return result;
}

我错过了什么,还有什么可以做得更好的?

编辑 修复并简化了代码。

public int Lag = 1;

public float calcAutocorrelation(float[] frame)

    int N = frame.Length; //frame size

    float result = 0f;
    for (var n = 0; n < N; n++)
        result += frame[n] * frame[n + Lag]

    return result;
}

编辑2

因此,显然结果有时有时会变成NaN类型,我很难弄清楚。

我整理了一个简单的解决方案,例如下面的代码,但这并不是真正的解决方案,它只是一个绕过而无法提供所需正确结果的方法。

我用一个16 floats的小框架测试了我的代码,并且该框架没有任何NaN值。我是愚蠢的,还是我是愚蠢的,因为我无法为自己的生活弄清楚发生了什么。

测试框架:

frame[0]   : 0
frame[1]   : 0
frame[2]   : 96
frame[3]   : 185
frame[4]   : 0
frame[5]   : 0
frame[6]   : 0
frame[7]   : 185
frame[8]   : 0
frame[9]   : 0
frame[10]  : 192
frame[11]  : 184
frame[12]  : 0
frame[13]  : 0
frame[14]  : 0
frame[15]  : 184

代码:

public int lag = 1;

public float calcAutocorrelation(float[] frame){

    float result = 0f;
    for (int i = 0; i < frame.Length - lag; i++){

        float a = frame[i];
        if ( float.isNaN(a) )
            a = 0;

        int b_idx = (i + lag);
        float b = frame[b_idx];
        if ( float.isNaN(b) )
            b = 0;

        result += a * b;

    }

    return 0f - result; //just inverting the results for my purposes. Doesn't really affect the end goal.
}

问题 那么当bNaNb_idx = 7时,frame[7]185的原因呢? 这绝对让我感到困惑!

这是我发生的事情的屏幕截图: enter image description here


编辑3

发现了与NaN问题有关的问题。 (我认为)这似乎根本不是问题,可以使用float.isNaN()进行检查并更正。

将帧转换为字节数组的原因是由于基础音频库NAudio如何处理转换。

在此处阅读:http://mark-dot-net.blogspot.com/2008/06/wavebuffer-casting-byte-arrays-to-float.html

因此,即使它显示为字节数组,使用它时每个值也将正确地转换为浮点数。

很奇怪,但事实如此。就个人而言,根据法律,这种编码应该是非法的。

所以,一切似乎都正常(我认为?),我对公式的实现如何执行?

好吧,论文在图6的第6页指出以下内容:

  

进行的一项实验是将PDA应用于/ a /   KayPENTAX Elemetrics语音数据库中的语音包含50个   正常的声音和100种功能性和器质性声音障碍。

我录制了自己的/a/元音,并对其进行了运行,这是在屏幕上显示的内容:

enter image description here

  

enter image description here

     

论文第2页上的图1a

将结果与本文第2页的图1a进行比较,可以看到很相似,但是我仍然不确定是否正确实现了公式,因为要实现的公式应该类似于图1b或1c。

我认为现在的问题是公式变量i应该在代码方面。

论文在第二页上指出以下内容:

  

i =第n帧内的第一个样本

所以...嗯...

1 个答案:

答案 0 :(得分:0)

我认为您只需要在for循环中修复该条件,因此在最后一个循环中,它不会超出范围:

public int Lag = 1;

public float CalcAutocorrelation(float[] frame)
{
    int N = frame.Length; //frame size

    float result = 0;
    for (int n = 0; n < N - Lag; n++)
        result += frame[n] * frame[n + Lag];

    return result;
}

(请注意,我已经更改了for条件)。

如果遇到NaN错误,可以这样检查:

for (int n = 0; n < N - Lag; n++)
{
    result += frame[n] * frame[n + Lag];
    if (float.IsNaN(result))
    {
        var v1 = frame[n];
        var v2 = frame[n + Lag];
    }
}

只需在if内放置一个断点,看看发生了什么。那应该可以帮助您发现阵列内部的问题。解决之后,您可以删除该检查并恢复上面的代码。