开源音乐分离器Audio Decomposition:可实现盲源音频分离,无需外部乐器分离库,从头开始制作。将音乐转换为五线谱的程序

今天给大家分析一个音频分解器,通过傅里叶变换和信封匹配分离音乐中的各个音符和乐器,实现音乐到乐谱的转换。将音乐开源分离为组成乐器。该方式是盲源分离,从头开始制作,无需外部乐器分离库。

相关链接

代码:https://github.com/mbird1258/Audio-Decomposition

演示视频:https://youtu.be/-i0PSxcoDH0

准备

仪器数据

乐器数据全部来自爱荷华大学电子音乐工作室乐器数据库。利用这些文件,我们用下文所述方法找到整个波的傅里叶变换和波的包络。

工作原理

乐器的声波主要由其傅里叶变换和包络线来表征。因此,我们可以利用这两者来很好地了解哪种乐器正在演奏哪个音符。

傅立叶变换

该程序将音乐分解为组成音符和乐器的第一种方法是每 0.1 秒对音乐文件进行一次傅里叶变换(频谱图),并将我们存储的每种乐器的傅里叶变换相加,以重新创建 0.1 秒窗口的傅里叶变换。这个想法是希望在设定的时间内完美地重现音乐,因为傅里叶变换应该能相对好地代表所演奏的音乐。

原始傅里叶变换

原始傅里叶变换

组成文书

组成文书

重新创建傅里叶变换

通过求解以下矩阵可得出每种乐器的幅度。该矩阵是通过对每种乐器的 MSE 成本函数按频率(例如 5 hz 时的 FT 值)求偏导数而得出的。矩阵中的每一行都是不同的偏导数。(第一个是相对于大提琴的,第二个是相对于钢琴的,等等)

信封

将乐器的包络与声波匹配的第一步是获取包络本身。包络是波的上限,虽然有函数可以做到这一点,但它们似乎难以处理噪音和某些类型的声波。因此,由于我们必须处理不同频率的许多不同乐器,我们需要一个更强大的解决方案。

为了获得包络,该函数将声波分成几块,然后取每块的最大值。为了进一步优化结果,该函数找到包络低于原始声波的点,并添加一个定义包络的新点。

下一步是将波的包络分解为起音、延音和释音。起音是音符的初始噪音,延音是音符保持时,释音是音符停止时。对于乐器样本,我们可以取波的第一个非零值来获取起音的开始。要获取起音和延音之间的点,我们获取函数向下凹或减小时的第一个点。要获取延音和释音之间的点,我们获取函数增加或向下凹的末端的第一个点。要获取释音的末端,我们找到函数非零的末端的第一个点。

为了进一步对波进行分类,我们需要考虑波可以采取的主要形式。一些乐器,例如钢琴,具有静态衰减,其中它们大多遵循指数衰减形状。另一方面,一些乐器,例如小提琴,可以随着音符的持续而增加或减少音量。除此之外,乐器文件中的一些音频样本会保留到声音结束,而其他音频样本则会提前释放。为了区分衰减是静态的还是动态的,如果衰减因子> 1,或者它偏离衰减曲线太多,则为动态的。为了区分包络是否有释放(AS或ASR),我们查看维持和释放的平均变化率,如果释放的变化率较低,则没有释放。

为了处理音乐文件,我们首先对每个音符频率的信号进行带通滤波。使用滤波后的波,我们迭代每个乐器。对于每种乐器,我们利用乐器的起音(标准化)和释放(标准化)的互相关来找到每个音符的开始和结束,然后利用乐器波和滤波后的音频的 MSE 来获得当时乐器的成本。之后,我们将在傅立叶变换步骤中找到的幅度乘以 1/(我们在此步骤中找到的成本)以获得最终的幅度。

展示 为了显示文件,我们使用 matplotlib 的散点图和 - 形点来显示乐谱。最初,我想根据幅度重新创建音频,但这导致了许多问题,花费了一段时间,并使故障排除变得更加困难。我也尝试使用 matplotlib 的 imshow 图,但在这种情况下效率极低,因为大多数值都是 0,并且每次我们平移或缩放屏幕时,matplotlib 都需要重新绘制每个点,无论它是否在屏幕上。

结果

总体效果很好。你可以用它来更好地重现乐谱,特别是当你很难找到正确的音高或和弦时,而且它运行起来也不会花费太多时间。

如何运行项目

  1. 从GitHub下载后分别运行 ScrapeInstruments.py 和 ProcessInstruments.py 一次 InstrumentAudioFiles 和 InstrumentData 现在应该被填充

  2. 将 soundfile.read() 可以处理的文件类型上传到 In 文件夹

  3. 进入 Main.py 并更改任何参数,主要是歌曲的乐器白名单或黑名单。

  4. 运行 Main.py PlayBack 现在应该为每个输入都有一个文件

  5. 运行Display.py查看结果!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 6年经验面试总结 2024.11.15

背景:深圳 面过12家中大厂、4家中小厂,通过4家中大厂,2家offer。 针对六年的求职面试总结:项目经验70%30%基础(基础应该必会) 对于上来就问八股文的公司,对于已经工作了5年以上的开发来说&…

智慧安防丨以科技之力,筑起防范人贩的铜墙铁壁

近日,贵州省贵阳市中级人民法院对余华英拐卖儿童案做出了一审宣判,判处其死刑,剥夺政治权利终身,并处没收个人全部财产。这一判决不仅彰显了法律的威严,也再次唤起了社会对拐卖儿童犯罪的深切关注。 余华英自1993年至2…

【原创】java+ssm+mysql房屋租赁管理系统设计与实现

个人主页:程序猿小小杨 个人简介:从事开发多年,Java、Php、Python、前端开发均有涉猎 博客内容:Java项目实战、项目演示、技术分享 文末有作者名片,希望和大家一起共同进步,你只管努力,剩下的交…

Linux高阶——1116—环形队列生产者消费者

目录 1、环形队列 2、生产者消费者 环形队列数组实现代码 成功截图 1、环形队列 相比于线性队列,环形队列可以有效避免访问越界问题,使用下标访问队列元素时,到达末尾后下标归0,返回起始位置,使用下标运算即可 a…

9.C++面向对象6(实现一个较为完善的日期类)

⭐本篇重点:const成员变量和函数,取地址重载 ⭐本篇代码:c学习/02.c面向对象-中/2.实现完善的日期类 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 日期类分析 二. 代码实现 2.1 构造函数 2.2 拷贝构造 2.3 …

构建SSH僵尸网络

import argparse import paramiko# 定义一个名为Client的类,用于表示SSH客户端相关操作 class Client:# 类的初始化方法,接收主机地址、用户名和密码作为参数def __init__(self, host, user, password):self.host hostself.user userself.password pa…

springboot 文件高效上传

文件上传功能可以说对于后端服务是必须的,不同场景对文件上传的要求也各不相同,有的追求速度,有的注重稳定性,还有的需要考虑文件大小和安全性。所以便有了秒传、断点续传和分片上传等解决方案。 1、总述 秒传 秒传&#xff0c…

MySQL 中的数据排序是怎么实现的

MySQL 内部数据排序机制 1. 排序算法 MySQL 使用不同的算法来对数据进行排序,通常依据数据量和是否有索引来决定使用哪种排序算法。主要的排序算法包括: 文件排序 (File Sort):这是 MySQL 默认的排序算法,用于无法利用索引或内…

199. 二叉树的右视图【 力扣(LeetCode) 】

文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 199. 二叉树的右视图 一、题目描述 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 二…

22.useNavigatorOnLine

React useNavigatorOnLine 钩子:如何实时监测用户的在线状态? 在现代 Web 应用中,实时监测用户的在线状态对于提供良好的用户体验至关重要。无论是离线功能还是网络状态提示,都需要准确地知道用户的连接状态。useNavigatorOnLine 钩子提供了一种简单而有效的方式来在 Reac…

Mongo数据库集群搭建

目录 1、Mongo集群优势 1.1 高可用性 1.2 水平扩展性 1.3 高性能 1.4 灵活的架构设计 1.5 数据安全 1.6 管理与监控 2、下载指定操作系统版本包 3、部署和验证工作 3.1 准备配置文件及依赖 3.2 启动第一个节点 3.3 部署更多的节点 3.4 初始化副本集 3.5 设置管理…

DB Type

P位 p 1时段描述符有效,p 0时段描述符无效 Base Base被分成了三个部分,按照实际拼接即可 G位 如果G 0 说明描述符中Limit的单位是字节,如果是G 1 ,那么limit的描述的单位是页也就是4kb S位 S 1 表示代码段或者数据段描…

大语言模型通用能力排行榜(2024年11月8日更新)

数据来源SuperCLUE 榜单数据为通用能力排行榜 排名 模型名称 机构 总分 理科 文科 Hard 使用方式 发布日期 - o1-preview OpenAI 75.85 86.07 76.6 64.89 API 2024年11月8日 - Claude 3.5 Sonnet(20241022) Anthropic 70.88 82.4…

【Unity基础】对比OnCollisionEnter与OnTriggerEnter

在Unity中,OnCollisionEnter 和 OnTriggerEnter 是两种用于处理碰撞的回调函数,但它们的工作方式和使用场景有所不同: 1. OnCollisionEnter 触发条件:当一个带有 Collider 组件并且**未勾选“Is Trigger”**的物体,与…

利用OpenAI进行测试需求分析——从电商网站需求到测试用例的生成

在软件测试工程师的日常工作中,需求分析是测试工作中的关键步骤。需求文档决定了测试覆盖的范围和测试策略,而测试用例的编写往往依赖于需求的准确理解。传统手工分析需求耗时长,尤其在面对大量需求和复杂逻辑时容易遗漏细节。本文将以电商网…

vue之axios根据某个接口创建实例,并设置headers和超时时间,捕捉异常

import axiosNew from axios;//给axios起个别名//创建常量实例 const instanceNew axiosNew.create({//axios中请求配置有baseURL选项,表示请求URL的公共部分,url baseUrl requestUrlbaseURL: baseURL,//设置超时时间为20秒timeout: 20000,headers: {…

【数学二】线性代数-二次型

考试要求 1、了解二次型的概念, 会用矩阵形式表示二次型,了解合同变换与合同矩阵的概念. 2、了解二次型的秩的概念,了解二次型的标准形、规范形等概念,了解惯性定理,会用正交变换和配方法化二次型为标准形。 3、理解正定二次型、正定矩阵的概念,并掌握其判别法. 二次型…

Qt 5.6.3 手动配置 mingw 环境

- 安装 qt 5.6.3 mingw 版 - 打开 qt creator - 找到选项 工具 - 选项- 构建和运行 - 找到 “编译器” 选项卡 ,点击 "添加" “编译器路径” 设置为 qt 安装目录下, tool 文件夹内的 g.exe 设置完成后,点击 "apply" ,使选项生…

pytorch tensor在CPU和GPU之间转换,numpy之间的转换

# input input.cpu().numpy() input input.cpu().detach().numpy() # 有gradCPU tensor转GPU tensor: cpu_imgs.cuda()GPU tensor 转CPU tensor: gpu_imgs.cpu()numpy转为CPU tensor: torch.from_numpy( imgs )4.CPU tensor转为numpy数…

k8s上部署redis高可用集群

介绍: Redis Cluster通过分片(sharding)来实现数据的分布式存储,每个master节点都负责一部分数据槽(slot)。 当一个master节点出现故障时,Redis Cluster能够自动将故障节点的数据槽转移到其他健…