java - 使用 FFT 匹配两个音频文件 (Android Studio)

标签 java android android-studio audio audio-fingerprinting

过去几天我一直在开发应用程序的一部分,我需要同时播放和录制音频文件。我需要完成的任务只是将录音与播放的音频文件进行比较并返回匹配的百分比。以下是我到目前为止所做的事情以及我的问题的一些背景:

  • 目标 API >15

  • 我决定使用 .wav 音频文件格式来简化文件解码

  • 我使用 AudioRecord 进行录音,使用 MediaPlayer 播放音频文件
  • 我创建了一个决策类来传递我的音频文件并将其转换为 PCM 以便执行匹配分析
  • 我使用以下规范来录制音频格式(CHANNEL_MONO、16 BIT、SAMPLE_RATE = 44100)
  • 将音频文件传递给解码器后,我会继续将其传递给 FFT 类,以获得分析所需的频域数据。

以下是我的一些问题:

  • 当我使用 AudioRecord 录制音频时,默认格式是 PCM 还是我需要以某种方式指定该格式?
  • 我正在尝试将录音传递到 FFT 类,以便获取频域数据来执行匹配分析。有没有办法在不将录音保存在用户设备上的情况下执行此操作?
  • 对两个文件执行 FFT 分析后,是否需要将数据存储在文本文件中才能执行匹配分析?有哪些选择或可能的方法可以做到这一点?
  • 经过大量研究后,我找到的所有资源都涵盖了如何将录音与数据库中包含的歌曲/音乐进行匹配。我的目标是查看两个特定音频文件的匹配程度,我该怎么做? - 我是否需要创建/使用哈希函数才能实现我的目标?对此问题的详细回答将会非常有帮助
  • 目前我有一个单独的线程用于录制;用于解码音频文件的单独 Activity ; FFT 分析的单独 Activity 。我计划在单独的线程或 AsyncTask 中运行匹配分析。您认为这种结构是最佳的还是有更好的方法?另外,我是否也应该在单独的线程中将音频文件传递给解码器,还是可以在录音线程或 MatchingAnalysis 线程中进行?
  • 在进行匹配比较之前,我是否需要在音频文件的操作中执行加窗操作?
  • 我是否需要解码 .wav 文件,还是可以直接比较 2 个 .wav 文件?
  • 比较前是否需要对音频文件进行低音调操作?
  • 为了进行匹配比较,我到底需要生成哪些数据(功率谱、能谱、频谱图等)?

我是否以正确的方式处理这个问题,或者我错过了什么?

最佳答案

在 Shazam 等应用中,Midomi 音频匹配是使用称为音频指纹的技术完成的,该技术使用频谱图和哈希。

  • 求 FFT 的第一步是正确的,但随后您需要在时间和频率之间制作一个称为频谱图的二维图表。
  • 此频谱图数组包含超过一百万个样本,我们无法处理这么多数据。所以我们发现振幅的峰值。峰值将是对应于其周围局部邻域中最大的幅度值的(时间,频率)对。峰值查找将是一个计算成本高昂的过程,不同的应用程序或项目以不同的方式执行此操作。我们使用峰值是因为它们对背景噪声更加不敏感。
  • 现在不同的歌曲可以有相同的峰值,但区别在于出现的顺序和时间差异。因此,我们将这些峰值组合成唯一的哈希值并将它们保存在数据库中。
  • 对您希望应用识别并匹配数据库中的每个音频文件执行上述过程。虽然匹配并不简单,但也应该考虑到时间差,因为歌曲可以来自任何时刻,并且我们有完整歌曲的指纹。但这不是问题,因为指纹包含相对时间差。

这是一个比较详细的过程,您可以在此链接 http://www.ee.columbia.edu/~dpwe/papers/Wang03-shazam.pdf 中找到更多说明

有一些库可以为你做到这一点 dejavu ( https://github.com/worldveil/dejavu ) 和 chromaprint (C++ 语言)。 Musicg by google 是用 java 编写的,但它在背景噪音下表现不佳。

匹配两个音频文件是一个复杂的过程,就像上面的评论一样,我也会告诉你先在电脑上尝试,然后在手机上尝试。

关于java - 使用 FFT 匹配两个音频文件 (Android Studio),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41456372/

相关文章:

android - 加速 SQLite 数据库 android

android - TextView 占用额外空间

android - Apple Silicon Android Studio 模拟器 : ERROR: can't find the emulator executable

java - 位图 API 上的 ScriptIntrinsicBlur<14

java - 如何更改我的 fragment 中的文件 XML 属性

JAVA - 它是 java.util.Calendar 类中的错误还是什么?

java - 动态 TestNG XML 创建。获取错误的 XML。我哪里错了

java - 暂停按钮java

java - 如何使用 Android 应用程序访问 MySQL 数据库?

java - Apache 通用编解码器 - 为什么 Hex.encode() 不是静态的?