亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python通過90行代碼搭建一個音樂搜索工具

系統(tǒng) 1763 0

下面小編把具體實(shí)現(xiàn)代碼給大家分享如下:

之前一段時間讀到了這篇博客,其中描述了作者如何用java實(shí)現(xiàn)國外著名音樂搜索工具shazam的基本功能。其中所提到的文章又將我引向了關(guān)于shazam的一篇論文及另外一篇博客。讀完之后發(fā)現(xiàn)其中的原理并不十分復(fù)雜,但是方法對噪音的健壯性卻非常好,出于好奇決定自己用python自己實(shí)現(xiàn)了一個簡單的音樂搜索工具―― Song Finder, 它的核心功能被封裝在SFEngine 中,第三方依賴方面只使用到了 scipy。

工具demo
這個demo在ipython下展示工具的使用,本項(xiàng)目名稱為Song Finder,我把索引、搜索的功能全部封裝在Song Finder中的SFEngine中。首先是簡單的準(zhǔn)備工作:

復(fù)制代碼 代碼如下:

In [1]: from SFEngine import *

In [2]: engine = SFEngine()


在這之后我們對現(xiàn)有歌曲進(jìn)行索引,我在original目錄下準(zhǔn)備了幾十首歌曲(.wav文件)作為曲庫:

復(fù)制代碼 代碼如下:

In [3]: engine.index('original') # 索引該目錄下的所有歌曲

在完成索引之后我們向Song Finder提交一段有背景噪音的歌曲錄音進(jìn)行搜索。對于這段《楓》在1分15秒左右的錄音:

工具的返回結(jié)果是:

復(fù)制代碼 代碼如下:

In [4]: engine.search('record/record0.wav')
original/周杰倫-楓 73
original/周杰倫-楓 31
original/周杰倫-楓 10
original/周杰倫-楓 28
original/我要快?? - ??惠妹 28

其中展示的分別是歌曲名稱及片段在歌曲中出現(xiàn)的位置(以秒計(jì)),可以看到工具正確找回了歌曲的曲名,也找到了其在歌曲中的正確位置。

而對于這段《童話》在1分05秒左右的背景噪音更加嘈雜的錄音:

工具的返回結(jié)果是:

復(fù)制代碼 代碼如下:

In [5]: engine.search('record/record8.wav')
original/光良 - 童話 67
original/光良 - 童話 39
original/光良 - 童話 33
original/光良 - 童話 135
original/光良 - 童話 69

可以看到盡管噪音非常嘈雜,但是工具仍然能成功識別所對應(yīng)的歌曲并對應(yīng)到歌曲的正確位置,說明工具在噪音較大的環(huán)境下有良好的健壯性!

項(xiàng)目主頁: Github

Song Finder原理
給定曲庫對一個錄音片段進(jìn)行檢索是一個不折不扣的搜索問題,但是對音頻的搜索并不像對文檔、數(shù)據(jù)的搜索那么直接。為了完成對音樂的搜索,工具需要完成下列3個任務(wù):

對曲庫中的所有歌曲抽取特征
以相同的方式對錄音片段提取特征
根據(jù)錄音片段的特征對曲庫進(jìn)行搜索,返回最相似的歌曲及其在歌曲中的位置
特征提取?離散傅立葉變換!
為了對音樂(音頻)提取特征,一個很直接的想法是得到音樂的音高的信息,而音高在物理上對應(yīng)的則又是波的頻率信息。為了獲取這類信息,一個非常直接的額做法是使用離散傅葉變化對聲音進(jìn)行分析,即使用一個滑動窗口對聲音進(jìn)行采樣,對窗口內(nèi)的數(shù)據(jù)進(jìn)行離散傅立葉變化,將時間域上的信息變換為頻率域上的信息,使用scipy的接口可以很輕松的完成。在這之后我們將頻率分段,提取每頻率中振幅最大的頻率:

復(fù)制代碼 代碼如下:

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個頻率作為其特征。對于整段音頻,我們重復(fù)調(diào)用這個函數(shù)進(jìn)行特征抽取:

            
def sample(self, filename, start_second, duration = 5, callback = None):

 start = start_second * 44100
 if duration == 0:
  end = 1e15
 else:
  end = start + 44100 * duration
 interval = 8192
 scaled = self.read_and_scale(filename)
 length = scaled.size
 while start < min(length, end):
  feature = self.extract_feature(scaled, start, interval)
  if callback != None:
   callback(filename, start, feature)
  start += interval


          

其中44100為音頻文件自身的采樣頻率,8192是我設(shè)定的取樣窗口(對,這樣hardcode是很不對的),callback是一個傳入的函數(shù),需要這個參數(shù)是因?yàn)樵诓煌瑘鼍跋聦τ谒玫降奶卣鲿胁煌暮罄m(xù)操作。

匹配曲庫
在得到歌曲、錄音的大量特征后,如何進(jìn)行高效搜索是一個問題。一個有效的做法是建立一個特殊的哈希表,其中的key是頻率,其對應(yīng)的value是一系列(曲名,時間)的tuple,其記錄的是某一歌曲在某一時間出現(xiàn)了某一特征頻率,但是以頻率為key而非以曲名或時間為key。

表格。。

這樣做的好處是,當(dāng)在錄音中提取到某一個特征頻率時,我們可以從這個哈希表中找出與該特征頻率相關(guān)的歌曲及時間!

當(dāng)然有了這個哈希表還不夠用,我們不可能把所有與特征頻率相關(guān)的歌曲都抽出來,看看誰命中的次數(shù)多,因?yàn)檫@樣會完全無視歌曲的時序信息,并引入一些錯誤的匹配。

我們的做法是,對于錄音中在t時間點(diǎn)的一個特征頻率f,從曲庫找出所有與f相關(guān)的(曲名,時間)tuple,例如我們得到了

復(fù)制代碼 代碼如下:

[(s1, t1), (s2, t2), (s3, t3)]

我們使用時間進(jìn)行對齊,得到這個列表

復(fù)制代碼 代碼如下:

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

記為

復(fù)制代碼 代碼如下:

[(s1, t1`), (s2, t2`), (s3, t3`)]

我們對所有時間點(diǎn)的所有特征頻率均做上述操作,得到了一個大列表:

復(fù)制代碼 代碼如下:

[(s1, t1`), (s2, t2`), (s3, t3`), ..., (sn, tn`)]

對這個列表進(jìn)行計(jì)數(shù),可以看到哪首歌曲的哪個時間點(diǎn)命中的次數(shù)最多,并將命中次數(shù)最多的(曲名,時間)對返回給用戶。

不足
這個小工具是一個幾個小時寫成的hack,有許都地方需要改進(jìn),例如:

目前只支持了wav格式的曲庫及錄音
所有數(shù)據(jù)都放在內(nèi)存中,曲庫體積增大時需要引入更好的后端存儲
索引應(yīng)該并行化,匹配也應(yīng)該并行化,匹配的模型其實(shí)是典型的map-reduce。

以上就是Python通過90行代碼搭建音樂搜索工具,希望大家喜歡。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产性生活视频 | 91久久澡人人爽人人添 | 日韩国产综合 | 成人夜色视频网站在线观看 | 欧美成人欧美激情欧美风情 | 国内久久久久影院精品 | 久久精选| 亚洲欧美日本视频 | 91精品一区二区三区久久久久 | 毛片电| 妖精视频在线看免费视频 | 永久免费观看黄网站 | 成人网18免费视频 | 久久夜夜 | 亚洲视频免费一区 | 日本不卡高清免费v | 国产亚洲精品激情一区二区三区 | 99久久免费国产香蕉麻豆 | 日韩欧美亚州 | 九九九九九九伊人 | 欧美日本另类xxx乱大交 | 精品一区二区三区的国产在线观看 | 国产福利视频奶水在线 | 久久成人国产精品青青 | 在线中文字幕一区 | 伊人二区 | 欧美成人欧美激情欧美风情 | 久久艹免费视频 | 香蕉视频日本 | 99国产福利视频在线观看 | 中文字幕在线免费观看视频 | 中文视频| 久久精品国产久精国产 | 久久亚洲精品专区蓝色区 | 亚洲综合久久久久久中文字幕 | 久久久久久综合一区中文字幕 | 第一福利在线视频 | 欧美激情在线精品一区二区 | 久久免费大片 | 强制高潮18xxxxhd日韩 | 成人毛片全部免费观看 |