我希望能够使用 java 检测预定频率的音调。我正在做的是播放一个音调(音调的频率根据用户输入而变化),并且我试图检测音调是否具有特定频率。如果是,我执行某种方法。根据我读到的内容,我需要 FFT,但我不确定如何在 java 中实现它。似乎有很多关于如何执行此操作的文档,但其中的文档涉及查看音频文件而不是实时分析。我不需要将音频保存到文件中,只需确定是否以及何时录制频率 x 的音调。
理想情况下,我希望以 44KHz 的采样率进行录制,并在确定是否检测到音调后,确定检测到音调的时间,精度为 +-3ms。然而,只要不荒谬(即+100ms),低于此的精度也是可以接受的。从我查到的内容中,我大致知道我需要做什么,但我需要帮助将它们整合在一起。使用伪代码,它看起来大致像这样(我认为)
请注意,我大致知道何时可以检测到满意频率的音调在 +-1 秒内
for(i = 0, i < 440000 * 2, i++){//*2 because of expected appearance interval;may change
record sound sample
fft(sound sample)
if(frequencySoundSample > x){
do something
return
}
}
播放音调时会有相当大的背景噪音。然而,音调将具有非常高的频率,例如 15-22KHz,因此我相信,通过简单地查找录音机何时检测到非常高的频率,我可以确定这是我的音调(而且音调也会以高振幅可能持续 0.5 秒或 1 秒)。我知道不会有其他高频声音作为背景噪音(我预计背景频率可能高达 5KHz)。
那我有两个问题。我提供的伪代码足以满足我想要做的事情吗?如果不是,或者有更好的方法,我完全赞成。其次,我如何在java中实现这个?我明白我需要做什么,但我很难将它们整合在一起。我对java很了解,但我不熟悉音频涉及的语法,而且我没有任何fft经验。请明确并给出带有注释的代码。我已经尝试解决这个问题有一段时间了,我只需要看到它们全部联系在一起。谢谢。
EDIT
我知道使用像我这样的 for 循环不会产生我想要的频率。更多的是粗略地展示我想要的东西。也就是说,随着时间的推移,同时记录、执行 fft 和测试频率。
如果您只是寻找特定频率,那么基于 FFT 的方法对于您的特定应用来说可能不是一个好的选择,原因有两个:
这是多余的——你计算整个频谱只是为了检测某一点的幅度
为了获得 3 ms 的起始检测分辨率,您需要连续 FFT 之间有很大的重叠,这比仅仅处理连续的样本块需要更多的 CPU 带宽
检测单个音调是否存在的更好选择是戈策尔算法(又名 Goertzel 过滤器)。它实际上是在单个频域仓上评估的 DFT,并广泛用于音调检测。它是much计算成本比 FFT 低,实现起来非常简单,并且您可以在每个样本上测试其输出,因此不存在分辨率问题(物理定律规定的问题除外)。您需要对输出的幅度进行低通滤波,然后使用某种阈值检测来确定音调的开始时间。
请注意,SO 上已经有许多关于音调检测和使用 Goertzel 算法的有用问题和答案(例如精确的音调开始/持续时间测量?) - 我建议阅读这些内容以及维基百科条目作为一个很好的起点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)