由于Merge错误,我得提交未完成的修改

This commit is contained in:
EillesWan 2022-10-05 22:21:13 +08:00
parent 3b53846ade
commit f8d707ac11
9 changed files with 416 additions and 228 deletions

131
README.md
View File

@ -33,130 +33,21 @@
诸葛亮与八卦阵 bgArray我的世界基岩版玩家喜欢编程和音乐深圳初一学生。
## 软件架构🏢
这是一个简单的Python包
## 使用教程📕
> 0. 安装python3.6+
>
> 在安装时一定要勾选Add Python 3.X to PATH不然就要手动设置
>
> 同时装完之后记得在cmd中输入python 试试是否安装成功,
> python的安装可以去网上随便找一下。
> 成功安装之后在cmd中输入python会显示
> <img src=https://foruda.gitee.com/images/1659972669907359295/cmd.png>
> 之类的东西。
> 1. 安装下载本程序git的话可以使用以下命令
>
> `git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
>
> 没有安装git的话可以下载zip包解压后进入目录即可。
> <img src=" https://foruda.gitee.com/images/1659972440341216712/下载.png" >
> 2. 运行(进入目录)
> 在目录下打开cmd进入到目录下执行以下命令
> <img src=https://foruda.gitee.com/images/1659974437388532868/输入.png>
> <img src=https://foruda.gitee.com/images/1659974754378201859/输入c.png>
> 回车一下,然后:
> <img src=https://foruda.gitee.com/images/1659974794561970425/pip.png>
> 输入下面的三个指令即可!
>
> `pip install mido`
>
> `pip install brotli`
>
> `pip install openpyxl`
>
> 3. 开始使用!
> 在目录下打开cmd步骤与上面的图片一致只是执行的代码换了进入到目录下执行以下命令(选择你需要的)
>
> `python example_convert_bdx.py`
>
> `python example_convert_mcpack.py`
>
> 4. 错误补充说明
> 如果你遇到了以下这种情况
> <img src=https://foruda.gitee.com/images/1659972789779764953/bug.jpeg>
> 那么,请按照这篇文章指引做:
> https://blog.csdn.net/qq_41179280/article/details/123804948
>
> 感谢Mono帮我们发现这个问题
>
> 5. 使用补充说明
> <img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
> midi路径含有mid文件路径、文件名、后缀的完整绝对路径
>
> 输出路径:输出文件夹的路径,就写一个英文.(句号)可以表示生成到当前目录下
> (意思就是支持相对路径)
>
> 是否重置计分板1或0歌曲放完是否重置推荐1
>
> 是否启用进度条1或0看个人需要
>
> 计分板名称:游戏内的计分板名称
>
> 音量0-1之间的小数含01正常来说推荐1
>
> 变速float数据一般写1
>
> 没有报错且在输出路径下找到mcpack或bdx即为生成成功
> <img src=https://foruda.gitee.com/images/1659973655881460036/输出.png>
### 对于 进度条自定义 功能的说明
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
一个进度条,明显地,有**固定部分**和**可变部分**来构成。而可变部分又包括了文字和图形两种(当然,《我的世界》里头的进度条,可变的图形也就是那个“条”了)。这一点你需要了解,因为后文中包含了很多这方面的概念需要你了解。
进度条的自定义功能使用一个字符串来定义自己的样式,其中包含众多**标识符**来表示可变部分。
标识符如下(注意大小写):
| 标识符 | 指定的可变量 |
|---------|----------------|
| `%%N` | 乐曲名(即传入的文件名)|
| `%%s` | 当前计分板值 |
| `%^s` | 计分板最大值 |
| `%%t` | 当前播放时间 |
| `%^t` | 曲目总时长 |
| `%%%` | 当前进度比率 |
| `_` | 用以表示进度条占位|
表示进度条占位的 `_` 是用来标识你的进度条的。也就是可变部分的唯一的图形部分。
**样式定义字符串**的样例如下,这也是默认的进度条的样式:
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
这是单独一行的进度条,当然你也可以制作多行的,如果是一行的,输出时所使用的指令便是 `title`,而如果是多行的话,输出就会用 `titleraw` 作为进度条字幕。
哦对了,上面的只不过是样式定义,同时还需要定义的是可变图形的部分,也就是进度条上那个真正的“条”。
对于这个我们就采用了固定参数的方法,对于一个进度条,无非就是“已经播放过的”和“没播放过的”两种形态,所以,使用一个元组来传入这两个参数就是最简单的了。元组的格式也很简单:`(str: 播放过的部分长啥样, str: 没播放过的部分长啥样)` 。例如,我们默认的进度“条”的定义是这样的:
`('§e=§r', '§7=§r')`
综合起来,把这些参数传给函数需要一个参数整合,你猜用的啥?啊对对对,我用的还是元组!
我们的默认定义参数如下:
`(r'▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*对了!为了避免生成错误,请尽量避免使用标识符作为定义样式字符串的其他部分*
## 致谢🙏
- 感谢 昀梦\<QQ1515399885\> 找出指令生成错误bug并指正
- 感谢由 Charlie_Ping “查理平” 带来的bdx文件转换参考
- 感谢 **昀梦**\<QQ1515399885\> 找出指令生成错误bug并指正
- 感谢由 **Charlie_Ping “查理平”** 带来的bdx文件转换参考
以及mid转我的世界乐器参考表格
- 感谢由 CMA_2401PT 为我们的软件开发进行指导
- 感谢由 Dislink Sforza \<QQ1600515314\>带来的midi音色解析以及转换指令的算法我们将其加入了我们众多算法之一
- 感谢 Touch \<QQ1793537164\>提供的测试支持
- 感谢 Mono\<QQ738893087\>反馈安装时的问题
- 感谢广大群友为此程序提供的测试等支持
- 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我!
- 感谢由 **CMA_2401PT** 为我们的软件开发进行指导
- 感谢由 **Dislink Sforza**\<QQ1600515314\>带来的midi音色解析以及转换指令的算法我们将其改编并应用
- 感谢 **Touch “偷吃”**\<QQ1793537164\>提供的测试支持,并对程序的改进提供了丰富的意见
- 感谢 **Mono**\<QQ738893087\>反馈安装时的问题
> 感谢广大群友为此程序提供的测试等支持
>
> 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我!
## 联系我们📞
@ -166,7 +57,7 @@
2. 电邮 EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. 微信 WYI_DoctorYI
### 作者\<*诸葛亮与八卦阵*\>(bgArray) 联系方式
### 作者\<*诸葛亮与八卦阵*\>(bgArray)联系方式
1. QQ 4740437765

View File

@ -34,103 +34,17 @@ Eilles (金羿)A high school student, individual developer, unfamous Bilibili
bgArray "诸葛亮与八卦阵": Fix bugs, improve code aesthetics, add new functions, change data format, etc.
### Framework🏢
A simple Python package.
## Instructions📕
> 0. Install Python 3.6+
>
> During installation, be sure to check "add Python 3.X to path", otherwise it needs to be set manually
>
> At the same time, after the installation, remember to enter in CMD: "python" to try
>
> whether the installation is successful.
>
> Python installation tutorial can be found on the Internet easily.
>
> 1. Install (download this program)
> Git, you can use the following commands:
>
> `git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
>
> If Git is not installed, you can download the zip package from the website. Then decompress it
> and enter the directory.
>
> 2. Run (enter directory)
>
> Open CMD in the directory, enter the directory, and execute the following commands:
>
> `pip install mido`
>
> `pip install brotli`
>
> `pip install openpyxl`
>
> 3. Start using!
>
> Open CMD in the directory, enter the directory, and execute the following commands:
>
> (Choose what you need)
>
> `python example_convert_bdx.py`
>
> `python example_convert_mcpack.py`
### Instructions for **Customize Progress Bar**
We have supported the function of making progress bar in *Minecraft*'s music player. And also the method of customize them. So the following instructions are about the parameters of the Progress Bar Customizition.
A Progress Bar, of course, is composed of **changeless** parts and **changable** parts. And the changable parts include texts or *images*(these images are made up of texts, or we can say, character paintings 😁). That is, for *Minecraft*, a changable image in a progress bar is just the "bar" part(which is like a stripe).
We use a string to describe the style of progress bar you need, and it includes many **identifier**s to replace the changable parts.
There are the identifiers:
| Identifier | Changable Part |
|--------------|------------------------------------------------------|
| `%%N` | Music name(file name which is imported into program) |
| `%%s` | Value of scoreboard of now |
| `%^s` | Max value of scoreboard |
| `%%t` | Current playback time |
| `%^t` | Total music time |
| `%%%` | Current playback progress |
| `_` | To be replaced by the *Bar* part of the progress bar |
The `_` is a placeholder to identifying the *bar* part, yeah, just the changable image.
This is an example of **style description string**, and this is also the default style of *Musicreater*'s progress bar.
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
This is a progress bar with only one line, but it is possible if you want to give a multiline parameter into the style description string.
But the string above is only for style identification, but we also need to identifying the changable image's image(just what the bar's look).
A "bar", simply, included 2 parts: *Have Been Played* & *Not Been Played*. So we use a tuple to pass the parameter. It's under a simple format: `(str: played, str: not)`. For example, the default parameter is below:
`('§e=§r', '§7=§r')`
So it's time to combine what I said in one parameter now!
This is a default definder parameter:
`('▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*Tip: To avoid errors, please not to use the identifiers as the other part of your style.*
## Thanks🙏
- Thank [Fuckcraft](https://github.com/fuckcraft) *(“鸣凤鸽子” ,etc)* for the function of Creating the Websocket Server for Minecraft: Bedrock Edition.
- *!! They have given me the rights to directly copy the lib into Musicreater*
- Thank *昀梦*\<QQ1515399885\> for finding and correcting the bugs in the commands that *Musicreater* Created.
- Thank *Charlie_Ping “查理平”* for bdx convert function, and
the data label that's used to convert the mid's instruments into minecraft's instruments.
- Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide.
- Thank *Miracle Plume “神羽”* \<QQshenyu40403\> for the Miracle Plume Bedrock Edition Audio Resource Pack
- 感谢由 Dislink Sforza \<QQ1600515314\>带来的midi转换算法我们将其加入了我们众多算法之一
- Thank *Arthur Morgan* for his/her biggest support for the debugging of Musicreater
- Thank *Dislink Sforza* \<QQ1600515314\> for the algorithm brought to us, his midi analysis algorithm became one of us's best ones
- Thank *Arthur Morgan*\<QQ312280061\> for his/her biggest support for the debugging of Musicreater
- Thank *Touch “偷吃”*\<QQ1793537164\> for support of debugging and testing program and algorithm, as well his/her suggestions to the improvement of our project
- Thank *Mono*\<QQ738893087\> for reporting problems while installing
- Thanks for a lot of groupmates who support me and help me to test the program.
- If you have give me some help but u haven't been in the list, please contact me.
@ -139,8 +53,10 @@ the data label that's used to convert the mid's instruments into minecraft's ins
### Author *Eilles*(金羿)
1. QQ 2647547478
2. E-mail EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
2. E-mail EillesWan2006@163.com
W-YI_DoctorYI@outlook.com EillesWan@outlook.com
3. WeChat WYI_DoctorYI
4. Telegram [@EillesWan](https://t.me/EillesWan)
### Author *bgArray*(诸葛亮与八卦阵)

View File

@ -86,7 +86,7 @@ while True:
if os.path.isdir(midipath):
for i in os.listdir(midipath):
if i.endswith('.mid'):
if i.lower().endswith('.mid'):
print(f'正在操作{i}')
convertion.convert(midipath + '/' + i, outpath + '/' + i[:-4] )
if outFormat == 0:

View File

@ -39,21 +39,25 @@ while True:
print('输入错误,请重新输入')
if os.path.isdir(midipath):
for i in os.listdir(midipath):
if i.endswith('.mid'):
print(f'正在操作{i}')
convertion.convert(midipath + '/' + i, outpath)
convertion.toBDXfile_withDelay(
1,
authorname if authorname != '' else input('请输入作者:'),
isProgress if isProgress != '' else bool(int(input('是否开启进度条(1|0)'))),
heightmax if heightmax != '' else int(input('请输入指令结构最大生成高度:')),
volume if volume != '' else float(input('请输入音量(0-1]')),
speed if speed != '' else float(input('请输入速度倍率:')),
player if player != '' else input('请输入玩家选择器:'),
)
def operation(i,):
print(f'正在操作{i}')
convertion.convert(midipath + '/' + i, outpath)
convertion.toBDXfile_withDelay(
1,
authorname if authorname != '' else input('请输入作者:'),
isProgress if isProgress != '' else bool(int(input('是否开启进度条(1|0)'))),
heightmax if heightmax != '' else int(input('请输入指令结构最大生成高度:')),
volume if volume != '' else float(input('请输入音量(0-1]')),
speed if speed != '' else float(input('请输入速度倍率:')),
player if player != '' else input('请输入玩家选择器:'),
)
if os.path.isdir(midipath):
import threading
for i in os.listdir(midipath):
if i.lower().endswith('.mid'):
threading.Thread(target=operation,args=(i,)).start()
else:
convertion.convert(midipath, outpath)
convertion.toBDXfile_withDelay(

88
docs/Use of Funtions.md Normal file
View File

@ -0,0 +1,88 @@
<h1 align="center">音·创 Musicreater</h1>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
## Instructions📕
> 0. Install Python 3.6+
>
> While installing, be sure to check "add Python 3.X to path", otherwise it needs to be set manually
>
> After the installation, remember to enter in CMD: "python" to try
>
> whether the installation is successful.
>
> Python installation tutorial can be found on the Internet easily.
>
> 1. Install (download this program)
> Git, you can use the following commands:
>
> `git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
>
> If Git is not installed, you can download the zip package from the website. Then decompress it
> and enter the directory.
>
> 2. Run (enter directory)
>
> Open CMD in the directory, enter the directory, and execute the following commands:
>
> `pip install mido`
>
> `pip install brotli`
>
> `pip install openpyxl`
>
> 3. Start using!
>
> Open CMD in the directory, enter the directory, and execute the following commands:
>
> (Choose what you need)
>
> `python example_convert_bdx.py`
>
> `python example_convert_mcpack.py`
### Instructions for **Customize Progress Bar**
We have supported the function of making progress bar in *Minecraft*'s music player. And also the method of customize them. So the following instructions are about the parameters of the Progress Bar Customizition.
A Progress Bar, of course, is composed of **changeless** parts and **changable** parts. And the changable parts include texts or *images*(these images are made up of texts, or we can say, character paintings 😁). That is, for *Minecraft*, a changable image in a progress bar is just the "bar" part(which is like a stripe).
We use a string to describe the style of progress bar you need, and it includes many **identifier**s to replace the changable parts.
There are the identifiers:
| Identifier | Changable Part |
|--------------|------------------------------------------------------|
| `%%N` | Music name(file name which is imported into program) |
| `%%s` | Value of scoreboard of now |
| `%^s` | Max value of scoreboard |
| `%%t` | Current playback time |
| `%^t` | Total music time |
| `%%%` | Current playback progress |
| `_` | To be replaced by the *Bar* part of the progress bar |
The `_` is a placeholder to identifying the *bar* part, yeah, just the changable image.
This is an example of **style description string**, and this is also the default style of *Musicreater*'s progress bar.
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
This is a progress bar with only one line, but it is possible if you want to give a multiline parameter into the style description string.
But the string above is only for style identification, but we also need to identifying the changable image's image(just what the bar's look).
A "bar", simply, included 2 parts: *Have Been Played* & *Not Been Played*. So we use a tuple to pass the parameter. It's under a simple format: `(str: played, str: not)`. For example, the default parameter is below:
`('§e=§r', '§7=§r')`
So it's time to combine what I said in one parameter now!
This is a default definder parameter:
`('▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*Tip: To avoid errors, please not to use the identifiers as the other part of your style.*

117
docs/使用教程.md Normal file
View File

@ -0,0 +1,117 @@
<h1 align="center">音·创 Musicreater</h1>
<p align="center">
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
</p>
## 使用教程📕
> 0. 安装python3.6+
>
> 在安装时一定要勾选Add Python 3.X to PATH不然就要手动设置
>
> 同时装完之后记得在cmd中输入python 试试是否安装成功,
> python的安装可以去网上随便找一下。
> 成功安装之后在cmd中输入python会显示
> <img src=https://foruda.gitee.com/images/1659972669907359295/cmd.png>
> 之类的东西。
> 1. 下载本程序
>
> git的话可以使用以下命令
>
> `git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
>
> 没有安装git的话可以下载zip包解压后进入目录即可。
> <img src=" https://foruda.gitee.com/images/1659972440341216712/下载.png" >
> 2. 运行(进入目录)
> 在目录下打开cmd进入到目录下执行以下命令
> <img src=https://foruda.gitee.com/images/1659974437388532868/输入.png>
> <img src=https://foruda.gitee.com/images/1659974754378201859/输入c.png>
> 回车一下,然后:
> <img src=https://foruda.gitee.com/images/1659974794561970425/pip.png>
> 输入下面的三个指令即可!
>
> `pip install mido`
>
> `pip install brotli`
>
> `pip install openpyxl`
>
> 3. 开始使用!
> 在目录下打开cmd步骤与上面的图片一致只是执行的代码换了进入到目录下执行以下命令(选择你需要的)
>
> `python example_convert_bdx.py`
>
> `python example_convert_mcpack.py`
>
> 4. 错误补充说明
> 如果你遇到了以下这种情况
> <img src=https://foruda.gitee.com/images/1659972789779764953/bug.jpeg>
> 那么,请按照这篇文章指引做:
> https://blog.csdn.net/qq_41179280/article/details/123804948
>
> 感谢Mono帮我们发现这个问题
>
> 5. 使用补充说明
> <img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
> midi路径含有mid文件路径、文件名、后缀的完整绝对路径
>
> 输出路径:输出文件夹的路径,就写一个英文.(句号)可以表示生成到当前目录下
> (意思就是支持相对路径)
>
> 是否重置计分板1或0歌曲放完是否重置推荐1
>
> 是否启用进度条1或0看个人需要
>
> 计分板名称:游戏内的计分板名称
>
> 音量0-1之间的小数含01正常来说推荐1
>
> 变速float数据一般写1
>
> 没有报错且在输出路径下找到mcpack或bdx即为生成成功
> <img src=https://foruda.gitee.com/images/1659973655881460036/输出.png>
### 对于 进度条自定义 功能的说明
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
一个进度条,明显地,有**固定部分**和**可变部分**来构成。而可变部分又包括了文字和图形两种(当然,《我的世界》里头的进度条,可变的图形也就是那个“条”了)。这一点你需要了解,因为后文中包含了很多这方面的概念需要你了解。
进度条的自定义功能使用一个字符串来定义自己的样式,其中包含众多**标识符**来表示可变部分。
标识符如下(注意大小写):
| 标识符 | 指定的可变量 |
|---------|----------------|
| `%%N` | 乐曲名(即传入的文件名)|
| `%%s` | 当前计分板值 |
| `%^s` | 计分板最大值 |
| `%%t` | 当前播放时间 |
| `%^t` | 曲目总时长 |
| `%%%` | 当前进度比率 |
| `_` | 用以表示进度条占位|
表示进度条占位的 `_` 是用来标识你的进度条的。也就是可变部分的唯一的图形部分。
**样式定义字符串**的样例如下,这也是默认的进度条的样式:
`▶ %%N [ %%s/%^s %%% __________ %%t|%^t]`
这是单独一行的进度条,当然你也可以制作多行的,如果是一行的,输出时所使用的指令便是 `title`,而如果是多行的话,输出就会用 `titleraw` 作为进度条字幕。
哦对了,上面的只不过是样式定义,同时还需要定义的是可变图形的部分,也就是进度条上那个真正的“条”。
对于这个我们就采用了固定参数的方法,对于一个进度条,无非就是“已经播放过的”和“没播放过的”两种形态,所以,使用一个元组来传入这两个参数就是最简单的了。元组的格式也很简单:`(str: 播放过的部分长啥样, str: 没播放过的部分长啥样)` 。例如,我们默认的进度“条”的定义是这样的:
`('§e=§r', '§7=§r')`
综合起来,把这些参数传给函数需要一个参数整合,你猜用的啥?啊对对对,我用的还是元组!
我们的默认定义参数如下:
`(r'▶ %%N [ %%s/%^s %%% __________ %%t|%^t]',('§e=§r', '§7=§r'))`
*对了!为了避免生成错误,请尽量避免使用标识符作为定义样式字符串的其他部分*

View File

@ -38,5 +38,5 @@ Note! Except for this source file, all the files in this repository and this pro
from .main import *
print('转换功能由音·创开发者开发,版权归参与开发的人员共同所有。')
print('Midi转换功能由音·创开发者开发,版权归参与开发的人员共同所有。')
print('Copyright © 2022 all the developers of Musicreater')

View File

@ -463,7 +463,7 @@ class midiConvert:
self, scoreboardname: str = "mscplay", volume: float = 1.0, speed: float = 1.0
) -> list:
"""
使用金羿的转换思路将midi转换为我的世界命令列表
使用金羿的转换思路将midi转换为我的世界命令列表使用线性方法调整音量
:param scoreboardname: 我的世界的计分板名称
:param volume: 音量注意这里的音量范围为(0,1]如果超出将被处理为正确值其原理为在距离玩家 (1 / volume -1) 的地方播放音频
:param speed: 速度注意这里的速度指的是播放倍率其原理为在播放音频的时候每个音符的播放时间除以 speed
@ -483,6 +483,7 @@ class midiConvert:
ticks = 0
instrumentID = 0
singleTrack = []
noteOn = []
for msg in track:
ticks += msg.time
@ -494,6 +495,33 @@ class midiConvert:
if msg.type == "program_change":
# print("TT")
instrumentID = msg.program
if msg.type == 'note_on' and msg.velocity != 0:
noteOn.append([msg, msg.note, ticks])
elif type_[1] is True:
if msg.type == 'note_on' and msg.velocity == 0:
for u in noteOn:
index = 0
if u[1] == msg.note:
lastMessage = u[0]
lastTick = u[2]
break
index += 1
trackS.append(
NoteMessage(
msg.channel,
msg.note,
lastMessage.velocity,
lastTick,
ticks - lastTick,
mid,
)
)
# print(noteOn)
# print(index)
try:
noteOn.pop(index)
except IndexError:
noteOn.pop(index - 1)
if msg.type == "note_on" and msg.velocity != 0:
nowscore = round(
(ticks * tempo)

144
noteTmain.py Normal file
View File

@ -0,0 +1,144 @@
import mido
def delete_extra_zero(n: float) -> int or float:
"""
删除多余的0
版权声明本文为CSDN博主XerCis的原创文章遵循CC 4.0 BY-SA版权协议转载请附上原文出处链接及本声明
原文链接https://blog.csdn.net/lly1122334/article/details/108770141
删除小数点后多余的0
:param n: input
:return: output
"""
n = '{:g}'.format(n)
n = float(n) if '.' in n else int(n) # 含小数点转float否则int
return n
def bpm_by_MetaMessage_Set_tempo(tmp: int) -> int or float:
"""
midi文件tempo事件bpm算法
A function that's used to compute the bpm of a midiFile,
which algorithm is made up of midiFile's tempo meta message.
:param tmp:输入mid的metaMessage中速度tempo值
input the tempo value which is in the tempo meta message.
:return:bpm
This algorithm is made by ©bgArray.
算法版权归©诸葛亮与八卦阵所有
"""
second = tmp / 1000000
bpm = delete_extra_zero(60 / second)
# debug.dp(bpm)
return bpm
class NoteMessage:
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
self.channel = channel
self.note = pitch
self.velocity = velocity
self.startTime = startT
self.lastTime = lastT
self.tempo = now_bpm # 这里要程序实现获取bpm可以参考我的程序
def mt2gt(mt, tpb_a, bpm_a):
return mt / tpb_a / bpm_a * 60
self.startTrueTime = mt2gt(self.startTime, midi.ticks_per_beat, self.tempo) # / 20
# delete_extra_zero(round_up())
if change_bpm is not None:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, change_bpm) # / 20
else:
self.lastTrueTime = mt2gt(self.lastTime, midi.ticks_per_beat, self.tempo) # / 20
# delete_extra_zero(round_up())
print((self.startTime * self.tempo) / (midi.ticks_per_beat * 50000))
def __str__(self):
return "noteMessage channel=" + str(self.channel) + " note=" + str(self.note) + " velocity=" + \
str(self.velocity) + " startTime=" + str(self.startTime) + " lastTime=" + str(self.lastTime) + \
" startTrueTime=" + str(self.startTrueTime) + " lastTrueTime=" + str(self.lastTrueTime)
def load(mid: mido.MidiFile):
type_ = [False, False, False] # note_off / note_on+0 / mixed
is_tempo = False
# 预检
for i, track in enumerate(mid.tracks):
for msg in track:
# print(msg)
if msg.is_meta is not True:
if msg.type == 'note_on' and msg.velocity == 0:
type_[1] = True
elif msg.type == "note_off":
type_[0] = True
if msg.is_meta is True and msg.type == "set_tempo":
is_tempo = True
if is_tempo is not True:
raise Exception("这个mid没有可供计算时间的tempo事件")
if type_[0] is True and type_[1] is True:
type_[2] = True
type_[1] = False
type_[0] = False
print(type_)
bpm = 0
recent_change_bpm = 0
is_change_bpm = False
# 实检
for i, track in enumerate(mid.tracks):
noteOn = []
trackS = []
ticks = 0
for msg in track:
print(msg)
ticks += msg.time
print(ticks)
if msg.is_meta is True and msg.type == "set_tempo":
recent_change_bpm = bpm
bpm = bpm_by_MetaMessage_Set_tempo(msg.tempo)
is_change_bpm = True
# print((ticks * 92) / (mid.ticks_per_beat * 50000))
# MC_tick = delete_extra_zero(round_up(
# (ticks * 92) / (mid.ticks_per_beat * 50000)
# ))
# print(MC_tick)
# print(ticks / mid.ticks_per_beat / 92 * 60)
if msg.type == 'note_on' and msg.velocity != 0:
noteOn.append([msg, msg.note, ticks])
if type_[1] is True:
if msg.type == 'note_on' and msg.velocity == 0:
for u in noteOn:
index = 0
if u[1] == msg.note:
lastMessage = u[0]
lastTick = u[2]
break
index += 1
print(lastTick)
if is_change_bpm and recent_change_bpm != 0:
trackS.append(NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, recent_change_bpm, bpm))
is_change_bpm = False
else:
trackS.append(
NoteMessage(msg.channel, msg.note, lastMessage.velocity, lastTick, ticks - lastTick,
mid, bpm))
# print(noteOn)
# print(index)
try:
noteOn.pop(index)
except IndexError:
noteOn.pop(index - 1)
print(trackS)
for j in trackS:
print(j)
if __name__ == '__main__':
load(mido.MidiFile("test.mid"))