概念理解

  1. 语音识别:通过一种语音检索算法来识别一段音频内容的含义。
  2. 音频文件:指带有声音的文件,比如音乐。
  3. MFCC:音频文件转为数字的过程
  4. 时域:振幅Y和时间T的关系。
  5. 频域:振幅Y和频率F的关系。
  6. 短时傅里叶变换:通过对每个时间极短的音频片段做傅里叶变换,来得到这个时间段的频率分布,之所以成为短时,是因为这个算法只有再短时内语音音频的频率以及振幅是比较平稳的,如果时间过长就会导致傅里叶变换不准确。
  7. 频谱图:每个时间点出现的频率分布图,即每一帧或者每时刻上出现的频率数值和振幅数值,为了用二维数据表示这个三维数据,把振幅压缩到二维平面中,使用颜色的浅重来表示振幅的大小。[见图1A]
  8. 稀疏矩阵/星云图:经过处理的频谱图,把频谱图颜色重的变成星星【锚点】,把其它变成空白。[见图1B]
  9. 指纹哈希:指纹哈希是由星座图组成的,星座图中时间-频率点对组合在一起。选择锚点,每个锚点都有一个与之相关联的目标区域。每个锚点依次与目标区域内的点配对,每一对产生两个频率分量加上点之间的时间差.[见图1C]
  10. Hash:哈希值,32位的不可重复的数字,数据库用来存储数据的一种方式,优点查询速度快,缺点存储空间剧增,典型的拿空间换时间。
  11. time:时间值,32位不可重复的数字
  12. 哈希·时间偏移记录:Hash:time = [f1:f2:∆t]:t1 [见图1D]
  13. 扇出因子:在计算哈系数时,一个锚点的目标区域中一次处理相关锚点的个数,可理解为KNN中的K值,计算相邻点的个数
  14. 密度因子:单位区域内锚点的个数
  15. 每秒处理音频记录的哈希数 = 每秒星座点的密度因子 * 进入目标区域的扇出因子[F],也就是为什么扇出因子直接导致存储空间成本的变化
  16. 噪音:
  17. 降噪算法:【腐蚀算法】一种降噪的算法,类似于图形算法里面的原理https://jingyan.baidu.com/article/f96699bbf99d9e894f3c1b4c.html
  18. 张量:维度的意思
  19. 阈值:满足条件的最小值或者最大值

算法原理

由于商业原因,以下只是部分代码,只讲了大概原理,其原理是通过给歌曲建立指纹库来验证被检测样本是哪个歌曲,如果某段歌曲匹配了,那么它们在时间上会出现线性关系。

具体步骤如下:

A、建立歌曲指纹

1、读取歌曲

通过librosa包获取语音数据

# 语音预处理,生成频谱数据def _pre_music(self, music_path):# 音频时间序列,音频的采样率y, sr = librosa.load(path=music_path,sr=hp.fingerprint.core.sr,)arr2D = librosa.stft(y=y,n_fft=hp.fingerprint.core.n_fft,hop_length=hp.fingerprint.core.hop_length,win_length=hp.fingerprint.core.win_length)return np.abs(arr2D) ** 2

2、获取频谱图

通过Au软件可以看出来,音频的频谱图

  随着每个时间点的放大,可以看到每一个采样点的之间的频谱图

把声谱图转为频谱图的过程是通过MFCC得到的,有兴趣的可以自己搜索相关技术文章,这属于信号处理专业的相关知识。

转为频谱图:shape = [频率,帧数]

# 生成频谱图
arr2D = mlab.specgram(# 数据channel_samples,# 窗口大小NFFT=wsize,# 采样率Fs=Fs,# 加窗window=mlab.window_hanning,# 重叠率noverlap=int(wsize * wratio))[0]
# (2049, 5027)
# print(np.shape(arr2D))

3、频谱图转为星图

把频谱图里面的频率0变为最小值,防止无法取对数

取对数,作用:某些值过大

取对数之后会出现无穷小的值,把这些值变为0

求局部最大值【即锚点-星星】,neighborhood控制着样本密度

# maximun_filter 找到局部最大值所对应的坐标
struct = generate_binary_structure(2, 2)  # 2维 离中心点一个距离
neighborhood = iterate_structure(struct, hp.fingerprint.core.neighborhood)  # 中心点扩大到离中心点40个距离
local_max = maximum_filter(spectrogram, footprint=neighborhood) == spectrogram# 局部最大值
amps = spectrogram[local_max]

获取局部最大值的坐标【即锚点坐标】:[时间,频率], shape = [y,x] = [频率,时间]

# 获得peakes 是按[行,列]返回的:j是频率 i是时间
j, i = np.where(local_max)

通过过滤能量最小值来减少噪音

4、存储指纹和歌曲ID

根据时间进行排序

peakes = sorted(peakes)

时间偏移坐标:t1

一个锚点的哈希个数取决于,当前锚点与其它锚点计算的范围:0<t1<200,样本密度和扇出因子是控制哈希·时间偏移记录的数量。

# 锚点
for i in range(len(peakes)):# 近邻点for j in range(1, hp.fingerprint.core.near_num):# 判断下标是否越界if (i + j) < len(peakes):t_1 = peakes[i][0]t_2 = peakes[i + j][0]f_1 = peakes[i][1]f_2 = peakes[i + j][1]delta_t = t_2 - t_1

建立每个锚点的哈希值:[f1,f2,delta_t]

hash_str = "%s|%s|%s" % (str(freq1), str(freq2), str(t_delta))
h = hashlib.sha1(hash_str.encode('utf-8'))
yield (h.hexdigest()[0:20], t1)

数据库中的存储的数据是:哈希值,时间偏移记录,歌曲ID,

B、待测歌曲样本

获取待测样本数据,通过短时傅里叶变换转为频谱图

def get_audio():parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter)parser.add_argument('-s', '--seconds', nargs='?')args = parser.parse_args()if not args.seconds:args.seconds = "7"seconds = int(args.seconds)chunksize = 2 ** 12channels = 1record_forever = Falselistener = Listener()listener.start_recording(seconds=seconds,chunksize=chunksize,channels=channels)while True:bufferSize = int(listener.rate / listener.chunksize * seconds)print("正在录音")for i in range(0, bufferSize):number = listener.process_recording()if not record_forever: breaklistener.stop_recording()print("录音停止")listener.save_recorded('xxx.mp3')return './xxx.mp3'

样本频谱图

样本星座图

  1. 用最小值替换全0,取log能量对数,把负无穷小取0
  2. 通过maximum_filter()获取最大值坐标,得到星座图
  3. 最后通过偏离每个锚点,计算得到每个锚点和目标区域的Hash:time
  4. 在数据库中通过查询hash来得到匹配的match_hashes,以及t_offset
  5. 统计match_hashes中每个t_offset所对应的歌曲id个数
  6. 个数最多的歌曲id就是该歌曲,t_offset是开始的地方
 if len(matches) > 0:match_collections = {}max_count = 0start_time = Nonefinal_music_id = Nonex, y, z = [], [], []for matche in matches:# 数据库t 样本tmusic_id, t, t_sample = matchex.append(int(t))y.append(t_sample)z.append(music_id)# 偏移值offset = int(t) - t_sample# 判断字典里面是否有这个偏移if offset not in match_collections:match_collections[offset] = {}pass# 判断字典里面是否有这个music_idif music_id not in match_collections[offset]:match_collections[offset][music_id] = 0passmatch_collections[offset][music_id] += 1# 判断这个偏移下的music_id是否是最多if match_collections[offset][music_id] > max_count:max_count = match_collections[offset][music_id]start_time = offsetfinal_music_id = music_idprint(x, y, z)drow_plot(x, y, z, show=True)print(match_collections, max_count)# 开始匹配时间print((start_time * hp.fingerprint.hop_length / hp.fingerprint.sr))music_name = connector.find_music_by_id(final_music_id)print(music_name)

结果

线性关系图:

听歌识曲算法技术[语音识别]相关推荐

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

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

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

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

  3. Chrome插件:网易云音乐听歌识曲

    大家好,我是若川.持续组织了8个月源码共读活动,感兴趣的可以 点此加我微信ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...

  4. Chrome插件:云音乐听歌识曲

    当你用网页在视频网站刷视频的时候,有没有碰到过一个 BGM 激起你内心的波澜,而你却不知道它的名字.此时只能打开手机进行听歌识曲,而通过一个浏览器的插件却更容易解决这个问题.不需要繁琐的掏出手机,也不 ...

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

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

  6. 基于音频指纹技术的微信“摇一摇搜歌”和QQ音乐“听歌识曲”

    摘要: 逛商场时想知道广播里放的好听的歌是什么?听到音乐想跟着唱,想不起歌词怎么办?这些问题都通过微信"摇一摇搜歌"和QQ音乐"听歌识曲"帮您解决! 逛商场时想 ...

  7. atitit 音频 项目 系列功能表 音乐 v3 t67.docx Atitit 音频 项目 系列功能表 1.音频 音乐 语言领域的功能表 听歌识曲功能 酷我功能。 铃声 功能。。 音频切割(按

    atitit 音频 项目 系列功能表 音乐 v3 t67.docx Atitit 音频 项目 系列功能表 音频 音乐 语言领域的功能表 听歌识曲功能 酷我功能. 铃声 功能.. 音频切割(按照副歌部分 ...

  8. atitit 音频 项目 系列功能表 音乐 v3 t67.docx Atitit 音频 项目 系列功能表 音频 音乐 语言领域的功能表 听歌识曲功能 酷我功能。 铃声 功能。。 音频切割(按照副歌部

    atitit 音频 项目 系列功能表 音乐 v3 t67.docx Atitit 音频 项目 系列功能表 音频 音乐 语言领域的功能表 听歌识曲功能 酷我功能. 铃声 功能.. 音频切割(按照副歌部分 ...

  9. 听歌识曲原理探究以及样例代码

    技术故事 听歌识曲是一个很成熟的技术.现在的主流音乐播放器,几乎都有这个功能. 但是第一个吃螃蟹的是上个世纪末的一个叫**"Shazam Entertainment Limited" ...

最新文章

  1. 了解下C# 基本语法
  2. Jvm 系列(六):Java 服务 GC 参数调优案例
  3. python伪造浏览器请求头_Python3 伪装浏览器的方法示例
  4. wxWidgets:可用类概述
  5. MFC添加自定义消息及重写消息过程
  6. js修改id的值_如何修改pytesthtml源码来优化接口自动化测试报告
  7. element 下拉选择_猿实战18——商品发布之类目选择
  8. String引起的OutOfMemory异常 + 如何计算C#对象所占内存的大小
  9. 2018 年,JavaScript 都经历了什么?
  10. 插槽作用域渲染按钮开关 ~ 满满的干货哦
  11. PHP中使用CURL(三)
  12. mtk2503 新增物联网卡apn
  13. c 易语言dll 循环,易语言的Dll命令及程序集知识点
  14. 火狐安装网页视频下载插件(Video DownloadHelper)
  15. Java 机器学习库Smile实战(一)SVM
  16. Tomcat8如何配置项目appBase和docBase
  17. mysql数据库test密码_TestCenter常见问题
  18. 计算机专业专科可以进的国企,专科毕业生想进国企?这三大专业不要错过,成功率高达60%...
  19. 【配电网重构】基于粒子群算法实现最小化功率损耗的配电网重构附matlab代码
  20. 《Context Contrasted Feature and Gated Multi-Scale Aggregation for Scene Segmentation》论文阅读

热门文章

  1. word文档在保存后消失,如何恢复?
  2. 部分有关会计单词的英中文对照
  3. CNN:RCNN、SPPNet、Fast RCNN、Faster RCNN、YOLO V1 V2 V3、SSD、FCN、SegNet、U-Net、DeepLab V1 V2 V3、Mask RCNN
  4. Svelte-Ui-Admin基于svelte-ui中后台管理系统|Svelte3+Vite3后台框架
  5. adb shell 模拟器 关闭\打开WIFI
  6. 创蓝253-创蓝万数平台图像识别OCR技术
  7. 华为过程可信cib是指_华为EMUI10取消IMEI?数字联盟可信ID——更可靠的移动设备唯一标识...
  8. python英文分句_英文分句
  9. 设置 IntelliJ IDEA 主题和字体的方法
  10. C#按钮添加图片的解决