【问题标题】:Autocorrelation returns random results with mic input (using a high pass filter)自相关返回带有麦克风输入的随机结果(使用高通滤波器)
【发布时间】:2010-11-24 02:43:05
【问题描述】:

很抱歉问了一个与我之前提出的问题 (FFT Problem (Returns random results)) 类似的问题,但我查找了音高检测和自相关,并找到了一些使用自相关进行音高检测的代码。

我正在尝试对用户唱歌进行音高检测。问题是,它不断返回随机结果。我有一些来自http://code.google.com/p/yaalp/ 的代码,我已将其转换为 C++ 并进行了修改(如下)。我的采样率为 2048,数据大小为 1024。我正在检测正弦波和麦克风输入的音高。正弦波的频率是 726.0,它检测到它是 722.950820(我可以接受),但它检测到麦克风的音高是从 100 到 1050 左右的随机数。

我现在正在使用高通滤波器来消除直流偏移,但它不起作用。我做对了吗,如果是这样,我还能做些什么来解决它?任何帮助将不胜感激!

(固定)

谢谢,

尼尔。

编辑:更改了代码以实现截止频率为 30hz 的高通滤波器(来自 What Are High-Pass and Low-Pass Filters?,谁能告诉我如何使用卷积将低通滤波器转换为高通滤波器?)但它仍然是返回随机结果。不幸的是,将它插入 VST 主机并使用 VST 插件来比较频谱对我来说不是一个选择。

编辑:已修复,感谢大家的帮助,但我一直无法正常工作,现在使用新代码。

【问题讨论】:

  • 顺便说一句:您的内存管理应该得到改进,因为您永远不会取消分配您分配的内存,但我相信您知道并且首先希望让算法运行。但你不应该忘记这一点!
  • 为什么标记为 C++?该代码非常不是 C++。
  • 其中没有一行 C++ 行,但 Niall 喜欢这种方式。

标签: c++ c signal-processing pitch pitch-tracking


【解决方案1】:

我不是声音专家,但如果您使用 44100 次采样(我猜是每秒采样数)并使用 1024 个数据点。您正在处理大约 1/40 秒的数据。我并不感到惊讶,当前的音高变化很大,这取决于你选择哪一个。如果你想找到一个声音的平均音高或主音高,我预计需要大约 1 秒的数据。

【讨论】:

  • 那么,每秒更多的样本会产生或多或少的准确结果吗?
  • @Nail:在我看来,@Jens 建议您需要比 1024 更多的样本是正确的。如果我没记错的话,您在之前的文章中收到了来自 @avakar 的类似指示问题:stackoverflow.com/questions/1351381/…
【解决方案2】:

在 44.1 kHz 采样频率下,1024 个样本仅略多于 23 ms 的数据。难道这只是不足以计算人类歌手的音高的数据吗?

我的意思是,我能发出的持续 23 毫秒的声音可能不是我有太多音高控制的东西;我希望这种测量会在更长的时间内完成。

【讨论】:

  • 那么,每秒更多的样本会产生或多或少的准确结果吗?
  • 亲爱的,在尝试编纂某些东西之前,您至少应该粗略地了解一下!更多样本 -> 更长的时间;每秒更多的样本:相同数量的样本的时间更少。每秒更少的样本 -> 给定数量的样本更多的时间。
【解决方案3】:

问题出在你的 findBestCandidates() 函数中:

在此函数中,您可以访问从 0 到 'length - 1' 的 'inputs' 数组。 当您在 detectPitchCalculation() 函数中调用此函数时,“输入”为“结果”,“长度”为“nHiPeriodInSamples”。 但是“结果”仅分配并填充到“nHiPeriodInSamples - nLowPeriodInSamples - 1”。 因此,如果 'nLowPeriodInSamples' 大于 0,您将访问 findBestCandidates() 函数内的未分配和随机内存!

编辑:

另一个错误是您在 detectPitchCalculation() 函数中填充了 'results' 数组的每个 'nResolution' 条目,但访问了 findBestCandidates() 函数中的每个条目(通过 'inputs' 参数)。但是由于您使用“nResolution = 1”调用detectPitchCalculation(),这并不能解释您的具体问题......所以我会多看一点。但是如果你用更高的分辨率调用它肯定会出现问题。

【讨论】:

  • 我已将 nHiPeriodInSamples 更改为 nHiPeriodInSamples - nLowPeriodInSamples - 1,但它仍在为麦克风输入返回随机值。
  • 省略“- 1”,因为长度是“nHiPeriodInSamples - nLowPeriodInSamples”,这意味着您可以访问从 0 到“nHiPeriodInSamples - nLowPeriodInSamples - 1”的索引。但这不会解决你的随机问题,我会再看看你的程序。
【解决方案4】:

我在你的代码中看不到问题,但我的 C 语言不好。但我会尝试以下方法来查找问题:

  • 使用结果已知的数据运行,例如以 sin(x) 作为输入
  • 以小数据量(例如 2)运行它

将结果与已知的正确结果进行比较。你应该可以在互联网上找到这些,或者手工完成。

如果随机意味着:相同的输入,不同的输出,你很可能在变量的初始化中有一些错误。使用调试器和已知输入检查所有变量,尤其是数组的所有元素是否已正确初始化。

【讨论】:

  • 来自正弦波的输入会产生或多或少准确的结果,但来自麦克风的输入会产生大约 100 到大约 1050 的随机结果。但我检查了来自麦克风的数据是正确的。
猜你喜欢
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 2022-09-26
  • 1970-01-01
相关资源
最近更新 更多