mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2024-11-11 01:27:35 +08:00
快好了,不急不急
This commit is contained in:
parent
3921190832
commit
813186bef9
@ -103,6 +103,9 @@ while True:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if os.path.isdir(midipath):
|
if os.path.isdir(midipath):
|
||||||
for i in os.listdir(midipath):
|
for i in os.listdir(midipath):
|
||||||
if i.lower().endswith('.mid'):
|
if i.lower().endswith('.mid'):
|
||||||
|
139
docs/功能使用说明.md
139
docs/功能使用说明.md
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
0. 安装 Python3.6+
|
0. 安装 Python3.6+
|
||||||
|
|
||||||
首先需要下载Python的安装包
|
首先需要下载Python的安装包,最好是 *Python3.8*,因为作者就用的是这个版本
|
||||||
|
|
||||||
> [下载64位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
|
> [下载64位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe)
|
||||||
> [下载32位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
|
> [下载32位Python安装包](https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe)
|
||||||
@ -46,27 +46,31 @@
|
|||||||
|
|
||||||
打开了终端之后,请在终端中输入以下指令
|
打开了终端之后,请在终端中输入以下指令
|
||||||
|
|
||||||
`pip install mido -i https://mirrors.aliyun.com/pypi/simple/`
|
```bash
|
||||||
|
pip install mido -i https://mirrors.aliyun.com/pypi/simple/
|
||||||
`pip install brotli -i https://mirrors.aliyun.com/pypi/simple/`
|
pip install brotli -i https://mirrors.aliyun.com/pypi/simple/
|
||||||
|
```
|
||||||
|
|
||||||
安装成功后您可能会见到类似下图的提示:
|
安装成功后您可能会见到类似下图的提示:
|
||||||
|
|
||||||
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
|
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
|
||||||
|
|
||||||
|
### 本工具的下载与使用
|
||||||
|
|
||||||
2. 下载本代码库以及演示程序
|
0. 下载本代码库以及演示程序
|
||||||
|
|
||||||
- 若您使用git,请直接克隆本仓库:
|
- 若您使用git,请直接克隆本仓库:
|
||||||
|
|
||||||
`git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git`
|
```bash
|
||||||
|
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git
|
||||||
|
```
|
||||||
|
|
||||||
- 若您不使用git,可以在[*码云*(Gitee)](https://gitee.com/EillesWan/Musicreater.git)或[*GitHub*](https://github.com/EillesWan/Musicreater.git)下载zip包,或者[加入QQ群聊861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr),在群文件中获取。
|
- 若您不使用git,可以在[*码云*(Gitee)](https://gitee.com/EillesWan/Musicreater.git)或[*GitHub*](https://github.com/EillesWan/Musicreater.git)下载zip包,或者[加入QQ群聊861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr),在群文件中获取。
|
||||||
|
|
||||||
<img src=" https://foruda.gitee.com/images/1659972440341216712/下载.png" >
|
<img src=" https://foruda.gitee.com/images/1659972440341216712/下载.png" >
|
||||||
|
|
||||||
|
|
||||||
3. 开始使用
|
1. 开始使用
|
||||||
|
|
||||||
在目录下打开终端,例如,打开命令行,请进入到目录下,在地址框内输入`cmd`:
|
在目录下打开终端,例如,打开命令行,请进入到目录下,在地址框内输入`cmd`:
|
||||||
|
|
||||||
@ -75,10 +79,10 @@
|
|||||||
|
|
||||||
执行以下命令:(选择你需要的)
|
执行以下命令:(选择你需要的)
|
||||||
|
|
||||||
`python demo_convert.py`
|
```bash
|
||||||
|
python demo_convert.py
|
||||||
`python demo_convert_bdx_byDelay.py`
|
python demo_convert_bdx_byDelay.py
|
||||||
|
```
|
||||||
|
|
||||||
### 补充错误说明
|
### 补充错误说明
|
||||||
|
|
||||||
@ -94,7 +98,116 @@
|
|||||||
|
|
||||||
感谢群友Mono帮我们发现这个问题
|
感谢群友Mono帮我们发现这个问题
|
||||||
|
|
||||||
2. 参数补充说明
|
## Linux操作系统
|
||||||
|
|
||||||
|
|
||||||
|
### 运行环境安装
|
||||||
|
|
||||||
|
0. 安装并检验Python运行环境
|
||||||
|
|
||||||
|
一般的Linux发行版都有安装Python环境,我们只需要保证其版本即可,理论上 ≥Python3.6 都可以运行我们的库
|
||||||
|
|
||||||
|
我们可以使用
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -V
|
||||||
|
```
|
||||||
|
|
||||||
|
来查看 Python 版本,如下
|
||||||
|
|
||||||
|
<img src=https://foruda.gitee.com/images/1665120915821957090/429561fd_9911226.png>
|
||||||
|
|
||||||
|
- 非必要环节
|
||||||
|
|
||||||
|
如果你跟作者一样,觉得 Python 3.10+ 太难用很烦人的话,那真是皆大欢喜,让我们一起来回退版本吧!
|
||||||
|
|
||||||
|
- pacman 包管理器(多用于Arch Linux上)
|
||||||
|
|
||||||
|
让我们先来把 python3 加入忽略升级的列表中,使用`vim`修改`/etc/pacman.conf`,在`IgnorePkg`后加上`python3`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo vim /etc/pacman.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src=https://foruda.gitee.com/images/1665124611490335193/5e99ca26_9911226.png>
|
||||||
|
|
||||||
|
然后我们开始从[Arch Achieve](https://archive.archlinux.org/packages/)上找Python的版本列表。(*这里说明一下,在Arch中,Python默认指的是Python3,而与其他某些Linux发行版中Python默认指代Python2不同,所以在Arch Achieve中也是如此。*)我这里找到的是[Python3.8.6](https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst),于是我们用`pacman`把她下载下来:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo pacman -U https://archive.archlinux.org/packages/p/python/python-3.8.6-1-x86_64.pkg.tar.zst
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src=https://foruda.gitee.com/images/1665126362769399903/ea4b9598_9911226.png>
|
||||||
|
|
||||||
|
完美!
|
||||||
|
|
||||||
|
接着,我们来确认,Python自带的包管理器pip是否安装到位:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pip # 确认pip是否安装
|
||||||
|
# 当这个命令输入后有长段提示出现则为已经安装
|
||||||
|
|
||||||
|
# 如果返回如下,那么则pip尚未安装
|
||||||
|
/usr/bin/python: No module named pip
|
||||||
|
# 可以使用如下命令来安装pip
|
||||||
|
sudo pacman -S python-pip
|
||||||
|
# 安装完成后记得验证
|
||||||
|
python -m pip
|
||||||
|
|
||||||
|
|
||||||
|
# 如果还是失败,那么就需要用其他工具安装pip:
|
||||||
|
wget https://bootstrap.pypa.io/get-pip.py
|
||||||
|
sudo python get-pip.py
|
||||||
|
# 安装完成后一定要验证!!!
|
||||||
|
python -m pip
|
||||||
|
```
|
||||||
|
|
||||||
|
确认完成之后,我们来安装一下依赖库:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install mido -i https://mirrors.aliyun.com/pypi/simple/
|
||||||
|
pip install brotli -i https://mirrors.aliyun.com/pypi/simple/
|
||||||
|
```
|
||||||
|
|
||||||
|
安装成功后您可能会见到类似下图的提示:
|
||||||
|
|
||||||
|
<img src="https://foruda.gitee.com/images/1662737676719454287/f61a70f7_9911226.png">
|
||||||
|
|
||||||
|
|
||||||
|
### 本代码库的下载与使用
|
||||||
|
|
||||||
|
1. 使用Git下载本库及其示例代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone -b pkgver https://gitee.com/EillesWan/Musicreater.git MSCTpkgver
|
||||||
|
```
|
||||||
|
|
||||||
|
当上述命令执行成功,你会在执行此命令的所在位置发现一个名为 `MSCTpkgver` 的文件夹,其中包含的正是我们心心念念下载的本程序和示例代码。
|
||||||
|
而我们要运行的也正是示例代码,因此,赶快进入下载到的文件夹:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd MSCTpkgver
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 开始使用
|
||||||
|
|
||||||
|
在目录下打开终端,执行以下命令:(选择你需要的)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python demo_convert.py
|
||||||
|
python demo_convert_bdx_byDelay.py
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 其他说明
|
||||||
|
|
||||||
|
## 参数补充说明
|
||||||
|
|
||||||
<img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
|
<img src=https://foruda.gitee.com/images/1659974810147043475/运行.png>
|
||||||
|
|
||||||
@ -120,7 +233,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 对于 进度条自定义 功能的说明
|
## 对于 进度条自定义 功能的说明
|
||||||
|
|
||||||
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
|
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
|
||||||
|
|
||||||
|
69
msctPkgver/exceptions.py
Normal file
69
msctPkgver/exceptions.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
# 音·创 开发交流群 861684859
|
||||||
|
# Email EillesWan2006@163.com W-YI_DoctorYI@outlook.com EillesWan@outlook.com
|
||||||
|
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||||
|
# 若需使用或借鉴 请依照 Apache 2.0 许可证进行许可
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
音·创 库版 (Musicreater Package Version)
|
||||||
|
是一款免费开源的针对《我的世界:基岩版》的midi音乐转换库
|
||||||
|
注意!除了此源文件以外,任何属于此仓库以及此项目的文件均依照Apache许可证进行许可
|
||||||
|
Musicreater pkgver (Package Version 音·创 库版)
|
||||||
|
A free open source library used for convert midi file into formats that is suitable for **Minecraft: Bedrock Edition**.
|
||||||
|
Note! Except for this source file, all the files in this repository and this project are licensed under Apache License 2.0
|
||||||
|
|
||||||
|
Copyright 2022 all the developers of Musicreater
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the 'License');
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an 'AS IS' BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MSCTBaseException(Exception):
|
||||||
|
"""音·创库版本的所有错误均继承于此"""
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
def 喵(self,):
|
||||||
|
for i in self.args:
|
||||||
|
print(i+"喵!")
|
||||||
|
|
||||||
|
def crash_it(self):
|
||||||
|
raise self
|
||||||
|
|
||||||
|
|
||||||
|
class CrossNoteError(MSCTBaseException):
|
||||||
|
'''同通道下同音符交叉出现所产生的错误'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NotDefineTempoError(MSCTBaseException):
|
||||||
|
'''没有Tempo设定导致时间无法计算的错误'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MidiDestroyedError(MSCTBaseException):
|
||||||
|
'''Midi文件损坏'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ChannelOverFlowError(MSCTBaseException):
|
||||||
|
'''一个midi中含有过多的通道(应≤16)'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -99,41 +99,12 @@ def _toCmdList_m1(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import mido
|
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:
|
class NoteMessage:
|
||||||
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
|
def __init__(self, channel, pitch, velocity, startT, lastT, midi, now_bpm, change_bpm=None):
|
||||||
@ -202,14 +173,9 @@ def load(mid: mido.MidiFile):
|
|||||||
print(ticks)
|
print(ticks)
|
||||||
if msg.is_meta is True and msg.type == "set_tempo":
|
if msg.is_meta is True and msg.type == "set_tempo":
|
||||||
recent_change_bpm = bpm
|
recent_change_bpm = bpm
|
||||||
bpm = bpm_by_MetaMessage_Set_tempo(msg.tempo)
|
bpm = 60000000 / msg.tempo
|
||||||
is_change_bpm = True
|
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:
|
if msg.type == 'note_on' and msg.velocity != 0:
|
||||||
noteOn.append([msg, msg.note, ticks])
|
noteOn.append([msg, msg.note, ticks])
|
||||||
if type_[1] is True:
|
if type_[1] is True:
|
||||||
|
@ -38,6 +38,8 @@ import uuid
|
|||||||
import shutil
|
import shutil
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
from .exceptions import *
|
||||||
|
|
||||||
|
|
||||||
def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
|
def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||||
"""使用compression指定的算法打包目录为zip文件\n
|
"""使用compression指定的算法打包目录为zip文件\n
|
||||||
@ -62,9 +64,9 @@ def makeZip(sourceDir, outFilename, compression=8, exceptFile=None):
|
|||||||
|
|
||||||
|
|
||||||
class midiConvert:
|
class midiConvert:
|
||||||
def __init__(self):
|
def __init__(self, debug: bool = False):
|
||||||
"""简单的midi转换类,将midi文件转换为我的世界结构或者包"""
|
"""简单的midi转换类,将midi文件转换为我的世界结构或者包"""
|
||||||
pass
|
self.debugMode = debug
|
||||||
|
|
||||||
def convert(self, midiFile: str, outputPath: str):
|
def convert(self, midiFile: str, outputPath: str):
|
||||||
"""转换前需要先运行此函数来获取基本信息"""
|
"""转换前需要先运行此函数来获取基本信息"""
|
||||||
@ -228,8 +230,7 @@ class midiConvert:
|
|||||||
return a
|
return a
|
||||||
|
|
||||||
def __score2time(self, score: int):
|
def __score2time(self, score: int):
|
||||||
return str(int(int(score / 20) / 60)) + ":" + \
|
return str(int(int(score / 20) / 60)) + ":" + str(int(int(score / 20) % 60))
|
||||||
str(int(int(score / 20) % 60))
|
|
||||||
|
|
||||||
def __formProgressBar(
|
def __formProgressBar(
|
||||||
self,
|
self,
|
||||||
@ -257,11 +258,8 @@ class midiConvert:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __replace(
|
def __replace(
|
||||||
s: str,
|
s: str, tobeReplaced: str, replaceWith: str, times: int, other: str
|
||||||
tobeReplaced: str,
|
):
|
||||||
replaceWith: str,
|
|
||||||
times: int,
|
|
||||||
other: str):
|
|
||||||
if times == 0:
|
if times == 0:
|
||||||
return s.replace(tobeReplaced, other)
|
return s.replace(tobeReplaced, other)
|
||||||
if times == s.count(tobeReplaced):
|
if times == s.count(tobeReplaced):
|
||||||
@ -322,19 +320,15 @@ class midiConvert:
|
|||||||
countof_s = int((i + 1) / maxscore * pgblength)
|
countof_s = int((i + 1) / maxscore * pgblength)
|
||||||
|
|
||||||
finalprgsbar.append(
|
finalprgsbar.append(
|
||||||
"title @a[scores={" +
|
"title @a[scores={"
|
||||||
scoreboardname +
|
+ scoreboardname
|
||||||
"=" +
|
+ "="
|
||||||
str(
|
+ str(i + 1)
|
||||||
i +
|
+ "}] actionbar "
|
||||||
1) +
|
+ __replace(
|
||||||
"}] actionbar " +
|
nowstr, "_", progressbar[1][0], countof_s, progressbar[1][1]
|
||||||
__replace(
|
)
|
||||||
nowstr,
|
)
|
||||||
"_",
|
|
||||||
progressbar[1][0],
|
|
||||||
countof_s,
|
|
||||||
progressbar[1][1]))
|
|
||||||
|
|
||||||
return finalprgsbar
|
return finalprgsbar
|
||||||
|
|
||||||
@ -394,8 +388,7 @@ class midiConvert:
|
|||||||
|
|
||||||
:return:str
|
:return:str
|
||||||
"""
|
"""
|
||||||
block = b"\x24" + \
|
block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)
|
||||||
particularValue.to_bytes(2, byteorder="big", signed=False)
|
|
||||||
|
|
||||||
for i in [
|
for i in [
|
||||||
impluse.to_bytes(4, byteorder="big", signed=False),
|
impluse.to_bytes(4, byteorder="big", signed=False),
|
||||||
@ -412,10 +405,8 @@ class midiConvert:
|
|||||||
return block
|
return block
|
||||||
|
|
||||||
def _toCmdList_m1(
|
def _toCmdList_m1(
|
||||||
self,
|
self, scoreboardname: str = "mscplay", volume: float = 1.0, speed: float = 1.0
|
||||||
scoreboardname: str = "mscplay",
|
) -> list:
|
||||||
volume: float = 1.0,
|
|
||||||
speed: float = 1.0) -> list:
|
|
||||||
"""
|
"""
|
||||||
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表
|
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表
|
||||||
:param scoreboardname: 我的世界的计分板名称
|
:param scoreboardname: 我的世界的计分板名称
|
||||||
@ -449,31 +440,33 @@ class midiConvert:
|
|||||||
# print("TT")
|
# print("TT")
|
||||||
instrumentID = msg.program
|
instrumentID = msg.program
|
||||||
if msg.type == "note_on" and msg.velocity != 0:
|
if msg.type == "note_on" and msg.velocity != 0:
|
||||||
|
try:
|
||||||
nowscore = round(
|
nowscore = round(
|
||||||
(ticks * tempo)
|
(ticks * tempo)
|
||||||
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
|
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
|
||||||
)
|
)
|
||||||
|
except NameError:
|
||||||
|
raise NotDefineTempoError('计算当前分数时出错 未定义参量')
|
||||||
maxscore = max(maxscore, nowscore)
|
maxscore = max(maxscore, nowscore)
|
||||||
soundID, _X = self.__Inst2soundIDwithX(instrumentID)
|
soundID, _X = self.__Inst2soundIDwithX(instrumentID)
|
||||||
singleTrack.append(
|
singleTrack.append(
|
||||||
"execute @a[scores={" +
|
"execute @a[scores={"
|
||||||
str(scoreboardname) +
|
+ str(scoreboardname)
|
||||||
"=" +
|
+ "="
|
||||||
str(nowscore) +
|
+ str(nowscore)
|
||||||
"}" +
|
+ "}"
|
||||||
f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}")
|
+ f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}"
|
||||||
|
)
|
||||||
commands += 1
|
commands += 1
|
||||||
if len(singleTrack) != 0:
|
if len(singleTrack) != 0:
|
||||||
tracks.append(singleTrack)
|
tracks.append(singleTrack)
|
||||||
|
|
||||||
return [tracks, commands, maxscore]
|
return [tracks, commands, maxscore]
|
||||||
|
|
||||||
# 值得注意的是,我这里没有修改
|
# 值得注意的是,我这里没有修改多少
|
||||||
def _toCmdList_m2(
|
def _toCmdList_m2(
|
||||||
self,
|
self, scoreboardname: str = "mscplay", MaxVolume: float = 1.0, speed: float = 1.0
|
||||||
scoreboardname: str = "mscplay",
|
) -> list:
|
||||||
volume: float = 1.0,
|
|
||||||
speed: float = 1.0) -> list:
|
|
||||||
"""
|
"""
|
||||||
使用金羿的转换思路,将midi转换为我的世界命令列表,使用线性方法调整音量
|
使用金羿的转换思路,将midi转换为我的世界命令列表,使用线性方法调整音量
|
||||||
:param scoreboardname: 我的世界的计分板名称
|
:param scoreboardname: 我的世界的计分板名称
|
||||||
@ -482,14 +475,18 @@ class midiConvert:
|
|||||||
:return: tuple(命令列表, 命令个数, 计分板最大值)
|
:return: tuple(命令列表, 命令个数, 计分板最大值)
|
||||||
"""
|
"""
|
||||||
tracks = []
|
tracks = []
|
||||||
if volume > 1:
|
if MaxVolume > 1:
|
||||||
volume = 1
|
MaxVolume = 1
|
||||||
if volume <= 0:
|
if MaxVolume <= 0:
|
||||||
volume = 0.001
|
MaxVolume = 0.001
|
||||||
|
|
||||||
commands = 0
|
commands = 0
|
||||||
maxscore = 0
|
maxscore = 0
|
||||||
|
|
||||||
|
# 一个midi中仅有16通道 我们通过通道来识别而不是音轨
|
||||||
|
channels = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
|
||||||
|
|
||||||
|
|
||||||
for i, track in enumerate(self.midi.tracks):
|
for i, track in enumerate(self.midi.tracks):
|
||||||
|
|
||||||
ticks = 0
|
ticks = 0
|
||||||
@ -508,33 +505,7 @@ class midiConvert:
|
|||||||
# print("TT")
|
# print("TT")
|
||||||
instrumentID = msg.program
|
instrumentID = msg.program
|
||||||
if msg.type == 'note_on' and msg.velocity != 0:
|
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(
|
nowscore = round(
|
||||||
(ticks * tempo)
|
(ticks * tempo)
|
||||||
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
|
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
|
||||||
@ -542,12 +513,13 @@ class midiConvert:
|
|||||||
maxscore = max(maxscore, nowscore)
|
maxscore = max(maxscore, nowscore)
|
||||||
soundID, _X = self.__Inst2soundIDwithX(instrumentID)
|
soundID, _X = self.__Inst2soundIDwithX(instrumentID)
|
||||||
singleTrack.append(
|
singleTrack.append(
|
||||||
"execute @a[scores={" +
|
"execute @a[scores={"
|
||||||
str(scoreboardname) +
|
+ str(scoreboardname)
|
||||||
"=" +
|
+ "="
|
||||||
str(nowscore) +
|
+ str(nowscore)
|
||||||
"}" +
|
+ "}"
|
||||||
f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}")
|
+ f"] ~ ~ ~ playsound {soundID} @s ~ ~{1 / MaxVolume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}"
|
||||||
|
)
|
||||||
commands += 1
|
commands += 1
|
||||||
if len(singleTrack) != 0:
|
if len(singleTrack) != 0:
|
||||||
tracks.append(singleTrack)
|
tracks.append(singleTrack)
|
||||||
@ -576,7 +548,8 @@ class midiConvert:
|
|||||||
if volume <= 0:
|
if volume <= 0:
|
||||||
volume = 0.001
|
volume = 0.001
|
||||||
|
|
||||||
if isMixedWithPrograssBar:
|
# 此处是对于仅有 True 的参数和自定义参数的判断
|
||||||
|
if isMixedWithPrograssBar == True:
|
||||||
isMixedWithPrograssBar = (
|
isMixedWithPrograssBar = (
|
||||||
r"▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]",
|
r"▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]",
|
||||||
("§e=§r", "§7=§r"),
|
("§e=§r", "§7=§r"),
|
||||||
@ -607,7 +580,8 @@ class midiConvert:
|
|||||||
)
|
)
|
||||||
except BaseException:
|
except BaseException:
|
||||||
tracks[nowtick] = [
|
tracks[nowtick] = [
|
||||||
f"execute {player} ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}", ]
|
f"execute {player} ~ ~ ~ playsound {soundID} @s ~ ~{1 / volume - 1} ~ {msg.velocity * (0.7 if msg.channel == 0 else 0.9)} {2 ** ((msg.note - 60 - _X) / 12)}",
|
||||||
|
]
|
||||||
|
|
||||||
allticks = list(tracks.keys())
|
allticks = list(tracks.keys())
|
||||||
|
|
||||||
@ -629,11 +603,8 @@ class midiConvert:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __replace(
|
def __replace(
|
||||||
s: str,
|
s: str, tobeReplaced: str, replaceWith: str, times: int, other: str
|
||||||
tobeReplaced: str,
|
):
|
||||||
replaceWith: str,
|
|
||||||
times: int,
|
|
||||||
other: str):
|
|
||||||
if times == 0:
|
if times == 0:
|
||||||
return s.replace(tobeReplaced, other)
|
return s.replace(tobeReplaced, other)
|
||||||
if times == s.count(tobeReplaced):
|
if times == s.count(tobeReplaced):
|
||||||
@ -699,12 +670,12 @@ class midiConvert:
|
|||||||
if ids[r"%%s"]:
|
if ids[r"%%s"]:
|
||||||
nowstr = nowstr.replace(r"%%s", str(allticks[i] + 1))
|
nowstr = nowstr.replace(r"%%s", str(allticks[i] + 1))
|
||||||
if ids[r"%%t"]:
|
if ids[r"%%t"]:
|
||||||
nowstr = nowstr.replace(
|
nowstr = nowstr.replace(r"%%t", self.__score2time(allticks[i] + 1))
|
||||||
r"%%t", self.__score2time(
|
|
||||||
allticks[i] + 1))
|
|
||||||
if ids[r"%%%"]:
|
if ids[r"%%%"]:
|
||||||
nowstr = nowstr.replace(r"%%%", str(
|
nowstr = nowstr.replace(
|
||||||
int((allticks[i] + 1) / allticks[-1] * 10000) / 100) + "%", )
|
r"%%%",
|
||||||
|
str(int((allticks[i] + 1) / allticks[-1] * 10000) / 100) + "%",
|
||||||
|
)
|
||||||
|
|
||||||
countof_s = int((allticks[i] + 1) / allticks[-1] * pgblength)
|
countof_s = int((allticks[i] + 1) / allticks[-1] * pgblength)
|
||||||
|
|
||||||
@ -752,8 +723,7 @@ class midiConvert:
|
|||||||
:return 成功与否,成功返回(True,True),失败返回(False,str失败原因)
|
:return 成功与否,成功返回(True,True),失败返回(False,str失败原因)
|
||||||
"""
|
"""
|
||||||
if method == 1:
|
if method == 1:
|
||||||
cmdlist, _a, maxscore = self._toCmdList_m1(
|
cmdlist, _a, maxscore = self._toCmdList_m1(scoreboardname, volume, speed)
|
||||||
scoreboardname, volume, speed)
|
|
||||||
else:
|
else:
|
||||||
return (False, f"无法找到算法ID{method}对应的转换算法")
|
return (False, f"无法找到算法ID{method}对应的转换算法")
|
||||||
del _a
|
del _a
|
||||||
@ -768,17 +738,19 @@ class midiConvert:
|
|||||||
with open(
|
with open(
|
||||||
f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8"
|
f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8"
|
||||||
) as f:
|
) as f:
|
||||||
f.write('{\n "format_version": 1,\n "header": {\n "description": "' +
|
f.write(
|
||||||
self.midFileName +
|
'{\n "format_version": 1,\n "header": {\n "description": "'
|
||||||
' Pack : behavior pack",\n "version": [ 0, 0, 1 ],\n "name": "' +
|
+ self.midFileName
|
||||||
self.midFileName +
|
+ ' Pack : behavior pack",\n "version": [ 0, 0, 1 ],\n "name": "'
|
||||||
'Pack",\n "uuid": "' +
|
+ self.midFileName
|
||||||
str(uuid.uuid4()) +
|
+ 'Pack",\n "uuid": "'
|
||||||
'"\n },\n "modules": [\n {\n "description": "' +
|
+ str(uuid.uuid4())
|
||||||
f"the Player of the Music {self.midFileName}" +
|
+ '"\n },\n "modules": [\n {\n "description": "'
|
||||||
'",\n "type": "data",\n "version": [ 0, 0, 1 ],\n "uuid": "' +
|
+ f"the Player of the Music {self.midFileName}"
|
||||||
str(uuid.uuid4()) +
|
+ '",\n "type": "data",\n "version": [ 0, 0, 1 ],\n "uuid": "'
|
||||||
'"\n }\n ]\n}')
|
+ str(uuid.uuid4())
|
||||||
|
+ '"\n }\n ]\n}'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
with open(
|
with open(
|
||||||
f"{self.outputPath}/temp/manifest.json", "r", encoding="utf-8"
|
f"{self.outputPath}/temp/manifest.json", "r", encoding="utf-8"
|
||||||
@ -792,14 +764,14 @@ class midiConvert:
|
|||||||
data["modules"][0]["description"] = "None"
|
data["modules"][0]["description"] = "None"
|
||||||
data["modules"][0]["uuid"] = str(uuid.uuid4())
|
data["modules"][0]["uuid"] = str(uuid.uuid4())
|
||||||
manifest.close()
|
manifest.close()
|
||||||
open(f"{self.outputPath}/temp/manifest.json", "w",
|
open(f"{self.outputPath}/temp/manifest.json", "w", encoding="utf-8").write(
|
||||||
encoding="utf-8").write(json.dumps(data))
|
json.dumps(data)
|
||||||
|
)
|
||||||
|
|
||||||
# 将命令列表写入文件
|
# 将命令列表写入文件
|
||||||
indexfile = open(
|
indexfile = open(
|
||||||
f"{self.outputPath}/temp/functions/index.mcfunction",
|
f"{self.outputPath}/temp/functions/index.mcfunction", "w", encoding="utf-8"
|
||||||
"w",
|
)
|
||||||
encoding="utf-8")
|
|
||||||
for track in cmdlist:
|
for track in cmdlist:
|
||||||
indexfile.write(
|
indexfile.write(
|
||||||
"function mscplay/track" + str(cmdlist.index(track) + 1) + "\n"
|
"function mscplay/track" + str(cmdlist.index(track) + 1) + "\n"
|
||||||
@ -839,10 +811,8 @@ class midiConvert:
|
|||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
) as f:
|
) as f:
|
||||||
f.writelines(
|
f.writelines(
|
||||||
"\n".join(
|
"\n".join(self.__formProgressBar(maxscore, scoreboardname))
|
||||||
self.__formProgressBar(
|
)
|
||||||
maxscore,
|
|
||||||
scoreboardname)))
|
|
||||||
else:
|
else:
|
||||||
with open(
|
with open(
|
||||||
f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction",
|
f"{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction",
|
||||||
@ -860,9 +830,8 @@ class midiConvert:
|
|||||||
indexfile.close()
|
indexfile.close()
|
||||||
|
|
||||||
makeZip(
|
makeZip(
|
||||||
f"{self.outputPath}/temp/",
|
f"{self.outputPath}/temp/", self.outputPath + f"/{self.midFileName}.mcpack"
|
||||||
self.outputPath +
|
)
|
||||||
f"/{self.midFileName}.mcpack")
|
|
||||||
|
|
||||||
shutil.rmtree(f"{self.outputPath}/temp/")
|
shutil.rmtree(f"{self.outputPath}/temp/")
|
||||||
|
|
||||||
@ -943,8 +912,9 @@ class midiConvert:
|
|||||||
+ scoreboardname
|
+ scoreboardname
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 此处是对于仅有 True 的参数和自定义参数的判断
|
||||||
if progressbar:
|
if progressbar:
|
||||||
if progressbar:
|
if progressbar == True:
|
||||||
commands += self.__formProgressBar(maxScore, scoreboardname)
|
commands += self.__formProgressBar(maxScore, scoreboardname)
|
||||||
else:
|
else:
|
||||||
commands += self.__formProgressBar(
|
commands += self.__formProgressBar(
|
||||||
@ -976,8 +946,7 @@ class midiConvert:
|
|||||||
|
|
||||||
nowy += 1 if yforward else -1
|
nowy += 1 if yforward else -1
|
||||||
|
|
||||||
if ((nowy > maxheight) and (yforward)) or (
|
if ((nowy > maxheight) and (yforward)) or ((nowy < 0) and (not yforward)):
|
||||||
(nowy < 0) and (not yforward)):
|
|
||||||
nowy -= 1 if yforward else -1
|
nowy -= 1 if yforward else -1
|
||||||
|
|
||||||
yforward = not yforward
|
yforward = not yforward
|
||||||
@ -1027,8 +996,7 @@ class midiConvert:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if method == 1:
|
if method == 1:
|
||||||
cmdlist = self._toCmdList_withDelay_m1(
|
cmdlist = self._toCmdList_withDelay_m1(volume, speed, player, progressbar)
|
||||||
volume, speed, player, progressbar)
|
|
||||||
else:
|
else:
|
||||||
return (False, f"无法找到算法ID {method} 对应的转换算法")
|
return (False, f"无法找到算法ID {method} 对应的转换算法")
|
||||||
|
|
||||||
@ -1088,8 +1056,7 @@ class midiConvert:
|
|||||||
|
|
||||||
nowy += 1 if yforward else -1
|
nowy += 1 if yforward else -1
|
||||||
|
|
||||||
if ((nowy > maxheight) and (yforward)) or (
|
if ((nowy > maxheight) and (yforward)) or ((nowy < 0) and (not yforward)):
|
||||||
(nowy < 0) and (not yforward)):
|
|
||||||
nowy -= 1 if yforward else -1
|
nowy -= 1 if yforward else -1
|
||||||
|
|
||||||
yforward = not yforward
|
yforward = not yforward
|
||||||
|
Loading…
Reference in New Issue
Block a user