ShaZam深入分析之从数字声音到频率

我们在之前的文章中介绍了如何从模拟声音转变到数字声音。现在假如有了一个数字声音,你如何得到他的频率呢?这个部分很重要,因为ShaZam的算法基本都是基于频率的。

对模拟信号来说,这里有一个变化称为连续傅里叶变换。它可以把一个时间的函数转变成频率的函数。也就是假如把傅里叶变换应用到一个声音上,你就会得到它的频率。

但是这里有两个问题:

  • 我们处理的数字信号,所以它是一个有限的不连续声音。
  • 为了更好地理解音乐内部的频率,我们需要把傅里叶变换应用到整个音乐信号的更好的部分,比如我们需要把它应用到0.1s的部分。

还好,我们这里有一个新的数学函数,称之为离散傅里叶变换。

离散傅里叶变换

DFT(离散傅里叶变换)应用到离散信号中,并且返回一个离散的光谱。下面这里是它的公式:

这个公式中:

  • N是窗口的大小:组成信号的样本数目
  • X(n)代表第n个频率区间
  • x(k)是音频信号中的第k个样本

例如,对一个有4096个样本的音频信号,我们需要应用这个公式4096次:

  • n=0计算第0个频率区间
  • n=1计算第一个频率区间
  • n=2计算第二频率区间

你也许注意到,我说的是频率区间而不是频率。这是因为DFT给出的离散光谱。频率区间是DFT能够计算的最小频率单元。频率区间的大小等于信号的采样率除以窗口的大小(N)。在我们上面的例子中,有4096个窗口,标准的声音采样率是44.1kHz,所以频率分辨率就是10.77Hz (第0个有点特殊)

  • 第0个频率区间是0Hz到5.38Hz
  • 第一个频率区间是5.38Hz到16.15Hz
  • 第二个频率区间是16.15Hz到26.92Hz
  • 第三个频率区间是26.92Hz到37.68Hz

这就意味着DFT不能够区分小于10.77Hz的两个频率。比如27Hz,32Hz,37Hz其实都落在同一个频谱区间。假如37Hz的音符比较重,你只会知道第三个频率区间比较重。这个对最低八度音阶的解离其实是有问题的,比如:

  • A1在55Hz,而B1在58.27Hz以及G1在49Hz。
  • 标准88键的第一个音符实在A0 27.5Hz,然后后面是A#0位于29.14Hz

你可以通过增加窗口大小来改进频率分辨率,但这也意味着会丢失音乐中的快速频率/音符的改变:

一个音乐信号的采样率是44.1 kHz

  • 增加窗口的大小意味着增加更多的样本,因此就是增加window的时间。
  • 对于4096样本,这个window的时间就是0.1秒,频率分辨率是10.7Hz:你可以每0.1s探测一次改变
  • 对于16384样本,这个window的时间就是0.37s,频率分辨率就是2.7Hz:你只能探测到0.37s的改变。

音频信号的一个特殊性就是只需要通过DFT计算一般的频率区间。在之前的定义中,频率区间的定义是10.7Hz,这也就意味着2047个的频率区间展现了从21902.9Hz到21913.6Hz。但是:

  • 第2048个频率区间和第0个是一样的
  • 第2049个频率区间和第一个也是一样的
  • X+2048和第X个是一样的

参考文章:http://coding-geek.com/how-shazam-works/

You may also like...

Leave a Reply

Your email address will not be published.