听歌识曲是如何工作的,看完这个你就懂啦!

使用的算法是《An Industrial-Strength Audio Search Algorithm》,部分算法借鉴了Github的dejavu(https://github.com/worldveil/dejavu)项目。

上一篇:

为获得良好的阅读体验,你可能先需要了解 散列(哈希),python基础语法,一定的代码阅读能力,一定的语文理解能力(up写的很乱)。

在开始阅读本篇文章之前,最好认真阅读一下论文《An Industrial-Strength Audio Search Algorithm》,最好是一个字一个字,一个图一个图的把paper看下来(然后你就不需要来看这篇文章了,笑)

paper下载链接:https://www.ee.columbia.edu/~dpwe/papers/Wang03-shazam.pdf

中文翻译:https://blog.csdn.net/yutianzuijin/article/details/49787551

建议读英文的鸭。

好的,那么正式开始。

基本原理:对于每个音频,我们都要给他生成一些特殊的指纹,然后用这些指纹和要识别的歌曲进行比较,最后取匹配率最高的那个,就是识别出来的歌曲啦~

听起来是不是非常简单鸭~~~~

那么怎么生成这个指纹呢,好问题!我们要分为三个步骤:生成频谱图(频域图像)。

在频谱图的基础上计算出Constellation Map(星状图)

对星状图进行处理,生成指纹哈希。

首先是生成频谱图。

为了生成频谱图,我们就得把歌曲最开始拿出来的数据进行一波傅里叶变换,把时域信号转变为频域信号。什么?你不知道傅里叶变换(Fourier Transformation)?不如看看这个:https://zhuanlan.zhihu.com/p/19759362

但是,傅里叶变换有一个缺陷,那就是它在变换过程中把时间信息丢失了,也就是说傅里叶变换不能反映时间维度局部区域上的特征, 人们虽然从傅立叶变换能清楚地看到一整段信号包含的每一个频率的分量值,但很难看出对应于频率域成分的不同时间信号的持续时间和发射的持续时间,缺少时间信息使得傅立叶分析再更精密的分析中失去作用 [1]。

在听歌识曲中,时间是一个非常重要的因素。如果我们没有了时间,我就不知道什么频率在什么时候出现,强度又是多少。所以,我们不能抛弃时间这个变量。因此,我们可以利用短时傅里叶变换(STFT,short time Fourier transformation)来对音频数据进行分析和计算。

短时傅里叶变换通过加窗操作,把信号分成一段一段来计算,这样子在将时域型号转变为频域信号的同时,保留住了时间。

这看起来非常困难,但是!python中大量的第三方库给予了我们极大的便利。这里我们用到了 matplotlib 中的 mlab.specgram 来对音频数据进行分析。

生成频谱图

如图所示,只要我们把上一步中取到的音频数据(sample 每一个channel中的数据),放到里面,然后加上一些参数就好啦。

对于剩下的参数,我们可以取默认值,也可以自己修改。有兴趣可以去官方文档里看。

UP的取值是 nfft = 4096, nooverlap = 2048, window(加窗函数)用的是Hamming窗函数,fs是音频的采样速率。

接着,我们还可以对数据进行一些操作,比如:对取出来的值进行log运算,将其放到对数空间中,便于数据之间的比较与操作(因为不放入对数空间的话,数值可能会很大)。放入对数空间中

像这样,通过log10 之后的强度大小(或者说能量大小)便会控制在0-70这个范围之内啦。

频谱图的样子:在au中生成的频谱图

论文中给出的频谱图

好的,生成了频谱图,接下来我们要做的就是第二步,生成 Constellation Map!

首先我们来看看星状图到底长什么样(如果你读过paper,或许可能已经知道了)论文中给出的图片

根据peper中所说的,能量越大的点抗噪性就越强,所以我们将能量大的点作为判断依据。

在频谱图中,颜色越亮代表该点的能量越大。

小小的解释一下,这个频谱图看起来是二维的,实际上是三维的,包含时间,频率,以及能量大小(强度)

仔细观察一下,每个点(也就是星星,或者说峰值)的位置是不是都在都在颜色比较亮的地方。通过matplotlib生成的

这是一整首歌所产生的星状图

那么,我们要如何找到这些能量较大的点(峰值)呢?(由于up能力有限,只能复制粘贴别人的方法了)。

worldveil 大神巧妙的使用scipy,利用图像分析法来找到这些点。

好的,我们请看 worldveil 大神在项目dejavu [2] 中带来的算法(鼓掌!!!!!)。寻找峰值

minimun_peak_amplitude 是可以认为是峰值的最小能量值(在log空间中它 的取值范围是0-70),取得越高,产生的能量较大点的数量就越少,准确率就越低,但也不要取的太小。我在这里取了minimun_peak_amplitude=10

peak_neighborhood_size 是一个点想要成为能量较大点,也就是local maximum 所处的领域的大小。越小的话产生的点会越多,不建议太大,也不建议太小。我在这里取了peak_neighborhood_size = 20

经过一顿操作,峰值就找出来了。

其中 frequency_idx 和 time_idx 就是能量较大的点(峰值)所处的频率坐标和时间坐标了。

我们可以用zip函数把他们组成坐标的形式[(t1,f1),(t2,f2),(t3,f3)……]组合为坐标

----

其实到这里,我们已经可以通过这个星状图来对歌曲进行识别了。只要看某个片段是否能够与整首歌中某一块区域的对上就可以判断了。

论文的作者是这样子描述的:If you put the constellation map of a database song on a strip chart, and the constellation map of a short matching audio sample of a few seconds length on a transparent piece of plastic, then slide the latter over the former, at some point a significant number of points will coincide when the proper time offset is located and the two constellation maps are aligned in register. [4]翻译:如果你把数据库中某首歌的星状图散乱在一个条形图上,然后将几秒样本的星状图放在一个透明的塑料板上。在条形图上滑行塑料板(有点像游标卡尺),到某个时刻的时候就会出现一件神奇的事情:当样本和数据库歌曲的正确位置对齐时,重叠的极大值就会格外多,这样就意味着样本和数据库中正确音乐的正确位置匹配上了![3]

但是,直接对比需要耗费大量的时间。那么如何才能加快呢?我们可以对这些坐标进行快速组合哈希来获取最终的指纹并减少对比所需要的时间。

所以第三步!对星状图进行处理,生成指纹哈希。

生成指纹哈希的基本原理:将两个峰值点组合在一起,生成一个指纹,包含由两者的频率和时间差组成的哈希,以及前一个点的时间位置。指纹的生成方式

为此,我们首先要选择一个锚点(anchor point),然后每个锚点都对应一个目标区域(target zone)。(ps: 这个target zone 的选择极为讲究,我踩了一堆坑。)指纹生成图解

target zone 与 anchor point 的距离不宜靠的太近,也不宜离得太远。

前者会导致选择的两个点没有独特性,从而使生成 的哈希没有什么卵用;后者会导致两个点的时间跨度太大,也会使生成哈希没什么鸡儿用。所以,这个时候我们要认真看一下论文中的图(上图)。

在图中可以发现,anchor point 和 target zone 之间至少隔了5个时间单位,小于5个时间单位的都没选。

所以,我们在选择target zone的时候,时间差最好要超过5个单位。如果你们不信的话可以自己试一试,up被这个坑了好久。

接下来上代码

首先,我们要对上一步中取得的那些峰值以时间顺序进行排序,方便之后选择 anchor point 与 target zone。峰值排序

然后,我们将每一个能量较大点后的n个点作为target zone的范围。这个n称为fan-out。Fan-out用来决定每一个 anchor point 最多可以与多少个点进行匹配。

同时,我们通过判断两个点之间的时间差是否在我们需要的范围内(是否在 target zone之中),来最终决定是否将这两个点作为歌曲的指纹放入数据库中。选择生成指纹的峰值

time_constraint_condition 是一个 元组,包含可以作为指纹的两个点的最小时间差和最大时间差,up的取值是 (9,200)

fanout_factor 就是fanout常数。该值越大,生成的指纹就越多。在提高成功率的同时大大增大了所需要的储存空间以及牺牲了一点点的查询速度。up 的取值是 fanout_facotr = 20 (论文中说大于10就可以了)

然后,我们只需要把两个点的频率以及时间差组合起来,生成一个哈希,在加上 anchor point 的时间位置,一个指纹就生成好了。生成指纹

嘛,这样子生成指纹的部分就完成啦。接下来就只有搜索与识别的部分了。

结束。

Reference:

[1]: https://blog.csdn.net/lvsehaiyang1993/article/details/80521538

[2]: https://github.com/worldveil/dejavu

[3]: https://blog.csdn.net/yutianzuijin/article/details/49787551

[4]: Wang, Avery. "An Industrial Strength Audio Search Algorithm." Ismir. Vol. 2003. 2003.

转载请先获得许可。

python指纹识别算法_shazam听歌识曲算法解析+python实现-2 生成指纹相关推荐

  1. python 听歌识曲_Shazam听歌识曲算法解析+python实现-3 检索歌曲

    听歌识曲是如何工作的,看完这个你就懂啦! 使用的算法是<An Industrial-Strength Audio Search Algorithm>,部分算法借鉴了Github的dejav ...

  2. 听歌识曲算法技术[语音识别]

    概念理解 语音识别:通过一种语音检索算法来识别一段音频内容的含义. 音频文件:指带有声音的文件,比如音乐. MFCC:音频文件转为数字的过程 时域:振幅Y和时间T的关系. 频域:振幅Y和频率F的关系. ...

  3. 下一代听歌识曲技术——从信号处理到深度学习

    音乐丰富我们的生活:音乐传达人类的情感:音乐表达人类的艺术.人类文明的进程中离不开音乐这个载体,音乐也离不开人类的真情创作.在听到好听却没听过的歌曲时,如何快速准确得到该歌曲的歌名成为当务之急.Liv ...

  4. python声音识别歌曲_听歌识曲!python这个骚操作可以了解一下!

    音频指纹识别的目的是确定音频的数字"摘要".从而与音频样本进行比对得出它出自哪首歌曲,像现在QQ音乐.网易云音乐等各大音乐软件都有此功能,它根据歌曲的前两到五秒识别音乐歌名.今天我 ...

  5. 听歌识曲--用python实现一个音乐检索器

    听歌识曲,顾名思义,用设备"听"歌曲,然后它要告诉你这是首什么歌.而且十之八九它还得把这首歌给你播放出来.这样的功能在QQ音乐等应用上早就出现了.我们今天来自己动手做一个自己的听歌 ...

  6. 听歌识曲--用python实现一个音乐检索器的功能

    作者:唯心不易 字体:[增加 减小] 类型:转载 时间:2016-11-15 我要评论 本篇文章中主要介绍了用python实现一个音乐检索器,类似于QQ音乐的摇一摇识曲,有兴趣的同学可以了解一下. 听 ...

  7. python声音识别歌曲_听歌识曲--用python实现一个音乐检索器

    听歌识曲,顾名思义,用设备"听"歌曲,然后它要告诉你这是首什么歌.而且十之八九它还得把这首歌给你播放出来.这样的功能在QQ音乐等应用上早就出现了.我们今天来自己动手做一个自己的听歌 ...

  8. 基于音频指纹的听歌识曲系统

    听歌识曲,我想大家都不陌生.虽然不同的厂商识别率不同(可能是因为版权的原因),但是每个音乐APP都会有这么一个功能.我们以扣扣音乐为例,扣扣音乐听歌识曲功能比较丰富,不仅有基本的听歌识曲还有哼唱识别, ...

  9. python 听歌识曲_听歌识曲--用python实现一个音乐检索器

    作者 | 唯心不易@博客园 http://www.cnblogs.com/chuxiuhong/p/6063602.html 听歌识曲,顾名思义,用设备"听"歌曲,然后它要告诉你这 ...

最新文章

  1. Apollo 自动驾驶开发套件(D-KIT)
  2. mysql size_mysql fetch size 相关问题
  3. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! iview-admin@2.0.0 dev: `vue-cli-service serve
  4. 03-类与对象——课后动手动脑
  5. [html] 说说你对WEB标准和W3C的理解与认识?
  6. zend studio一些常用配置
  7. python编码思维导图_Python入门之ATM+购物车代码版思维导图
  8. jQuery源码解析之offset()
  9. (十一)RabbitMQ消息队列-如何实现高可用
  10. 谭浩强 c语言 swap,C语言谭浩强完整教案.ppt
  11. MPUSH消息推送服务器搭建
  12. 为选区添加描边_ps怎么给选区加上虚线描边
  13. 汉字读音表GB2312版 (共7809个汉字)
  14. Mybatis注解开发笔记
  15. 山东省第八届 ACM 省赛 Parity check (规律、水)
  16. luminati代理如何在Hubstudio中使用?
  17. IDE输入import语句自动消失
  18. idea java项目乱码问题处理
  19. 恭喜 李志强 成为 Layotto committer!
  20. cisco asa(asa5510 设置)防火墙的配置详解

热门文章

  1. php 圆角的度数计算,【圆角度的计算公式是什么】-圆的角度公式-数学-沃捍瞻同学...
  2. 质量管理:PDCA循环到PACD循环
  3. 怎么给android工程改名字,Android Studio项目改名操作
  4. 币值最大化问题 C++C++
  5. 不羁野草挑战遗传法则
  6. 键盘输入,键盘输入结束符。
  7. 爬取北京二手房数据信息(python)
  8. 正宇丨你的不自律,会毁了你一辈子
  9. spark常见转换算子(transformation)的操作
  10. 必应暗藏戏精模式,拿捏名人说话语气口头禅!官方还自推三种个性供挑选