这是一个非常广泛的问题,但让我尝试备份并描述一下音频识别的一般工作原理,以及您自己可以如何执行此操作。
我将假设音频来自音频文件而不是流,但无论哪种方式都应该相对容易理解。
数字音频基础知识
音频文件是通过称为采样的过程记录到设备中的一系列样本。采样是将连续的模拟信号(例如,来自麦克风或电吉他的电信号)转换为离散的数字信号的过程。
对于音频信号,几乎总是以单一的采样率进行采样,通常在 8kHz 到 192kHz 之间。对您而言,关于采样的唯一特别重要的事情是:
- 数字音频系统可以表示的最高频率称为奈奎斯特率,它是采样率的一半。因此,如果您使用 48kHz 的采样率,则可能表示的最高频率为 24kHz。这通常是足够的,因为人类只能听到高达 20kHz 的声音,因此您可以安全地使用超过 40kHz 的任何采样率,除非您尝试录制不适合人类的东西。
- 采样后,数字音频文件以浮点或整数值的形式存储。大多数情况下,音频文件表示为 32 位浮点、24 位整数或 16 位整数。在任何情况下,大多数现代音频处理都是使用浮点数完成的,并且通常在窗口内缩放(-1.0、1.0)。在这个系统中,交替的 -1.0s 和 1.0s 是可能的最高频率的最响亮的方波,而一系列 0.0s 是静音。
音频识别
相对于一定数量的用例,音频识别的一般算法很复杂,而且通常效率低下。例如,您是否试图确定一个音频文件是否与另一个音频文件完全匹配,或者它们听起来是否几乎相同?例如,让我们看一下最简单的音频比较算法(至少是我能想到的最简单的)。
def compareAudioFiles(a, b):
if len(a) != len(b):
return False
for idx in range(len(a)):
# if the current item in a isn't equal to the current item in b
if a[idx] != b[idx]:
return False
return True # if the two above returns aren't triggered, a and b are the same.
这**仅在特定情况下有效* - 如果音频文件略有不同,它们将不会被匹配为相同。让我们谈谈这可能会失败的几种方式:
- 浮点比较——在浮点数之间使用
== 是有风险的,因为浮点数的比较精度如此之高,以至于样本的微小变化会导致它们注册为不同的。例如:
SamplesA = librosa.core.load('audio_file_A.wav')
SamplesB = librosa.core.load('audio_file_A.wav')
SamplesB[0] *= 1.0...00000001 # replace '...' with lots of zeros
compareAudioFiles(SamplesA, SamplesB) # will be false.
尽管SamplesB 的细微变化是难以察觉的,但compareAudioFiles 可以识别。
- 零填充 -- 文件前后的单个样本 0 将导致失败:
SamplesA = librosa.core.load('audio_file_A.wav')
SamplesB = numpy.append(SamplesA, 0) # adds one zero to the end
# will be False because len(SamplesA) != len(samplesB)
compareAudioFiles(SamplesA, SamplesB) # False
这不起作用的原因还有很多,例如相位不匹配、偏置以及过滤后的低频或高频信号听不见。
您可以继续改进此算法以弥补此类问题,但它可能仍然无法很好地将感知到的声音与其他声音相匹配。简而言之,如果您想以比较音频听起来的方式的方式执行此操作,您需要使用声学指纹库。一个这样的库是pyacoustid。否则,如果您想单独比较文件中的音频样本,您可能会想出一个相对稳定的算法来测量时域中声音之间的差异,同时考虑零填充、不精确、偏差和其他噪声。
对于 Python 中的通用音频操作,我推荐LibROSA
祝你好运!