| 关键词: nbsp 代码 频率 歌曲 特征 一个 original 工具 光良 时间 | ||
之前一段时间读到了这篇博客,其中描述了作者如何用java实现国外著名音乐搜索工具shazam的基本功能。其中所提到的文章又将我引向了关于 shazam的一篇论文及另外一篇博客。读完之后发现其中的原理并不十分复杂,但是方法对噪音的健壮性却非常好,出于好奇决定自己用python自己实现 了一个简单的音乐搜索工具—— Song Finder, 它的核心功能被封装在SFEngine 中,第三方依赖方面只使用到了 scipy。 工具demo 复制代码 代码如下: In [1]: from SFEngine import * In [2]: engine = SFEngine() 在这之后我们对现有歌曲进行索引,我在original目录下准备了几十首歌曲(.wav文件)作为曲库: 复制代码 代码如下: In [3]: engine.index('original') # 索引该目录下的所有歌曲 在完成索引之后我们向Song Finder提交一段有背景噪音的歌曲录音进行搜索。对于这段《枫》在1分15秒左右的录音: 工具的返回结果是: 复制代码 代码如下: In [4]: engine.search('record/record0.wav') original/周杰伦-枫 73 original/周杰伦-枫 31 original/周杰伦-枫 10 original/周杰伦-枫 28 original/我要快樂 - 張惠妹 28 其中展示的分别是歌曲名称及片段在歌曲中出现的位置(以秒计),可以看到工具正确找回了歌曲的曲名,也找到了其在歌曲中的正确位置。 而对于这段《童话》在1分05秒左右的背景噪音更加嘈杂的录音: 工具的返回结果是: 复制代码 代码如下: In [5]: engine.search('record/record8.wav') original/光良 - 童话 67 original/光良 - 童话 39 original/光良 - 童话 33 original/光良 - 童话 135 original/光良 - 童话 69 可以看到尽管噪音非常嘈杂,但是工具仍然能成功识别所对应的歌曲并对应到歌曲的正确位置,说明工具在噪音较大的环境下有良好的健壮性! 项目主页: Github Song Finder原理 对曲库中的所有歌曲抽取特征 复制代码 代码如下: def extract_feature(self, scaled, start, interval): end = start + interval dst = fft(scaled[start: end]) length = len(dst)/2 normalized = abs(dst[:(length-1)]) feature = [ normalized[:50].argmax(), \ 50 + normalized[50:100].argmax(), \ 100 + normalized[100:200].argmax(), \ 200 + normalized[200:300].argmax(), \ 300 + normalized[300:400].argmax(), \ 400 + normalized[400:].argmax()] return feature 这样,对于一个滑动窗口,我提取到了6个频率作为其特征。对于整段音频,我们重复调用这个函数进行特征抽取:
其中44100为音频文件自身的采样频率,8192是我设定的取样窗口(对,这样hardcode是很不对的),callback是一个传入的函数,需要这个参数是因为在不同场景下对于所得到的特征会有不同的后续操作。 匹配曲库 表格。。 这样做的好处是,当在录音中提取到某一个特征频率时,我们可以从这个哈希表中找出与该特征频率相关的歌曲及时间! 当然有了这个哈希表还不够用,我们不可能把所有与特征频率相关的歌曲都抽出来,看看谁命中的次数多,因为这样会完全无视歌曲的时序信息,并引入一些错误的匹配。 我们的做法是,对于录音中在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`)] 对这个列表进行计数,可以看到哪首歌曲的哪个时间点命中的次数最多,并将命中次数最多的(曲名,时间)对返回给用户。 不足 目前只支持了wav格式的曲库及录音 以上就是Python通过90行代码搭建音乐搜索工具,希望大家喜欢。 | ||
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|