【脑洞手填目标一】通过学习python实现简谱自动转音频的功能

2024-01-04 05:20

本文主要是介绍【脑洞手填目标一】通过学习python实现简谱自动转音频的功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、目标:数字转音频,保存并可以播放

需求场景:日常生活中发现自己唱歌调很不准,但如果有钢琴演奏每个音符从旁协助就能准确唱对了,由于很多歌并没有专门用琴演奏出演唱的调子,市面上也没有找到符合我需求的工具,刚巧在学习python,于是想通过学习python强大的mido类库来试试能不能实现自己的需求。

需求拆分

使用语言工具:python
需要实现功能点:word文档扫描,简谱解析,音频转化,生成MIDI文件保存,文件可以正常播放。

功能点实现

1、MIDI文件的生成;
简单生成Do音的DEMO实现代码如下:

import mido# 创建MIDI文件
midi_file = mido.MidiFile()
# 创建一个声部轨道
track = mido.MidiTrack()
# 添加轨道
midi_file.tracks.append(track)# 设置MIDI音色和速度
# program_change确定乐器的类型,0是钢琴
track.append(mido.Message('program_change', program=0))
#添加音符
track.append(mido.Message('note_on', note=60, velocity=64, time=0))
#添加该音符的结束标记
track.append(mido.Message('note_off', note=60, velocity=64, time=2000))# 保存MIDI文件
midi_file.save('output.mid')

此时发现midi文件频率编号有很多,一个乐谱对应大量音符节奏等元素,复用率很高,这就需要有个工具类去定义这些常用的音节,于是我百度了下具体音高和MIDI编号对应关系,如下图所示:
音高的对应midi编号
根据这个对应关系我单独写了个类方法,通过传参可以转换成对应编号:

def num(yin):                    if yin == "C2" or yin == "..1" :           #低两个八度 doreturn 36if yin == "D2" or yin == "..2":           #rereturn 38if yin == "E2" or yin == "..3":           #mireturn 40if yin == "F2" or yin == "..4":           #fareturn 41if yin == "G2" or yin == "..5":           #so 或者说 solreturn 43if yin == "A2" or yin == "..6":           #lareturn 45if yin == "B2" or yin == "..7":           #sireturn 47if yin == "C3" or yin == ".1":          #低八度   doreturn 48if yin == "D3" or yin == ".2":           #rereturn 50if yin == "E3" or yin == ".3":           #mireturn 52if yin == "F3" or yin == ".4":           #fareturn 53if yin == "G3" or yin == ".5":   #so 或者说 solreturn 55if yin == "A3" or yin == ".6":            #lareturn 57if yin == "B3" or yin == ".7":             #sireturn 59#中音区if yin == "C4" or yin == "1":       #中音doreturn 60if yin == "D4" or yin == "2":        #中音rereturn 62if yin == "E4" or yin == "3" or yin == 3:       #中音mireturn 64if yin == "F4" or yin == "4" or yin == 4:       #中音fareturn 65if yin == "G4" or yin == "5" or yin == 5:   #中音so  或者说 solreturn 67if yin == "A4" or yin == "6" or yin == 6:       #中音lareturn 69if yin == "B4" or yin == "7" or yin == 7:       #中音sireturn 71#高音区if yin == "C5" or yin == "1." :   #doreturn 72if yin == "D5" or yin == "2.":   #re return 74if yin == "E5" or yin == "3.":   #mireturn 76if yin == "F5" or yin == "4.":   #fareturn 77if yin == "G5" yin == "5."":       #so 或者说是 solreturn 79 if yin == "A5" or yin == "6.":   #lareturn 81if yin == "B5" or yin == "7." :   #sireturn 83

由于我的开发工具是anaconda中的jupyterLab,生成的不是py文件,是ipynb文件,在引入时会发生找不到库/文件的情况,需用通过shell命令转为py文件,加在后面运行时会生成py文件

try:!jupyter nbconvert --to python name_to_number.ipynb   
except:pass

接下来考虑文本内容读取,考虑最简单的实现方式就是txt文本读入规定格式的字符串后,对字符串分割,通过循环增加新的音符进去。
于是我手动新增一个文本文档,将简谱图片中的旋律以音符_拍数的方式录入保存后,通过open函数读入文本文档,open函数返回的不是文本内容,是文件对象,通过read() 方法可以获取字符串内容,接下来问题就简单了。代码如下:

# 指定节拍方便计算每拍持续多长时间
bpm = 120
# 获取文件数据
data = open('music.txt',encoding='utf-8')
# open函数返回的是当前打开文件对象的信息,包括编码,只读模式等
sheet_music = data.read().split(" ");
# 数据格式:音符_拍数
# 循环将简谱转化为MIDI消息
for note in sheet_music:timePerBeat = 60/bpm*1000note_number = name_to_number.num(note.split("_")[0])# F表示全拍,H半拍if note.split("_")[1] == 'H':timePerBeat = timePerBeat*0.5# 读取到最后返回None表示文件结束if note_number !=None:track.append(mido.Message('note_on', note=note_number, velocity=64, time=0))track.append(mido.Message('note_off', note=note_number, velocity=64, time=int(timePerBeat)))

这里有几个坑点:
1,mido.Message方法中的time参数要传入整数形式,传入形参需要强转类型,否则会报data type类型必须为int;
2,文件对象read后以None结尾表示文件结束,而我做的自定义类里没有设置None的情况所以转换的时候会因为未转换成int类型导致Message方法报出参数类型错误的问题。

现在可以转换MIDI了,但是不够智能,接下来需要通过识别提取图片中的关键信息,生成需要的文本文档,但是完全不会笑死,由于这个半成品都不如的代码实在太难用了,我想我是会努力优化的。

这篇关于【脑洞手填目标一】通过学习python实现简谱自动转音频的功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/568275

相关文章

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

一文详解如何从零构建Spring Boot Starter并实现整合

《一文详解如何从零构建SpringBootStarter并实现整合》SpringBoot是一个开源的Java基础框架,用于创建独立、生产级的基于Spring框架的应用程序,:本文主要介绍如何从... 目录一、Spring Boot Starter的核心价值二、Starter项目创建全流程2.1 项目初始化(