90 行 Python 搭一个音乐搜索工具【附代码】

之前一段时间读到了这篇文章,其中描述了作者如何实现国外著名音乐搜索工具shazam的基本功能。

读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现了一个简单的音乐搜索工具—— Song Finder, 它的核心功能被封装在SFEngine 中,第三方依赖方面只使用到了 scipy。

工具demo

这个demo在ipython下展示工具的使用,本项目名称为Song Finder,我把索引、搜索的功能全部封装在Song Finder中的SFEngine中。

首先是简单的准备工作:

In [1]: from SFEngine import *In [2]: engine = SFEngine()
在这之后我们对现有歌曲进行索引,我在original目录下准备了几十首歌曲(.wav文件)作为曲库:

In [3]: engine.index(‘original‘) # 索引该目录下的所有歌曲
在完成索引之后我们向Song Finder提交一段有背景噪音的歌曲录音进行搜索。对于这段《枫》在1分15秒左右的录音:

工具的返回结果是:

其中展示的分别是歌曲名称及片段在歌曲中出现的位置(以秒计),可以看到工具正确找回了歌曲的曲名,也找到了其在歌曲中的正确位置。

而对于这段《童话》在1分05秒左右的背景噪音更加嘈杂的录音:

工具的返回结果是:

可以看到尽管噪音非常嘈杂,但是工具仍然能成功识别所对应的歌曲并对应到歌曲的正确位置,说明工具在噪音较大的环境下有良好的健壮性!

项目主页: Github

Song Finder原理

给定曲库对一个录音片段进行检索是一个不折不扣的搜索问题,但是对音频的搜索并不像对文档、数据的搜索那么直接。为了完成对音乐的搜索,工具需要完成下列3个任务:

对曲库中的所有歌曲抽取特征
以相同的方式对录音片段提取特征
根据录音片段的特征对曲库进行搜索,返回最相似的歌曲及其在歌曲中的位置

特征提取?离散傅立叶变换!

为了对音乐(音频)提取特征,一个很直接的想法是得到音乐的音高的信息,而音高在物理上对应的则又是波的频率信息。

为了获取这类信息,一个非常直接的额做法是使用离散傅叶变化对声音进行分析,即使用一个滑动窗口对声音进行采样,对窗口内的数据进行离散傅立叶变化,将时间域上的信息变换为频率域上的信息,使用scipy的接口可以很轻松的完成。在这之后我们将频率分段,提取每频率中振幅最大的频率:

这样,对于一个滑动窗口,我提取到了6个频率作为其特征。对于整段音频,我们重复调用这个函数进行特征抽取:

其中44100为音频文件自身的采样频率,8192是我设定的取样窗口(对,这样hardcode是很不对的),callback是一个传入的函数,需要这个参数是因为在不同场景下对于所得到的特征会有不同的后续操作。

匹配曲库

在得到歌曲、录音的大量特征后,如何进行高效搜索是一个问题。一个有效的做法是建立一个特殊的哈希表,其中的key是频率,其对应的value是一系列(曲名,时间)的tuple,其记录的是某一歌曲在某一时间出现了某一特征频率,但是以频率为key而非以曲名或时间为key。

这样做的好处是,当在录音中提取到某一个特征频率时,我们可以从这个哈希表中找出与该特征频率相关的歌曲及时间!

当然有了这个哈希表还不够用,我们不可能把所有与特征频率相关的歌曲都抽出来,看看谁命中的次数多,因为这样会完全无视歌曲的时序信息,并引入一些错误的匹配。

我们的做法是,对于录音中在t时间点的一个特征频率f,从曲库找出所有与f相关的(曲名,时间)tuple,例如我们得到了

[(s1, t1), (s2, t2), (s3, t3)]
我们使用时间进行对齐,得到这个列表

[(s1, t1-t), (s2, t2-t), (s3, t3-t)]
记为

[(s1, t1), (s2, t2), (s3, t3`)]
我们对所有时间点的所有特征频率均做上述操作,得到了一个大列表:

[(s1, t1), (s2, t2), (s3, t3), ..., (sn, tn)]
对这个列表进行计数,可以看到哪首歌曲的哪个时间点命中的次数最多,并将命中次数最多的(曲名,时间)对返回给用户。

不足

这个小工具是一个几个小时写成的hack,有许都地方需要改进,例如:

目前只支持了wav格式的曲库及录音
所有数据都放在内存中,曲库体积增大时需要引入更好的后端存储
索引应该并行化,匹配也应该并行化,匹配的模型其实是典型的map-reduce。
项目主页

https://github.com/zhengqm/SongFinder

好啦,以上就是我的分享,如果你跟我一样都喜欢python,想成为一名优秀的程序员,也在学习python的道路上奔跑,欢迎你加入python学习群:839383765 群内每天都会分享最新业内资料,分享python免费课程,共同交流学习,让学习变(编)成(程)一种习惯!

原文地址:http://blog.51cto.com/14186420/2350074

时间: 2024-10-09 13:46:43

90 行 Python 搭一个音乐搜索工具【附代码】的相关文章

【转载】90行python搭一个音乐搜索工具 —— Song Finder

90行python搭一个音乐搜索工具 —— Song Finder Jul 23, 20153 minute read 之前一段时间读到了这篇博客,其中描述了作者如何用java实现国外著名音乐搜索工具shazam的基本功能.其中所提到的文章又将我引向了关于shazam的一篇论文及另外一篇博客.读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现了一个简单的音乐搜索工具—— Song Finder, 它的核心功能被封装在 SFEngine 中,

90 行 Python 搭一个音乐搜索工具

之前一段时间读到了这篇博客,其中描述了作者如何用java实现国外著名音乐搜索工具shazam的基本功能.其中所提到的文章又将我引向了关于shazam的一篇论文及另外一篇博客.读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现了一个简单的音乐搜索工具—— Song Finder, 它的核心功能被封装在SFEngine 中,第三方依赖方面只使用到了 scipy. 工具demo 这个demo在ipython下展示工具的使用,本项目名称为Song

用python编写一个高效搜索代码工具

用python编写一个高效搜索代码工具大多码农在linux环境下使用grep+关键词的命令搜索自己想要的代码或者log文件.今天介绍用python如何编写一个更强大的搜索工具,windows下也适用.我们的需求:1, 可以同时指定多个关键词.比如某个文件某一行中有"error: aa bb cc",如果检索关键词error和cc则可以显示该行,避免单一关键词冗余信息太多2, 可以排除某些关键词.对于"error: aa bb cc" ,如果设定排除bb,则不予显示该

用python搭一个超简易的文件服务器

这个文件服务器纯粹是在学习python cgi编程时,顺便玩玩而已,因为搭文件服务器的话完全可以linux,简单方便,这里就是随便玩玩,功能也就是只能下载文件 1.登录页面,做个简单验证 新建一个html文件,里面就是简单的账号密码登录框,点击登录后action=“file_list.html” 2.文件列表页面 新建一个html文件,里面就是一个<ul>里面包含多个<li>,然后写上文件名即可,点击下载后action =“downloads.py” 3.python文件 主要就是

[转]用Python做一个自动生成读表代码的小脚本

写在开始(本片文章不是写给小白的,至少你应该知道一些常识!) 大家在Unity开发中,肯定会把一些数据放到配置文件中,尤其是大一点的项目,每次开发一个新功能的时候,都要重复的写那些读表代码.非常烦.来个实用小工具,大家随便看看. 1 #-*- coding: utf-8 -*- 2 #----------------------------------------------------------# 3 # 版本:python-3.5.0a3-amd64 4 # 功能:生成读表代码文件 5 #

Python爬虫学习记录【内附代码、详细步骤】

引言: 昨天在网易云课堂自学了<Python网络爬虫实战>,视频链接 老师讲的很清晰,跟着实践一遍就能掌握爬虫基础了,强烈推荐! 另外,在网上看到一位学友整理的课程记录,非常详细,可以优先参考学习.传送门:请点击 本篇文章是自己同步跟着视频学习的记录,欢迎阅读~~~ 实验:新浪新闻首页爬虫实践 http://news.sina.com.cn/china/ 一.准备 浏览器内建的开发人员工具(以Chrome为例) Python3 requests 库 Python3 BeautifulSoup4

正则表达式和grep文本搜索工具

正则表达式和文本搜索工具介绍 正则表达式:如果想搜索/etc/passwd文件中以root开头的行,对与人来说很容易理解,但是对与计算机来说就无法理解,这个时候就需要使用正则表达式来表达过滤条件了,让用户实现对文本的智能搜索.正则表达式就是由元字符及正常字符所书写的模式,其中的元字符不表示字符本身的意义,而是用于表达控制或通配等功能. 正则表达式的特点是: 1. 灵活性.逻辑性和功能性非常的强: 2. 可以迅速地用极简单的方式达到字符串的复杂控制. grep:支持正则表达式,是一个文本搜索工具,

一个比ack速度快n倍的代码搜索工具: ag

一个比ack速度快n倍的代码搜索工具:  ag 银搜索者(The Silver Searcher) 一个类似于代码搜索工具ack,着重于速度. Github:   https://github.com/ggreer/the_silver_searcher Ag有什么好处? 它比一个数量级快ack. 它忽略了你.gitignore和你的文件模式.hgignore. 如果您的源代码中有文件您不想搜索,只需将其模式添加到.ignore文件中即可.(*咳嗽* *.min.js*咳嗽*) 命令名称比起第3

用Python实现一个大数据搜索及源代码

在日常生活中,大家了解搜索引擎如百度.360.搜狗.谷歌等,搜索是大数据领域里常见的需求.Splunk和ELK分别是该领域在非开源和开源领域里的领导者.本文利用很少的Python代码实现了一个基本的数据搜索功能,试图让大家理解大数据搜索的基本原理. 布隆过滤器(BloomFilter) 第一步我们先要实现一个布隆过滤器. 布隆过滤器是大数据领域的一个常见算法,它的目的是过滤掉那些不是目标的元素.也就是说如果一个要搜索的词并不存在与我的数据中,那么它可以以很快的速度返回目标不存在. 让我们看看以下