比较wav文件

Posted

技术标签:

【中文标题】比较wav文件【英文标题】:comparing wav files 【发布时间】:2010-12-01 08:32:48 【问题描述】:

我有一个(大部分)工作程序来比较两个 wav 文件,看看较小的文件是否在较大的文件中。这是在 java 中完成的。

我首先确保两个 wav 文件都是规范波形格式。然后我使用 AudioInputStream 从它们中获取一个字节数组的数据。我以特定帧速率(例如现在:4096 字节)的块取出数据。我取较小输入的第一块,然后在较大输入中遍历相同大小的块。

我采用这些块并创建具有相同数据的双数组。我得到他们的 FFT 并使用相关函数在结果相关系数数组中找到一个峰值。然后我转到较小输入的下一部分,看看是否出现了类似的峰值。

这行得通,当文件相同时,峰值很明显,并且大多数时候结果都是正确的。我没有得到误报。然而,我确实得到了假阴性。

这是因为我不确定如何“对齐”数据。较小的文件可能来自较大文件中的任何点。大多数时候,这是通过我这样做的分块方法捕获的。但有时,就好像文件不同,没有找到峰值,尽管文件应该返回高相关性。

如果我取出一个误报(没有峰值)的文件,稍微调整一下,在它们的末尾或开头剪掉几千字节,然后再次运行程序,它会突然发现峰,这是一个非常明确的匹配。因此,它确实有效,只是以某种方式找不到相关性明显的峰值。我的相关函数翻译了 FFT 以使它们匹配,所以我认为这将涵盖所有内容,但显然我并没有涵盖所有数据。

我不确定如何将较小文件的块“对齐”到较大文件中的任何位置,以便相关函数能够确定相关发生的位置。一切正常,我只需要消除误报。有什么建议吗?

【问题讨论】:

【参考方案1】:

使用卷积滤波器比较两个波形。它会告诉您是否以及在何处发生匹配。计算卷积的快速算法是available。

【讨论】:

我相信这是我正在做的事情的总体思路。我确实知道比赛的地点和地点;相关值的大幅飙升很容易判断。我只是不确定如何在分块文件时执行此操作。我不能做整个文件,因为它们会变得很大,所以我需要逐块做,这会丢失一些数据。 如何将较小文件的一个块与较大文件的每一对相邻块匹配(允许重叠)?这应该保证您会找到匹配项,即使较小文件的块跨越较大文件中的块边界。找到一个匹配项后,您可以确认较小文件的其余部分与该偏移量匹配。【参考方案2】:

这称为matched filter。由于分块,您的实施受到了影响。传统上,您将输入视为连续流,从每个样本开始提取一个块,然后进行相关。因此,如果您的输入长度为 10k 个样本,您最终会运行过滤器 10k 次,每次将 4k 个样本带入过滤器(在您的示例中)。但是,这很慢。有几种方法可以加快速度:

    使用小块(例如 256 点)来加快 FFT 计算。您的相关性可能看起来不太好,导致更多误报,但也许您可以列出可能的匹配项并返回并查看更大的块。

    不是从输入中的每个样本开始获取缓冲区,而是从每第 512 个样本开始获取 4k 缓冲区,然后进行相关性(类似于Marcelo Cantos's suggestion in his comment)。然后,在 512 中查找峰值中间的样本,因为时移会导致尖峰移动。此外,边缘处额外的非相关样本将导致峰值不是全值的,所以如果你有,你需要放松这个约束再次,这可能会导致更多误报,因此您再次不得不求助于列表方法。

在实现细节方面,我假设您已经从较小的文件中预先计算了块?此外,您不会说是否检查时域或频域中的相关性。您可以在频域中寻找平坦的幅度,这相当于时域中的尖峰,以节省逆 FFT。您必须做一些实验来确定频谱的平坦程度,但这可能会大大缩短时间。

【讨论】:

【参考方案3】:

我不确定我是否完全掌握了您正在使用的算法,但这里有一个想法:如果您可以通过手动剪掉开头和结尾的位来识别波浪,那么这不是您的可能解决方案吗?算法也是?

【讨论】:

【参考方案4】:

你可以看看this paper。它解释了 shazam 服务使用的算法,该算法从几秒钟的样本中识别音乐。 另一种方法here,使用自组织地图来聚类相似的音乐。不完全是你想做的事,但它可以给你一些想法。

【讨论】:

以上是关于比较wav文件的主要内容,如果未能解决你的问题,请参考以下文章

是否可以根据它们的 wav 文件比较两首相似的歌曲?

用c或c++播放wav文件,怎么实现

无法在 wav 文件中找到 2 个声音帧之间的差异

录制成WAV文件

如何在delphi中比较.wav样本? [关闭]

整轨的WAV不带cue文件,怎么分轨