在音频文件中查找音频样本(已存在频谱图)

5

我的目标是:

  • 使用Skype,呼叫我的邮箱(成功)
  • 输入密码并告诉邮箱我想要录制新的欢迎信息(成功)
  • 现在,我的邮箱告诉我在提示音后录制新的欢迎信息
  • 我想等待提示声然后播放新的信息(失败)

我尝试实现最后一点的方法:

  • 使用FFT和滑动窗口创建频谱图(成功)
  • 为提示音创建“指纹”
  • 在来自Skype的音频中搜索该指纹

我面临的问题是:
来自Skype的音频和参考提示音的FFT结果在数字意义上不同,即它们相似但不相同,尽管提示音是从具有记录Skype音频的音频文件中提取出来的。下图显示了左侧为来自Skype音频的提示音的频谱图,右侧为参考提示音的频谱图。如您所见,它们非常相似,但并不相同...
上传了一张图片 http://img27.imageshack.us/img27/6717/spectrogram.png

我不知道如何继续下去。我应该平均它吗?即将其分成列和行,并比较这些单元格的平均值,如此处所述? 我不确定这是最好的方法,因为他已经说明,它在短音频样本中效果不佳,而提示音长度不到一秒...

有什么提示可以帮助我继续吗?

2个回答

4
你应该确定峰值频率和持续时间(可能是该频率上的最小功率, RMS 是最简单的度量方法)
这应该很容易测量。为了使事情更加聪明(但对于这个简单的匹配任务可能完全不必要),您可以在哔声窗口期间断言其他峰值不存在。
更新
要比较完整的音频片段,您需要使用卷积算法。我建议使用现成的库实现,而不是自己编写。
引用:
最常见的快速卷积算法使用快速傅里叶变换(FFT)算法通过循环卷积定理。具体来说,通过对每个序列进行FFT,逐点相乘,然后执行逆FFT找到两个有限长度序列的循环卷积。然后使用该技术与零扩展和/或丢弃输出部分有效地实现上述类型的卷积。其他快速卷积算法,例如Schönhage-Strassen算法,在其他环中使用快速傅里叶变换。

维基百科将http://freeverb3.sourceforge.net列为开源候选者。

编辑 添加到API教程页面的链接:http://freeverb3.sourceforge.net/tutorial_lib.shtml

其他资源:

http://en.wikipedia.org/wiki/Finite_impulse_response

http://dspguru.com/dsp/faqs/fir

Debian上已有相关工具的现有软件包:

[brutefir - a software convolution engine][3]
jconvolver - Convolution reverb Engine for JACK

libzita-convolver2 - C++ library implementing a real-time convolution matrix
teem-apps - Tools to process and visualize scientific data and images - command line tools
teem-doc - Tools to process and visualize scientific data and images - documentation
libteem1 - Tools to process and visualize scientific data and images - runtime

yorick-yeti - utility plugin for the Yorick language

这个课程指南可能是一个很好的入门/起步指南。 - sehe
@sehe:您能否详细解释一下卷积算法?使用谷歌,我甚至无法了解它如何帮助我解决问题... - Daniel Hilgarth
从维基百科链接的动画中,应该很清楚了。我不是声音处理专家,所以我不确定是否应该教你我自己也不太了解的东西 :) 简单来说,卷积函数是一个响应函数,在两个源信号在曲线上最相似的点(在时间上)会产生峰值。卷积可以比这更聪明,检测两个轴上的缩放副本和重复等,但你不需要那些。你只需要在某个时刻寻找一个“正匹配”的峰值,并判断它是否超过了你所需的阈值 :) - sehe
你只有时间和振幅。频率是隐含的:它是相同数据的时域表示。仅为了可视化,才需要/方便将三个单位合并在图表中。-- 不,你不会有很多高峰。如果你寻找一个样本,你会得到恰好一个匹配点(其余的会上下倾斜到达和离开该点)。如果音频中有类似的点,它们可能会产生子峰,但这与你无关。顺便说一句,已经更新了更多现有的库/应用程序 - sehe
@sehe:我发布了一个新问题,请看一下:https://dev59.com/VW025IYBdhLWcg3wtoQ_ - Daniel Hilgarth
显示剩余6条评论

1

首先,我会在频率方向上对其进行平滑处理,以使频率的小变化变得不那么重要。然后,只需取每个频率并减去两个幅度。平方差异并将它们相加。也许首先规范化信号,以便总振幅的差异不重要。然后将差异与阈值进行比较。


谢谢你的回答。我不认为仅对每个离散时间点的频率进行平滑处理会有很大帮助... 你试过类似这样的方法吗?为什么要平方差异而不是只使用Math.Abs呢? - Daniel Hilgarth
声音级别是对数测量。在波形中测量功率是振幅平方积分的总和,它只是二维物理声音/波形。你可以忽略它,但你会得到有偏差/歪曲的比较。再次查看我发布的RMS链接。 - sehe
在时间域中进行这项工作很困难,因为您不知道样本的确切开始时间。在频率空间中进行此操作对小时间偏移更加宽容。 - CodesInChaos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接