我正在尝试从一篇论文中实现音高检测算法,但是对于我来说,论文中的数学水平还有些高阶。
我只想确保我已正确理解它。
我还在代码中添加了注释,提出了一个使我感到困惑的问题。
可以在此处找到该论文:https://pdfs.semanticscholar.org/0124/09d447691fd74c49bc407b3818b4617641b2.pdf
我的代码如下。
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.
}
问题
那么当b
和NaN
是b_idx = 7
时,frame[7]
是185
的原因呢?
这绝对让我感到困惑!
编辑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/
元音,并对其进行了运行,这是在屏幕上显示的内容:
论文第2页上的图1a
将结果与本文第2页的图1a进行比较,可以看到很相似,但是我仍然不确定是否正确实现了公式,因为要实现的公式应该类似于图1b或1c。
我认为现在的问题是公式变量i
应该在代码方面。
论文在第二页上指出以下内容:
i =第n帧内的第一个样本
所以...嗯...
答案 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
内放置一个断点,看看发生了什么。那应该可以帮助您发现阵列内部的问题。解决之后,您可以删除该检查并恢复上面的代码。