【问题标题】:Pitch detection with computeSpectrum() return FFT values使用 computeSpectrum() 进行音高检测返回 FFT 值
【发布时间】:2011-06-08 17:55:05
【问题描述】:
  • 我正在使用 Actionscript 3.0 for Flash Player 10.3 进行开发
  • 我在加载的 .mp3 上使用 computeSpectrum()
  • 运行 *Event.ENTER_FRAME* 以获取 byteArray 中每个样本的快照
  • ByteArray 包含 512 个值(每个通道 256 个)。这些值是 FFT Spectrum,范围从 0 到 1。
  • 我不能为每个样本使用峰值频率(我发现了!)因为最高值不一定是基频! 结果,我得到了很多随机值! 当然我也猜对了一些,但这还不够!

我发现了自相关...
谁能给我一个如何使用它的例子?

或者链接,或者甚至来自其他脚本语言的示例脚本来掌握它?

问候
初始化代码

【问题讨论】:

  • 你想在原始波形上做自相关,还是在 FFT 上做?
  • 我想我会更喜欢 FFT,只是因为我试图检测用户刚刚录制但未保存在任何地方的东西的音调......在 Flash Player 中以 ByteArray 的形式存在
  • 我的意思是,您可以执行 1. FFT(信号)、2. Autocorr(信号)或 3. Autocorr(FFT(信号))。还有 4. FFT(FFT(signal)) ("倒谱") 我相信所有都被用于音高检测,虽然我不知道哪个最适合语音。
  • 嗨,怎么样?你设法让它工作吗?我正在做一个非常相似的项目。也使用这个gerrybeauregard.wordpress.com/2010/08/06/…...请在声音世界中分享您的发现:)。谢谢!

标签: flash actionscript-3 signal-processing fft


【解决方案1】:

听起来您已经了解如何获得 FFT 频谱了,对吧?

http://flic.kr/p/7notw6

但是,如果您正在寻找基础(绿点),则不能只使用最高峰。这不一定是根本。在我的示例中,实际基频为 100 Hz,但最高峰值为 300 Hz。

您可以通过多种不同的方式找到真正的基本原理,并且每种方式在不同的环境中效果更好。 comp.dsp 上的一个帖子提到“FFT、倒谱、自/互相关、AMDF/ASDF”。

举个简单的例子,每个红点与其相邻点的距离为 100 Hz,因此,如果您使用寻峰算法,然后将每个谐波与下一个谐波之间的距离平均起来,您就会找到基波,但是如果任何一个峰值被遗漏,或者包含额外的峰值,或者如果信号是对称的并且只包含奇次谐波(1f、3f、5f),这将失败。您需要找到模式,然后丢弃异常值,然后取平均值。这可能是一种容易出错的方法。

您还可以对原始波形进行自相关。从概念上讲,这意味着将波形的副本滑过自身,并找到与自身最佳对齐的延迟(这将是一个完整的周期)。在正常实现中,we use the FFT, though, to speed it up。自相关基本上是

  • IFFT(FFT(信号)⋅FFT(信号)*)

其中 * 表示复共轭或时间反转。 In Python, for instance:

correlation = fftconvolve(sig, sig[::-1], mode='full')

而fftconvolve()的源码比较简单:https://github.com/scipy/scipy/blob/master/scipy/signal/signaltools.py#L133

【讨论】:

  • 那张图片值 1.0E03 个字。
  • @rajah9 假设每个单词平均有 6 个字符,那么这个 48 kB 的图像在传达信息方面的效率只有 12.5%。 :)
  • 如果我必须选择一个免费的 C++ 库来应用音高检测,你会推荐哪一个?我目前正在研究 Adob​​e Alchemy,它允许我(理论上)在 C++ 库和 Flash 之间进行通信!
  • @initcode 我不知道。我只熟悉 Matlab 和 Python 中的高级内容。
  • 嗨 endolith,我仍在尝试解决检测问题...谢谢您的回答...我的问题是每个人都给了我很好的理论,但没有人解释得更详细,所以我可以开始尝试弄清楚如何编写公式...我需要在您上面给我的公式中询问更多细节,如果您有时间可以向我解释,请。
【解决方案2】:

您可以使用谐波乘积谱法来估计一个频谱(FFT 结果)中泛音峰之间的距离(频率差),即使某些峰丢失了,只要没有太多杂散频率峰(噪音)。

要制作谐波乘积频谱,请将 FFT 打印在半透明纸上,然后将其卷成圆柱体(或在软件中进行等效操作)。将圆柱体包裹得越来越紧,直到最大数量的峰重叠。圆周将是对音高的一个很好的估计。这适用于任何具有大量谐波的音乐声音,即使基本音高频率峰值缺失或微弱。

【讨论】:

    【解决方案3】:

    Sound.extract() 结果可以传递给SampleDataEvent.data

    【讨论】:

    • 感谢 www0z0k,我已经在使用 SampleDataEvent.SAMPLE_DATA 到 ByteArray!我正在寻找的是一种模拟 FFT 值的自相关以检测音高的方法!
    【解决方案4】:

    你想做什么?

    我之前没有使用过computeSpectrum(),但我作为 DSP 工程师的前半段职业生涯。

    如果它按照文档所说的那样做,那么您不需要自动关联结果。

    在您的字节数组中,索引表示频率箱,索引值表示该特定频率的大小。

    如果通过音高检测,您的意思是找到最强的频率,那么您需要循环遍历字节数组并计算每个索引的sqrt(left*left+right*right)。找到这些的最大值。最大值的索引代表最强的频率。

    假设fs=44.1kHz,i是你的索引,那么最强频率是

    f = (i/255) * (44100 / 2);

    请记住,您会受到频率分辨率的 bin 间距的限制。如果需要更高的分辨率,则需要对数据进行插值。

    【讨论】:

    • 嗨 MPD,谢谢您的回复...我实际上是在尝试检测音符中的音高,而不仅仅是采样箱中的峰值频率。问题是基频不一定是最高频率,所以我必须找到一种自相关的方法来检测该频率;然后很容易;我已经有了根据频率返回正确音符的功能!
    • 好的,那么您需要阅读更多关于音高检测算法的内容。有几种方法可以解决它。这里有一些相关的问题,但我没有阅读它们以了解它们有多少优点。自相关是一个时域问题,尽管您可以使用 FFT 来计算它。问题是 computeSpectrum() 没有给你完整的 FFT 值。您可能需要使用原始数据计算 FFT,或使用原始数据计算时域中的自相关。
    猜你喜欢
    • 2010-11-30
    • 2011-09-23
    • 2011-01-15
    • 1970-01-01
    • 2012-05-09
    • 2023-03-19
    • 2011-05-28
    • 2012-03-25
    • 2021-01-21
    相关资源
    最近更新 更多