当前位置: 首页 > news >正文

Shazam音乐检索算法原理及实现

 

算法基本流程如下: 

1. 采集音乐库

 2. 音乐指纹采集

3. 采用局部最大值作为特征点

 4. 将临近的特征点进行组合形成特征点对

5. 对每个特征点对进行hash编码

编码过程:将f1和f2进行10bit量化,其余bit用来存储时间偏移合集形成32bit的hash码

Hash = f1|f2<<10|diff_t<<20,存储信息(t1,Hash)

实现:

import numpy as np
import librosa
from scipy import signal
import pickle
import os
fix_rate = 16000 
win_length_seconds = 0.5
frequency_bits = 10
num_peaks = 15# 构造歌曲名与歌曲id之间的映射字典
def song_collect(base_path):index = 0dic_idx2song = {}for roots, dirs, files in os.walk(base_path):for file in files:if file.endswith(('.mp3', '.wav')):file_song = os.path.join(roots, file)dic_idx2song[index] = file_songindex += 1return dic_idx2song# 提取局部最大特征点
def collect_map(y, fs, win_length_seconds=0.5, num_peaks=15):win_length = int(win_length_seconds * fs)hop_length = int(win_length // 2)S = librosa.stft(y, n_fft=win_length, win_length=win_length, hop_length=hop_length)S = np.abs(S) # 获取频谱图D, T = np.shape(S)constellation_map = []  for i in range(T):spectrum = S[:, i]peaks_index, props = signal.find_peaks(spectrum, prominence=0, distance=200)# 根据显著性进行排序n_peaks= min(num_peaks, len(peaks_index))largest_peaks_index = np.argpartition(props['prominences'], -n_peaks)[-n_peaks:]for peak_index in peaks_index[largest_peaks_index]:frequency = fs / win_length * peak_index# 保存局部最大值点的时-频信息constellation_map.append([i, frequency])return constellation_map# 进行Hash编码
def create_hash(constellation_map, fs, frequency_bits=10, song_id=None):upper_frequency = fs / 2hashes = {}for idx, (time, freq) in enumerate(constellation_map):for other_time, other_freq in constellation_map[idx: idx + 100]: # 从邻近的100个点中找点对diff = int(other_time - time)if diff <= 1 or diff > 10: # 在一定时间范围内找点对continuefreq_binned = int(freq / upper_frequency * (2 ** frequency_bits))other_freq_binned = int(other_freq / upper_frequency * (2 ** frequency_bits))hash = int(freq_binned) | (int(other_freq) << 10) | (int(diff) << 20)hashes[hash] = (time, song_id)return hashes

特征提取:feature_collect.py

# 获取数据库中所有音乐
path_music = 'data'
current_path = os.getcwd()
path_songs = os.path.join(current_path, path_music)
dic_idx2song = song_collect(path_songs)# 对每条音乐进行特征提取
database = {}
for song_id in dic_idx2song.keys():file = dic_idx2song[song_id]print("collect info of file", file)# 读取音乐y, fs = librosa.load(file, sr=fix_rate)# 提取特征对constellation_map = collect_map(y, fs, win_length_seconds=win_length_seconds, num_peaks=num_peaks)# 获取hash值hashes = create_hash(constellation_map, fs, frequency_bits=frequency_bits, song_id=song_id)# 把hash信息填充入数据库for hash, time_index_pair in hashes.items():if hash not in database:database[hash] = []database[hash].append(time_index_pair)# 对数据进行保存
with open('database.pickle', 'wb') as db:pickle.dump(database, db, pickle.HIGHEST_PROTOCOL)
with open('song_index.pickle', 'wb') as songs:pickle.dump(dic_idx2song, songs, pickle.HIGHEST_PROTOCOL)
# 加载数据库
database = pickle.load(open('database.pickle', 'rb'))
dic_idx2song = pickle.load(open('song_index.pickle', 'rb'))
print(len(database))# 检索过程
def getscores(y, fs, database):# 对检索语音提取hashconstellation_map = collect_map(y, fs)hashes = create_hash(constellation_map, fs, frequency_bits=10, song_id=None)# 获取与数据库中每首歌的hash匹配matches_per_song = {}for hash, (sample_time, _) in hashes.items():if hash in database:maching_occurences = database[hash]for source_time, song_index in maching_occurences:if song_index not in matches_per_song:matches_per_song[song_index] = []matches_per_song[song_index].append((hash, sample_time, source_time))scores = {}# 对于匹配的hash,计算测试样本时间和数据库中样本时间的偏差for song_index, matches in matches_per_song.items():
#         scores[song_index] = len(matches)song_scores_by_offset = {}# 对相同的时间偏差进行累计for hash, sample_time, source_time in matches:delta = source_time - sample_timeif delta not in song_scores_by_offset:song_scores_by_offset[delta] = 0song_scores_by_offset[delta] += 1# 计算每条歌曲的最大累计偏差max = (0, 0)for offset, score in song_scores_by_offset.items():if score > max[1]:max = (offset, score)scores[song_index] = maxscores = sorted(scores.items(), key=lambda x:x[1][1], reverse=True)return scores

音乐检索:music_research.py

import threading
from playsound import playsounddef cycle(path):while 1:playsound(path)
def play(path, cyc=False):if cyc:cycle(path)else:playsound(path)path = 'test_music/record4.wav'
y, fs = librosa.load(path, sr=fix_rate)
# 播放待检索音频
music = threading.Thread(target=play, args=(path,))
music.start()# 检索打分
scores = getscores(y, fs, database)# 打印检索信息
for k, v in scores:file = dic_idx2song[k]name = os.path.split(file)[-1]# print("%s :%d"%(name, v))print("%s: %d: %d"%(name, v[0], v[1]))# 打印结果
if len(scores) > 0 and scores[0][1][1] > 50:print("检索结果为:", os.path.split(dic_idx2song[scores[0][0]])[-1])
else:print("没有搜索到该音乐")

麦克风录音识别音乐:

import pyaudio
import waveRATE = 48000 # 采样率
CHUNK = 1024 # 帧大小
record_seconds = 10 # 录音时长s
CHANNWLS = 2 # 通道数# 创建pyaudio流
audio = pyaudio.PyAudio()stream = audio.open(format=pyaudio.paInt16, # 使用量化位数16位channels=CHANNWLS, # 输入声道数目rate=RATE, # 采样率input=True, # 打开输入流frames_per_buffer=CHUNK) # 缓冲区大小frames = [] # 存放录制的数据
# 开始录音
print('录音中。。。')
for i in range(0, int(RATE / CHUNK * record_seconds)):# 从麦克风读取数据流data = stream.read(CHUNK)# 将数据追加到列表中frames.append(data)# 停止录音,关闭输入流
stream.stop_stream()
stream.close()
audio.terminate()# 将录音数据写入wav文件中
with wave.open('test_music/test.wav', 'wb') as wf:wf.setnchannels(CHANNWLS)wf.setsampwidth(audio.get_sample_size(pyaudio.paInt16))wf.setframerate(RATE)wf.writeframes(b''.join(frames))# 打开录音文件
path = 'test_music/test.wav'
y, fs = librosa.load(path, sr=fix_rate)# 线程播放待检索音频
# music = threading.Thread(target=play, args=(path,))
# music.start()# 音乐检索
print('检索中。。。')
scores = getscores(y, fix_rate, database)# 打印检索信息
# for k, v in scores:
#     file = dic_idx2song[k]
#     name = os.path.split(file)[-1]
#     # print("%s :%d"%(name, v))
#     print("%s: %d: %d"%(name, v[0], v[1]))# 打印结果
if len(scores) > 0 and scores[0][1][1] > 50:print("检索结果为:", os.path.split(dic_idx2song[scores[0][0]])[-1])
else:print("没有搜索到该音乐")

参考:音乐检索-Shazam算法原理_哔哩哔哩_bilibili

相关文章:

Shazam音乐检索算法原理及实现

算法基本流程如下&#xff1a; 1. 采集音乐库 2. 音乐指纹采集 3. 采用局部最大值作为特征点 4. 将临近的特征点进行组合形成特征点对 5. 对每个特征点对进行hash编码 编码过程&#xff1a;将f1和f2进行10bit量化&#xff0c;其余bit用来存储时间偏移合集形成32bit的hash码 …...

vue递归组件

父组件&#xff1a; <template><div><treeVue :treeData"treeData"></treeVue></div> </template><script setup lang"ts"> import { reactive } from "vue"; import treeVue from "./tree.vue…...

软件测试/测试开发丨测试用例自动录入 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤&#xff0c;节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…...

来学Python啦,大话字符串

To be a happy man&#xff0c; reading&#xff0c; travel&#xff0c; hard work&#xff0c; care for the body and mind。做一个幸福的人&#xff0c;读书&#xff0c;旅行&#xff0c;努力工作&#xff0c;关心身体和心境。 前面我们讲解过关于用Python写温度转换器&…...

pyqt5设置背景图片

PyQt5设置背景图片 1、打开QTDesigner 创建一个UI&#xff0c;camera.ui。 2、创建一个pictures.qrc文件 在ui文件同级目录下先创建一个pictures.txt&#xff0c;填写内容&#xff1a; <RCC><qresource prefix"media"><file>1.jpg</file>…...

C# WPF 自己写的一个模拟病毒传播的程序,有可视化

源代码: https://github.com/t39q/VirusSpread 主要代码 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace VirusSpread.Bu…...

stable diffusion实践操作-大模型介绍-SDXL1大模型

系列文章目录 大家移步下面链接中&#xff0c;里面详细介绍了stable diffusion的原理&#xff0c;操作等&#xff08;本文只是下面系列文章的一个写作模板&#xff09;。 stable diffusion实践操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生…...

软考高级系统架构设计师系列案例考点专题四:嵌入式系统

软考高级系统架构设计师系列案例考点专题四:嵌入式系统 一、相关概念二、软件可靠性和硬件可靠性的区别三、可靠性指标四、可靠性设计五、冗余技术六、软件容错七、双机容错技术八、集群技术九、负载均衡十、可维护性的评价指标十一、软件维护的分类嵌入式每年必考一题,但是属…...

Django Form实现表单使用及应用场景

首先需要定义一个使用场景&#xff1a; 音乐网站的前端部分可以添加上传歌手的单曲&#xff0c; 这个添加页面就使用django form表单来实现。 目录 数据表内容 歌手表及表模型 单曲表及表模型 演示表单使用 设置路由 创建form.py 视图实例化表单类 模板使用表单对象 表…...

golang面试题:json包变量不加tag会怎么样?

问题 json包里使用的时候&#xff0c;结构体里的变量不加tag能不能正常转成json里的字段&#xff1f; 怎么答 如果变量首字母小写&#xff0c;则为private。无论如何不能转&#xff0c;因为取不到反射信息。如果变量首字母大写&#xff0c;则为public。 不加tag&#xff0c…...

国内项目管理中级证书CSPM-3正在报名!

CSPM-3中级项目管理专业人员认证&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…...

vue表格不显示列号123456

我在网上找了半天&#xff0c;都是如何添加列号123456的&#xff0c;没有找到不显示列号的参考&#xff0c;现在把这个解决了&#xff0c;特此记录一下。 没有加右边的就会显示&#xff0c;加上右边的就隐藏了...

【大数据】Kafka 入门指南

Kafka 入门指南 1.Kafka 简介2.Kafka 架构3.分区与副本4.偏移量5.消费者组6.总结 1.Kafka 简介 Apache Kafka 是一种高吞吐、分布式的流处理平台&#xff0c;由 LinkedIn 开发并于 2011 年开源。它具有 高伸缩性、高可靠性 和 低延迟 等特点&#xff0c;因此在大型数据处理场景…...

Qt 5.15集成Crypto++ 8.8.0(MSVC 2019)笔记

一、背景 笔者已介绍过在Qt 5.15.x中使用MinGW&#xff08;8.10版本&#xff09;编译并集成Crypto 8.8.0。 但是该编译出来的库&#xff08;.a和.dll&#xff09;不适用MSVC&#xff08;2019版本&#xff09;构建环境&#xff0c;需要重新编译&#xff08;.lib或和.dll&#xf…...

前端面试的话术集锦第 9 篇:高频考点(webpack性能优化)

这是记录前端面试的话术集锦第九篇博文——高频考点(webpack性能优化),我会不断更新该博文。❗❗❗ 在此章节中,我不会浪费篇幅给大家讲如何写配置文件。如果你想学习这方面的内容,那么完全可以去官网学习。在这部分的内容中,我们会聚焦于以下两个知识点,并且每一个知识…...

程序员,你真热爱编程吗?

程序员的热爱与演变 我发现&#xff0c;程序员这个行业不像其他行业那样&#xff0c;很多人是因为热爱编程才去做程序员&#xff0c;不会被逼无奈去做程序员&#xff08;要是真有就太惨了&#xff09;。 热爱编程的漫长过程 热爱过、⼜不爱了、⼜爱了&#xff0c;这是个过程…...

算法通关村-----海量数据的处理方法

从40亿中产生一个不存在的数 问题描述 给定一个文件&#xff0c;包含40亿个非负整数&#xff0c;请你设计一个算法&#xff0c;产生一个不在该文件中的数字。假设你只有1GB内存。 问题分析 40亿整数,在java中&#xff0c;用int存储的话&#xff0c;大概需要40亿✖️4B,大约…...

Pytorch 多卡并行(1)—— 原理简介和 DDP 并行实践

近年来&#xff0c;深度学习模型的规模越来越大&#xff0c;需要处理的数据也越来越多&#xff0c;单卡训练的显存空间和计算效率都越来越难以满足需求。因此&#xff0c;多卡并行训练成为了一个必要的解决方案本文主要介绍使用 Pytorch 的 DistributedDataParallel&#xff08…...

快速排序(重点)

前言 快排是一种比较重要的排序算法&#xff0c;他的思想有时候会作用到个别算法提上&#xff0c;公司招聘的笔试上有时候也有他的过程推导题&#xff0c;所以搞懂快排势在必行&#xff01;&#xff01;&#xff01; 快速排序 基本思想&#xff1a; 根据基准&#xff0c;将数…...

python高级内置函数介绍及应用举例

目录 1. 概述2. 举例 1. 概述 Python中有许多高级内置函数&#xff0c;它们提供了丰富的功能和便利性&#xff0c;可以大大简化代码并提高效率。以下是一些常用的高级内置函数&#xff1a; map()&#xff1a; 用于将一个函数应用于一个可迭代对象的所有项&#xff0c;返回一…...

人体呼吸存在传感器成品,毫米波雷达探测感知技术,引领智能家居新潮流

随着科技的不断进步和人们生活质量的提高&#xff0c;智能化家居逐渐成为一种时尚和生活方式。 人体存在传感器作为智能家居中的重要组成部分&#xff0c;能够实时监测环境中人体是否存在&#xff0c;为智能家居系统提供更加精准的控制和联动。 在这个充满创新的时代&#xf…...

软件设计模式(三):责任链模式

前言 前面荔枝梳理了有关单例模式、策略模式的相关知识&#xff0c;这篇文章荔枝将沿用之前的写法根据示例demo来体会这种责任链设计模式&#xff0c;希望对有需要的小伙伴有帮助吧哈哈哈哈哈哈~~~ 文章目录 前言 责任链模式 1 简单场景 2 责任链模式理解 3 Java下servl…...

开发者的商业智慧:产品立项策划你知道多少?

文章目录 想法的萌芽&#x1f31f;初步评估产品可行性&#x1f34a;分析核心功能和特点以及竞争对手&#x1f4dd;大健康监测&#x1f4dd;时尚新科技产品&#x1f4dd;准确性&#x1f4dd;多功能&#x1f4dd;品牌口碑&#x1f4dd;数据分析与个性化建议&#x1f4dd;社交互动…...

Linux 6.6 初步支持AMD 新一代 Zen 5 处理器

AMD 下一代 Zen 5 CPU 现已开始为 Linux 6.6 支持提交相关代码&#xff0c;最新补丁包括提供温度监控和 EDAC 报告等。 最新的 Linux 6.6 代码中已经加入了包括支持硬件监视器温度监控和 EDAC 报告的补丁。此外&#xff0c;新版本还加入了 x86 / misc 补丁&#xff0c;Phoronix…...

第五章 Linux常用应用软件

第五章 Linux常用应用软件 ​ Ubuntu包含了日常所需的常用程序&#xff0c;集成了跨平台的办公套件LibreOffice和Mozila Firefox浏览器等。还提供了文本处理工具、图片处理工具等。 1.LibreOffice ​ LibreOffice免费开源&#xff0c;遵照GPL分发源代码&#xff0c;与OpenOf…...

连接云-边-端,构建火山引擎边缘云网技术体系

近日&#xff0c;火山引擎边缘云网络产品研发负责人韩伟在LiveVideoStack Con 2023上海站围绕边缘云海量分布式节点和上百T的网络规模&#xff0c;结合边缘云快速发展期间遇到的各种问题和挑战&#xff0c;分享了火山引擎边缘云网的全球基础设施&#xff0c;融合开放的云网技术…...

系统架构设计师(第二版)学习笔记----系统架构设计师概述

【原文链接】系统架构设计师&#xff08;第二版&#xff09;学习笔记----系统架构设计师概述 文章目录 一、架构设计师的定义、职责和任务1.1 架构设计师的定义1.2 架构设计师的任务 二、架构设计师应具备的专业素质2.1 架构设计师应具备的专业知识2.2 架构设计师的知识结构2.3…...

自动化测试:Selenium中的时间等待

在 Selenium 中&#xff0c;时间等待指在测试用例中等待某个操作完成或某个事件发生的时间。Selenium 中提供了多种方式来进行时间等待&#xff0c;包括使用 ExpectedConditions 中的 presence_of_element_located 和 visibility_of_element_located 方法等待元素可见或不可见&…...

vim 替换命令 “:s“

vim 替换命令 ":s" 1. 替换光标所在行的第一个匹配串2. 替换光标所在行全部匹配项3. 替换两行之间每行的第一个匹配项4. 替换两行之间的全部匹配项5. 替换整个文件中的每个匹配串6. 查找整个文件中的每个匹配串并询问是否替换 1. 替换光标所在行的第一个匹配串 命令…...

【golang】调度系列之m

调度系列 调度系列之goroutine 上一篇中介绍了goroutine&#xff0c;最本质的一句话就是goroutine是用户态的任务。我们通常说的goroutine运行其实严格来说并不准确&#xff0c;因为任务只能被执行。那么goroutine是被谁执行呢&#xff1f;是被m执行。 在GMP的架构中&#xff…...

报名网站建设公司哪里有/推广免费

今天在网上发现这样一个不错的小软件&#xff0c;通过这个软件在Windows XP机器上调试多个Web程序就方便了。软件名称&#xff1a;IIS admin下载地址&#xff1a;http://www.firstserved.net/services/iisadmin.php使用方法&#xff1a;运行IIS admin, 会在右下角出现小图标&am…...

php手机网站/四年级摘抄一小段新闻

简介 之前我们想到Excel解析一般是使用POI&#xff0c;但POI存在一个严重的问题&#xff0c;就是非常消耗内存。所以阿里人员对它进行了重写从而诞生了easyexcel&#xff0c;它解决了过于消耗内存问题&#xff0c;也对它进行了封装让使用者使用更加便利。 新手同学&#xff0…...

南京网站建设设计/网络策划书范文

计算机二级C语言程序填空题练习题导语&#xff1a;为帮助同学们更好更有准备地复习计算机二级C语言&#xff0c;小编整理了计算机二级C语言程序填空题练习题&#xff0c;一起来测试一下吧&#xff1a;程序填空题下列给定程序中&#xff0c;函数fun的功能是&#xff1a;把形参a所…...

男做基视频网站/怎么建立网站?

1、判断结构是允许程序针对不同情况执行不同指令序列的控制结构。2、判断在Python中用if语句实现。简单的判断是用一个简单的if来实现的。两路判断通常使用if-else。多路判断用if-elif-else 实现。3、判断基于条件的求值&#xff0c;条件是简单的布尔表达式。布尔表达式结果为t…...

四川杰新建设工程网站/培训课程有哪些

平时我们在使用git的时候&#xff0c;很少去关注其配置是如何&#xff0c;而在实际开发中&#xff0c;对git config这个命令的使用也并不是很多&#xff0c;但是配置对一个程序和项目来说都是很重要的&#xff0c;我们今天来看看git的配置以及git config的初步应用。 1. git co…...

商丘做网站多少钱/网站建设知名公司

网址1 网址2 网址3 随便点击以上任一链接&#xff0c;输入应用在google play上的网址就可以获取下载链接。...