在 JavaScript 中比较音源和麦克风之间的声音

Compare sound between source and microphone in JavaScript

我从事音频方面的工作,但我是该领域的新手。我想 将来自麦克风的声音与我的源音频匹配(只有 1 个声音) 就像来自 Shazam 的可口可乐广告。 Example Video(0.45 分钟)但是,我想在 JavaScript 之前在网站上制作它。谢谢。

构建类似于 Shazam 后端的东西并非易事。我们需要:

  1. 从用户的麦克风获取音频(简单)
  2. 将其与源进行比较并确定匹配项(嗯...如何...)

我们如何执行每个步骤?

获取音频

这个绝对没什么大不了的。为此,我们可以使用 Web Audio API。您可以 google 获取有关如何使用它的优秀教程。 This link 提供了一些很好的基础金属知识,您在使用它时可能想了解这些知识。

将样本与音频源文件进行比较

显然,这篇文章将成为此类项目中的算法挑战。可能有多种方法来处理这部分,这里没有足够的时间来描述它们,但是一种可行的技术(恰好是 Shazam 实际使用的),并且也有更详细的描述 here,是为您的来源 material 的较小部分创建一种指纹并与之进行比较,您可以使用 FFT 分析生成指纹。

其工作原理如下:

  1. 一次查看不超过几秒钟的样本的一小部分(请注意,这是使用滑动 window,而不是离散分区完成的)
  2. 计算音频选择的傅里叶变换。这将我们的选择分解为许多不同频率的信号。我们可以分析样本的频域,以得出关于我们所听到内容的有用结论。
  3. 通过识别 FFT 中的临界值(例如峰值频率或幅度)为选择创建指纹
  4. 如果你想像 Shazam 那样匹配多个样本,你应该维护一个指纹字典,但由于你只需要匹配一个来源 material,你可以只将它们维护在一个列表中.由于您的键将是一个数值数组,我建议另一种可以快速查询您的数据集的数据结构是 k-d tree。我不认为 Shazam 使用一个,但我越想,他们的系统似乎越接近 n 维最近邻搜索,如果你能保持关键点的数量一致的话。不过现在,保持简单,使用列表。

现在我们有一个指纹数据库,可以使用了。我们现在需要将它们与我们的麦克风输入进行比较。

  1. 使用滑动 window 对我们的麦克风输入进行小段采样,方法与我们处理源的方式相同。
  2. 对于每个片段,计算指纹,并查看它是否与存储中的任何片段相匹配。您可以在此处查找部分匹配项,您可以尝试进行许多调整和优化。
  3. 这将是一个嘈杂且不准确的信号,因此不要指望每个片段都能匹配。如果他们中的很多人都匹配(你必须通过实验弄清楚很多意味着什么),那么假设你有一个。如果匹配项相对较少,那么认为你没有。

结论

这不是一个超级容易做好的项目。所需的调整和优化量将被证明是一个挑战。有些麦克风不准确,大多数环境都有其他声音,所有这些都会影响您的结果,但它也可能没有听起来那么糟糕。我的意思是,这是一个从外面看起来复杂得无法接近的系统,我们只是把它分解成一些相对简单的步骤。

最后一点,您在 post 中多次提到 Javascript,您可能会注意到我在回答中提到它的次数为零,这是因为语言实施不是一个重要因素。这个系统足够复杂,最难的部分就是你在纸上解决的部分,所以你不需要用 "how can I do X in Y" 来思考,只需找出 X 的算法,然后Y应该自然而然。