mirror of
https://github.com/TriM-Organization/Musicreater.git
synced 2026-07-24 17:22:32 +00:00
Compare commits
364 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f226b1fab | |||
| cb95c51a47 | |||
| 6fe8e41dfa | |||
| b8bae7b913 | |||
| 7663bf8838 | |||
| 8aa503710d | |||
| d5d7230537 | |||
| 5d48fcd96a | |||
| aa94e3758b | |||
| 8b06078a90 | |||
| 799b9b664d | |||
| 4874ace92d | |||
| 54cd6b196e | |||
| 882fa4175e | |||
| b15c89b6c8 | |||
| b758a2f967 | |||
| a9ec7582a9 | |||
| 48f5a975db | |||
| acb347b491 | |||
| 6ca8820fa8 | |||
| fb4cd07dc6 | |||
| 3db35b24ab | |||
| a07f723d7c | |||
| 7cc70d6948 | |||
| b1fb82712d | |||
| bd329082c2 | |||
| 16be83ea29 | |||
| 5ffb654ec9 | |||
| 7f5efea038 | |||
| 5efabd5463 | |||
| 24fd0121a3 | |||
| a65be910a5 | |||
| 15cd0ad777 | |||
| 4904f612e1 | |||
| 27c6556693 | |||
| 26fbd346d8 | |||
| c419adc274 | |||
| f8926d2f4f | |||
| 4268139313 | |||
| 8b8334202c | |||
| 1cfbfe1ba1 | |||
| 3669b5f804 | |||
| 7146d17051 | |||
| 8a21b6c3e7 | |||
| 5cce59135a | |||
| 53fda9c986 | |||
| 75f94dab4c | |||
| 6aa557dcd2 | |||
| 215bcafb64 | |||
| f568803b0d | |||
| a8c0c9e1d5 | |||
| 4d7a1b614a | |||
| 975dbd71e3 | |||
| 8722d4fd83 | |||
| 8b9d9a78a3 | |||
| 032bbb81c4 | |||
| 49c4cfcbe2 | |||
| 352807cba0 | |||
| 8e938b4f84 | |||
| bf0ef8ebb2 | |||
| c4664f0e0c | |||
| 65a21dcfa7 | |||
| 032e2f0f0a | |||
| 87e80406a3 | |||
| 41a6a84342 | |||
| 4b9550db21 | |||
| 3d66c06e6d | |||
| 9872a69a66 | |||
| 0ce72fc4e3 | |||
| e0557da3cf | |||
| 7d6faebc5b | |||
| 502f4eb54d | |||
| 290db45c23 | |||
| 782395b6c9 | |||
| 392e74d8d9 | |||
| ebfaeafcda | |||
| 6955bb8eaf | |||
| 582e66cd58 | |||
| d64540bfd0 | |||
| 63499732eb | |||
| be40f8f920 | |||
| 190ef70fc4 | |||
| a74fd4b4de | |||
| 13f7c0cda0 | |||
| 2ebdf6be24 | |||
| 9ca0788eb2 | |||
| fba83ef968 | |||
| 68e019412d | |||
| bde2b4e378 | |||
| b04c01772f | |||
| 3cd85897fc | |||
| 00c2dcdeab | |||
| 88d36f94f0 | |||
| 8eda5c4736 | |||
| 37ccbe3dae | |||
| be43e4a92a | |||
| 5929ae417d | |||
| 517c7db112 | |||
| 91c31d4e90 | |||
| 3ae456c4d1 | |||
| b0af5f4950 | |||
| 1ccaa8e9aa | |||
| 8d1e6b2ecf | |||
| 75fabf9c37 | |||
| 95e34f5c7b | |||
| 5bb0227a7a | |||
| 397825b483 | |||
| 9c9ebe0a08 | |||
| 54d434404c | |||
| 0b3a19faad | |||
| 6cde168bf3 | |||
| 451d1d8e80 | |||
| 085ab3f4c0 | |||
| a16109f29a | |||
| 813186bef9 | |||
| 3921190832 | |||
| c32b94592a | |||
| 77b7344277 | |||
| 0a17f8b8f8 | |||
| f8d707ac11 | |||
| ad7e047abc | |||
| 5ea47c54cb | |||
| 5956e27d83 | |||
| b73a041883 | |||
| 36f1831cd1 | |||
| b20f350da4 | |||
| 5aaae83020 | |||
| 85e6340570 | |||
| 662c6506d8 | |||
| ad2fcd6f14 | |||
| 5dde31d081 | |||
| 2e11a9949b | |||
| 0a9c70f97c | |||
| 814ab2ab0e | |||
| 3b53846ade | |||
| 96af5183ac | |||
| 4aebf9db16 | |||
| fff689446a | |||
| 59fd2645e4 | |||
| 33ce7ed8c8 | |||
| 14f7d6fd7e | |||
| fb2fd13b21 | |||
| 5025cba356 | |||
| abb53a7499 | |||
| 73854be7be | |||
| 6f6a77d0b4 | |||
| e0a3399fed | |||
| 2afd6beb3f | |||
| 9517c49ec5 | |||
| 887452184b | |||
| d36134e525 | |||
| 453ca745af | |||
| 7d814bcda2 | |||
| 50dff06ac2 | |||
| d88e50819d | |||
| 325bb37210 | |||
| 55b933ac85 | |||
| 56fb029e75 | |||
| c5a7dfb608 | |||
| 0a640267ff | |||
| a6d7022f87 | |||
| dcc62ca66d | |||
| 4b53938adf | |||
| 8502a02880 | |||
| 80fab8ced0 | |||
| 1980aeb8de | |||
| 1fde8ca253 | |||
| 0ce24bff92 | |||
| 992572cbf1 | |||
| ce1099a246 | |||
| 2340741bb9 | |||
| 1f94f558c4 | |||
| 0c50ce1134 | |||
| 2e0dd06db6 | |||
| 9fd32d499f | |||
| 5c501a3466 | |||
| e872c19676 | |||
| 51d248cdc2 | |||
| a1dfe65042 | |||
| 70fc686057 | |||
| ba691d177a | |||
| b81860dadd | |||
| 343a62be47 | |||
| ab26c82bf9 | |||
| a2ae755e87 | |||
| e94af73c4f | |||
| bc247e1507 | |||
| 874cd1aea9 | |||
| 5a6d874204 | |||
| 08ffa1a6e2 | |||
| 16d0ecf009 | |||
| f57f4257fb | |||
| 3f0f714a7c | |||
| 65c23ca427 | |||
| bc99f8f4be | |||
| 3b6cb3865f | |||
| 64292a21b3 | |||
| 3ba8fdad8c | |||
| 7357a09e5f | |||
| cae0b7f23d | |||
| e1d4cd9933 | |||
| 3bc19ac396 | |||
| 3499c05eb4 | |||
| 259fb04980 | |||
| 8ce7a9fa83 | |||
| affb5b5404 | |||
| 1805ab53c0 | |||
| f3c5044800 | |||
| ca2e8c9155 | |||
| eda3a957cf | |||
| 4788d8949b | |||
| 1715735800 | |||
| d22b5b0c42 | |||
| 549dd3dbf9 | |||
| a65bfeba20 | |||
| 7edf979aee | |||
| 8f6cc04780 | |||
| 6cb5c9ba89 | |||
| ae83f9c21e | |||
| dd34ac9998 | |||
| 2da06136c5 | |||
| e9f4230a2d | |||
| 1b7ab73c02 | |||
| 2624c081bb | |||
| 87cc189da8 | |||
| 668bf480b2 | |||
| 4cc3f2678f | |||
| 701e9d5129 | |||
| 8dd2694e82 | |||
| ac962f0ab7 | |||
| b800384547 | |||
| 5da1041664 | |||
| 966ce515c3 | |||
| 349c255f5f | |||
| cbb77086d0 | |||
| 280e50f4cb | |||
| a2a37be8ef | |||
| 7acd6b7e38 | |||
| 4c95f76cf9 | |||
| 8a1a159eb8 | |||
| cb43caef26 | |||
| 200167ef84 | |||
| 7e0a127406 | |||
| 5e70dd73a1 | |||
| 7229b12e99 | |||
| 074124bc3d | |||
| 91446bfd81 | |||
| 5011efcdee | |||
| 3b4af19379 | |||
| d3d89d2567 | |||
| 441d1e9982 | |||
| 77e738cb7e | |||
| 46b6884e64 | |||
| d0a63d0f8e | |||
| 887394570b | |||
| c62806d470 | |||
| d21c26d632 | |||
| 26ec42a71d | |||
| 245e2fa1ec | |||
| e70fc806be | |||
| 72a3715722 | |||
| fd3d27d596 | |||
| 3d283bfded | |||
| 7d9b63b9fe | |||
| 82850a3d74 | |||
| 629cfa402b | |||
| 0818957f51 | |||
| 954a30f722 | |||
| 96e6bc2f7a | |||
| ca0e56e771 | |||
| 8fe71dbe0d | |||
| 97f334789e | |||
| d2a6ce2529 | |||
| 066e0b0cac | |||
| 052142ac08 | |||
| 59c481f6da | |||
| 53c17f0328 | |||
| ed28fc4866 | |||
| 320114533d | |||
| aa210ac678 | |||
| c4dd7b1ce8 | |||
| 99509be48c | |||
| 073ae827ab | |||
| 58b312554d | |||
| 55eeddb108 | |||
| 9d4a75cd41 | |||
| 882ce96b90 | |||
| 9093a66639 | |||
| b48a66115a | |||
| db20a87ae9 | |||
| 69eebd25a9 | |||
| 89ef3bcb55 | |||
| f08a2ff9be | |||
| 9f8694ef14 | |||
| 81272a1166 | |||
| a83052bd5d | |||
| 2fcfdca0a0 | |||
| bcaeb129a5 | |||
| 36b639f029 | |||
| 4b241dfc0b | |||
| 255cc84ef3 | |||
| c04b622297 | |||
| b6a63a794e | |||
| 7c0dd218b2 | |||
| 19bbb92cff | |||
| 26ee16f071 | |||
| 05eb0c05ec | |||
| 5d2e0582c3 | |||
| d3e0f78d2c | |||
| 79a2dfb5b1 | |||
| bf3367c7e4 | |||
| c91f5cf2f9 | |||
| d8ea747ef1 | |||
| 39148a6c76 | |||
| 0e3eb394ab | |||
| f0dedabe1a | |||
| dda78ab35f | |||
| 5b6ff5ee68 | |||
| fcb1a25227 | |||
| 81eb8e5376 | |||
| 7e13b22d46 | |||
| 07e153f215 | |||
| 908f622433 | |||
| 5f7ca0859f | |||
| 32ae868c34 | |||
| ce441e4905 | |||
| 3dc099af7e | |||
| cf7e51595e | |||
| 737b2d5f07 | |||
| 143de0bb37 | |||
| 17f9fa7ffc | |||
| 1bc1c6485b | |||
| 4bd7fca256 | |||
| ae2c9de9df | |||
| 60c85c663e | |||
| 8c2c0cc464 | |||
| 2cd7132762 | |||
| 71d445d255 | |||
| 737ec6a1be | |||
| 061d8bfa96 | |||
| 2f6c0e23d7 | |||
| ee5fd84d51 | |||
| 015ab129e9 | |||
| d3343ddd51 | |||
| c78a537573 | |||
| d353fc2ee8 | |||
| 1e6130fcd3 | |||
| 7e98c7bdb2 | |||
| 8cc1aa708f | |||
| 0b1a876b14 | |||
| 673239356c | |||
| 9e6994db34 | |||
| f8165b0e45 | |||
| ad2234ca10 | |||
| af3c7432ed | |||
| 44a3b6ce4f | |||
| 42ca4bcac1 | |||
| bdde742b3d | |||
| 3c46924afb | |||
| 9a181d709a | |||
| 4ae5d08f99 | |||
| bc227afd43 | |||
| f86879a673 | |||
| c674fbac3b |
@@ -0,0 +1,3 @@
|
||||
*.yaml linguist-language=Python
|
||||
*.xml linguist-language=Python
|
||||
*.md linguist-language=Python
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
# sth. can't open
|
||||
/msctPkgver/secrets/*.py
|
||||
/msctPkgver/secrets/*.c
|
||||
|
||||
|
||||
# mystuff
|
||||
/.vscode
|
||||
*.mid
|
||||
*.midi
|
||||
*.mcpack
|
||||
*.bdx
|
||||
*.json
|
||||
*.mcstructure
|
||||
/logs
|
||||
/languages
|
||||
/llc_cli.py
|
||||
/utils
|
||||
test.py
|
||||
|
||||
# Byte-compiled / optimized
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*$py.class
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# Pycharm
|
||||
/.idea
|
||||
|
||||
# log
|
||||
/.log
|
||||
|
||||
# package
|
||||
.7z
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
**注意,以下条款或版权声明应当且必须是高于此项目中任何其他声明的**
|
||||
|
||||
1. 音·创的全部开发者享有其完整版权,其开发者可以在任一时刻终止以后音·创源代码开放,若经由其开发者授予特殊权利,则授权对象可以将源代码进行特定的被特殊授权的操作
|
||||
2. 音·创或(及)其代码允许在 Apache2.0 协议的条款与说明下进行非商业使用
|
||||
3. 除部分代码特殊声明外,音·创允许对其或(及)其代码进行商业化使用,但是需要经过音·创主要开发者(诸葛亮与八卦阵、金羿)的一致授权,同时,授权对象在商业化授权的使用过程中必须依照 Apache2.0 协议的条款与说明
|
||||
4. 若存在对于音·创包含的部分代码的特殊开源声明,则此部分代码依照其特定的开源方式授权,但若此部分代码经由此部分代码的主要开发者一致特殊授权后商用,则授权对象在商用时依照此部分的开发者所准许的方式(或条款)进行商用,或默认依照 Apache2.0 协议进行商业化使用
|
||||
5. Apache2.0 协议的英文原文副本可见下文
|
||||
|
||||
> The English Translation of the TERMS AND CONDITIONS above is listed below
|
||||
>
|
||||
> This translated version is for reference only and has no legal effect.
|
||||
>
|
||||
> The version with legal effect is the Chinese version above.
|
||||
|
||||
**Note, The TERMS AND CONDITIONS below should and must be above all others in this project**
|
||||
|
||||
1. *Musicreater* is fully copyrighted by all its developers, the developers have the right to make *Musicreater* close sourced at any time. Operations are permitted under specific terms instructed by its developer(s).
|
||||
2. Non-commercial use of *Musicreater* and(or) its source code is permitted under Apache License 2.0.
|
||||
3. Commercial use of *Musicreater* is permitted under Apache License 2.0 with the unanimous permission of the steering developers of *Musicreater* (*bgArray*诸葛亮与八卦阵 and *Eilles*金羿).
|
||||
4. *Musicreater* is open sourced under priority given:
|
||||
1. License granted by the core developer(s) of a section after negotiation.
|
||||
2. Explicitly stated license.
|
||||
3. Apache 2.0 License.
|
||||
5. A copy of the original Apache Lisence 2.0 can be found below.
|
||||
|
||||
|
||||
```text
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
Copyright 2022 Team-Ryoun 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray")
|
||||
|
||||
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.
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""一个简单的我的世界音频转换库
|
||||
音·创 (Musicreater)
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater(音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2023 音·创 开发者
|
||||
Copyright © 2023 all the developers of Musicreater
|
||||
|
||||
开源相关声明请见 ../License.md
|
||||
Terms & Conditions: ../License.md
|
||||
"""
|
||||
|
||||
# 睿穆组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
from .main import *
|
||||
|
||||
__version__ = "0.5.1"
|
||||
__all__ = []
|
||||
__author__ = (("金羿", "Eilles Wan"), ("诸葛亮与八卦阵", "bgArray"), ("鸣凤鸽子", "MingFengPigeon"))
|
||||
@@ -0,0 +1,102 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
# 睿穆组织 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
"""一个简单的我的世界音频转换库
|
||||
音·创 (Musicreater)
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater(音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2023 音·创 开发者
|
||||
Copyright © 2023 all the developers of Musicreater
|
||||
|
||||
开源相关声明请见 ../License.md
|
||||
Terms & Conditions: ../License.md
|
||||
"""
|
||||
|
||||
|
||||
class MSCTBaseException(Exception):
|
||||
"""音·创库版本的所有错误均继承于此"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音·创库版本的所有错误均继承于此"""
|
||||
super().__init__(*args)
|
||||
|
||||
def miao(
|
||||
self,
|
||||
):
|
||||
for i in self.args:
|
||||
print(i + "喵!")
|
||||
|
||||
def crash_it(self):
|
||||
raise self
|
||||
|
||||
|
||||
class MidiFormatException(MSCTBaseException):
|
||||
"""音·创库版本的所有MIDI格式错误均继承于此"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""音·创库版本的所有MIDI格式错误均继承于此"""
|
||||
super().__init__("MIDI格式错误", *args)
|
||||
|
||||
|
||||
class MidiDestroyedError(MSCTBaseException):
|
||||
"""Midi文件损坏"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""Midi文件损坏"""
|
||||
super().__init__("MIDI文件损坏:无法读取MIDI文件", *args)
|
||||
|
||||
|
||||
class CommandFormatError(RuntimeError):
|
||||
"""指令格式与目标格式不匹配而引起的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""指令格式与目标格式不匹配而引起的错误"""
|
||||
super().__init__("指令格式不匹配", *args)
|
||||
|
||||
|
||||
class CrossNoteError(MidiFormatException):
|
||||
"""同通道下同音符交叉出现所产生的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""同通道下同音符交叉出现所产生的错误"""
|
||||
super().__init__("同通道下同音符交叉", *args)
|
||||
|
||||
|
||||
class NotDefineTempoError(MidiFormatException):
|
||||
"""没有Tempo设定导致时间无法计算的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""没有Tempo设定导致时间无法计算的错误"""
|
||||
super().__init__("在曲目开始时没有声明Tempo(未指定拍长)", *args)
|
||||
|
||||
|
||||
class ChannelOverFlowError(MidiFormatException):
|
||||
"""一个midi中含有过多的通道"""
|
||||
|
||||
def __init__(self, max_channel=16, *args):
|
||||
"""一个midi中含有过多的通道"""
|
||||
super().__init__("含有过多的通道(数量应≤{})".format(max_channel), *args)
|
||||
|
||||
|
||||
class NotDefineProgramError(MidiFormatException):
|
||||
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""没有Program设定导致没有乐器可以选择的错误"""
|
||||
super().__init__("未指定演奏乐器", *args)
|
||||
|
||||
|
||||
class ZeroSpeedError(MidiFormatException):
|
||||
"""以0作为播放速度的错误"""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""以0作为播放速度的错误"""
|
||||
super().__init__("播放速度为0", *args)
|
||||
@@ -0,0 +1,219 @@
|
||||
pitched_instrument_list = {
|
||||
0: ("note.harp", 6),
|
||||
1: ("note.harp", 6),
|
||||
2: ("note.pling", 6),
|
||||
3: ("note.harp", 6),
|
||||
4: ("note.pling", 6),
|
||||
5: ("note.pling", 6),
|
||||
6: ("note.harp", 6),
|
||||
7: ("note.harp", 6),
|
||||
8: ("note.share", 7), # 打击乐器无音域
|
||||
9: ("note.harp", 6),
|
||||
10: ("note.didgeridoo", 8),
|
||||
11: ("note.harp", 6),
|
||||
12: ("note.xylophone", 4),
|
||||
13: ("note.chime", 4),
|
||||
14: ("note.harp", 6),
|
||||
15: ("note.harp", 6),
|
||||
16: ("note.bass", 8),
|
||||
17: ("note.harp", 6),
|
||||
18: ("note.harp", 6),
|
||||
19: ("note.harp", 6),
|
||||
20: ("note.harp", 6),
|
||||
21: ("note.harp", 6),
|
||||
22: ("note.harp", 6),
|
||||
23: ("note.guitar", 7),
|
||||
24: ("note.guitar", 7),
|
||||
25: ("note.guitar", 7),
|
||||
26: ("note.guitar", 7),
|
||||
27: ("note.guitar", 7),
|
||||
28: ("note.guitar", 7),
|
||||
29: ("note.guitar", 7),
|
||||
30: ("note.guitar", 7),
|
||||
31: ("note.bass", 8),
|
||||
32: ("note.bass", 8),
|
||||
33: ("note.bass", 8),
|
||||
34: ("note.bass", 8),
|
||||
35: ("note.bass", 8),
|
||||
36: ("note.bass", 8),
|
||||
37: ("note.bass", 8),
|
||||
38: ("note.bass", 8),
|
||||
39: ("note.bass", 8),
|
||||
40: ("note.harp", 6),
|
||||
41: ("note.harp", 6),
|
||||
42: ("note.harp", 6),
|
||||
43: ("note.harp", 6),
|
||||
44: ("note.iron_xylophone", 6),
|
||||
45: ("note.guitar", 7),
|
||||
46: ("note.harp", 6),
|
||||
47: ("note.harp", 6),
|
||||
48: ("note.guitar", 7),
|
||||
49: ("note.guitar", 7),
|
||||
50: ("note.bit", 6),
|
||||
51: ("note.bit", 6),
|
||||
52: ("note.harp", 6),
|
||||
53: ("note.harp", 6),
|
||||
54: ("note.bit", 6),
|
||||
55: ("note.flute", 5),
|
||||
56: ("note.flute", 5),
|
||||
57: ("note.flute", 5),
|
||||
58: ("note.flute", 5),
|
||||
59: ("note.flute", 5),
|
||||
60: ("note.flute", 5),
|
||||
61: ("note.flute", 5),
|
||||
62: ("note.flute", 5),
|
||||
63: ("note.flute", 5),
|
||||
64: ("note.bit", 6),
|
||||
65: ("note.bit", 6),
|
||||
66: ("note.bit", 6),
|
||||
67: ("note.bit", 6),
|
||||
68: ("note.flute", 5),
|
||||
69: ("note.harp", 6),
|
||||
70: ("note.harp", 6),
|
||||
71: ("note.flute", 5),
|
||||
72: ("note.flute", 5),
|
||||
73: ("note.flute", 5),
|
||||
74: ("note.harp", 6),
|
||||
75: ("note.flute", 5),
|
||||
76: ("note.harp", 6),
|
||||
77: ("note.harp", 6),
|
||||
78: ("note.harp", 6),
|
||||
79: ("note.harp", 6),
|
||||
80: ("note.bit", 6),
|
||||
81: ("note.bit", 6),
|
||||
82: ("note.bit", 6),
|
||||
83: ("note.bit", 6),
|
||||
84: ("note.bit", 6),
|
||||
85: ("note.bit", 6),
|
||||
86: ("note.bit", 6),
|
||||
87: ("note.bit", 6),
|
||||
88: ("note.bit", 6),
|
||||
89: ("note.bit", 6),
|
||||
90: ("note.bit", 6),
|
||||
91: ("note.bit", 6),
|
||||
92: ("note.bit", 6),
|
||||
93: ("note.bit", 6),
|
||||
94: ("note.bit", 6),
|
||||
95: ("note.bit", 6),
|
||||
96: ("note.bit", 6),
|
||||
97: ("note.bit", 6),
|
||||
98: ("note.bit", 6),
|
||||
99: ("note.bit", 6),
|
||||
100: ("note.bit", 6),
|
||||
101: ("note.bit", 6),
|
||||
102: ("note.bit", 6),
|
||||
103: ("note.bit", 6),
|
||||
104: ("note.harp", 6),
|
||||
105: ("note.banjo", 6),
|
||||
106: ("note.harp", 6),
|
||||
107: ("note.harp", 6),
|
||||
108: ("note.harp", 6),
|
||||
109: ("note.harp", 6),
|
||||
110: ("note.harp", 6),
|
||||
111: ("note.guitar", 7),
|
||||
112: ("note.harp", 6),
|
||||
113: ("note.bell", 4),
|
||||
114: ("note.harp", 6),
|
||||
115: ("note.cow_bell", 5),
|
||||
116: ("note.bd", 7), # 打击乐器无音域
|
||||
117: ("note.bass", 8),
|
||||
118: ("note.bit", 6),
|
||||
119: ("note.bd", 7), # 打击乐器无音域
|
||||
120: ("note.guitar", 7),
|
||||
121: ("note.harp", 6),
|
||||
122: ("note.harp", 6),
|
||||
123: ("note.harp", 6),
|
||||
124: ("note.harp", 6),
|
||||
125: ("note.hat", 7), # 打击乐器无音域
|
||||
126: ("note.bd", 7), # 打击乐器无音域
|
||||
127: ("note.snare", 7), # 打击乐器无音域
|
||||
}
|
||||
|
||||
percussion_instrument_list = {
|
||||
34: ("note.bd", 7),
|
||||
35: ("note.bd", 7),
|
||||
36: ("note.hat", 7),
|
||||
37: ("note.snare", 7),
|
||||
38: ("note.snare", 7),
|
||||
39: ("note.snare", 7),
|
||||
40: ("note.hat", 7),
|
||||
41: ("note.snare", 7),
|
||||
42: ("note.hat", 7),
|
||||
43: ("note.snare", 7),
|
||||
44: ("note.snare", 7),
|
||||
45: ("note.bell", 4),
|
||||
46: ("note.snare", 7),
|
||||
47: ("note.snare", 7),
|
||||
48: ("note.bell", 4),
|
||||
49: ("note.hat", 7),
|
||||
50: ("note.bell", 4),
|
||||
51: ("note.bell", 4),
|
||||
52: ("note.bell", 4),
|
||||
53: ("note.bell", 4),
|
||||
54: ("note.bell", 4),
|
||||
55: ("note.bell", 4),
|
||||
56: ("note.snare", 7),
|
||||
57: ("note.hat", 7),
|
||||
58: ("note.chime", 4),
|
||||
59: ("note.iron_xylophone", 6),
|
||||
60: ("note.bd", 7),
|
||||
61: ("note.bd", 7),
|
||||
62: ("note.xylophone", 4),
|
||||
63: ("note.xylophone", 4),
|
||||
64: ("note.xylophone", 4),
|
||||
65: ("note.hat", 7),
|
||||
66: ("note.bell", 4),
|
||||
67: ("note.bell", 4),
|
||||
68: ("note.hat", 7),
|
||||
69: ("note.hat", 7),
|
||||
70: ("note.flute", 5),
|
||||
71: ("note.flute", 5),
|
||||
72: ("note.hat", 7),
|
||||
73: ("note.hat", 7),
|
||||
74: ("note.xylophone", 4),
|
||||
75: ("note.hat", 7),
|
||||
76: ("note.hat", 7),
|
||||
77: ("note.xylophone", 4),
|
||||
78: ("note.xylophone", 4),
|
||||
79: ("note.bell", 4),
|
||||
80: ("note.bell", 4),
|
||||
}
|
||||
|
||||
instrument_to_blocks_list = {
|
||||
"note.bass": ("planks",),
|
||||
"note.snare": ("sand",),
|
||||
"note.hat": ("glass",),
|
||||
"note.bd": ("stone",),
|
||||
"note.bell": ("gold_block",),
|
||||
"note.flute": ("clay",),
|
||||
"note.chime": ("packed_ice",),
|
||||
"note.guitar": ("wool",),
|
||||
"note.xylobone": ("bone_block",),
|
||||
"note.iron_xylophone": ("iron_block",),
|
||||
"note.cow_bell": ("soul_sand",),
|
||||
"note.didgeridoo": ("pumpkin",),
|
||||
"note.bit": ("emerald_block",),
|
||||
"note.banjo": ("hay_block",),
|
||||
"note.pling": ("glowstone",),
|
||||
"note.bassattack": ("command_block",), # 无法找到此音效
|
||||
"note.harp": ("glass",),
|
||||
}
|
||||
|
||||
nbs_instrument_to_name = {
|
||||
0: "Piano", # (air)
|
||||
1: "Double Bass", # (Wood)
|
||||
2: "Bass Drum", # (Stone)
|
||||
3: "Snare Drum", # (Sand)
|
||||
4: "Click", # (Glass)
|
||||
5: "Guitar", # (Wool)
|
||||
6: "Flute", # (Clay)
|
||||
7: "Bell", # (Block of Gold)
|
||||
8: "Chime", # (Packed Ice)
|
||||
9: "Xylophone", # (Bone Block)
|
||||
10: "Iron Xylophone", # (Iron Block)
|
||||
11: "Cow Bell", # (Soul Sand)
|
||||
12: "Didgeridoo", # (Pumpkin)
|
||||
13: "Bit", # (Block of Emerald)
|
||||
14: "Banjo", # (Hay)
|
||||
15: "Pling", # (Glowstone)
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
功能测试 若非已知 请勿更改
|
||||
此文件仅供功能测试,并非实际调用的文件
|
||||
请注意,此处的文件均为测试使用
|
||||
不要更改 不要更改 不要更改
|
||||
请注意这里的一切均需要其原作者更改
|
||||
这里用于放置一些新奇的点子
|
||||
用于测试
|
||||
不要更改 不要更改 不要更改!
|
||||
"""
|
||||
|
||||
# 音·创 开发交流群 861684859
|
||||
# Email TriM-Organization@hotmail.com
|
||||
# 版权所有 金羿("Eilles Wan") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon")
|
||||
# 若需转载或借鉴 许可声明请查看仓库目录下的 License.md
|
||||
|
||||
|
||||
"""
|
||||
音·创 (Musicreater)
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater (音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2023 音·创 开发者
|
||||
Copyright © 2023 all the developers of Musicreater
|
||||
|
||||
开源相关声明请见 ../License.md
|
||||
Terms & Conditions: ../License.md
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def _toCmdList_m1(
|
||||
self,
|
||||
scoreboardname: str = "mscplay",
|
||||
volume: float = 1.0,
|
||||
speed: float = 1.0) -> list:
|
||||
"""
|
||||
使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表
|
||||
:param scoreboardname: 我的世界的计分板名称
|
||||
:param volume: 音量,注意:这里的音量范围为(0,1],如果超出将被处理为正确值,其原理为在距离玩家 (1 / volume -1) 的地方播放音频
|
||||
:param speed: 速度,注意:这里的速度指的是播放倍率,其原理为在播放音频的时候,每个音符的播放时间除以 speed
|
||||
:return: tuple(命令列表, 命令个数, 计分板最大值)
|
||||
"""
|
||||
tracks = []
|
||||
if volume > 1:
|
||||
volume = 1
|
||||
if volume <= 0:
|
||||
volume = 0.001
|
||||
|
||||
commands = 0
|
||||
maxscore = 0
|
||||
|
||||
for i, track in enumerate(self.midi.tracks):
|
||||
|
||||
ticks = 0
|
||||
instrumentID = 0
|
||||
singleTrack = []
|
||||
|
||||
for msg in track:
|
||||
ticks += msg.time
|
||||
# print(msg)
|
||||
if msg.is_meta:
|
||||
if msg.type == "set_tempo":
|
||||
tempo = msg.tempo
|
||||
else:
|
||||
if msg.type == "program_change":
|
||||
# print("TT")
|
||||
instrumentID = msg.program
|
||||
if msg.type == "note_on" and msg.velocity != 0:
|
||||
nowscore = round(
|
||||
(ticks * tempo)
|
||||
/ ((self.midi.ticks_per_beat * float(speed)) * 50000)
|
||||
)
|
||||
maxscore = max(maxscore, nowscore)
|
||||
soundID, _X = self.__Inst2soundID_withX(instrumentID)
|
||||
singleTrack.append(
|
||||
"execute @a[scores={" +
|
||||
str(scoreboardname) +
|
||||
"=" +
|
||||
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)}")
|
||||
commands += 1
|
||||
if len(singleTrack) != 0:
|
||||
tracks.append(singleTrack)
|
||||
|
||||
return [tracks, commands, maxscore]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================
|
||||
|
||||
|
||||
|
||||
|
||||
import mido
|
||||
|
||||
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 = 60000000 / msg.tempo
|
||||
is_change_bpm = True
|
||||
|
||||
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"))
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================
|
||||
|
||||
|
||||
from typing import Union
|
||||
from .utils import x,y,z,bottem_side_length_of_smallest_square_bottom_box,form_note_block_in_NBT_struct,form_repeater_in_NBT_struct
|
||||
|
||||
# 不要用 没写完
|
||||
def delay_to_note_blocks(
|
||||
baseblock: str = "stone",
|
||||
position_forward: Union(x, y, z) = z,
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""传入音符,生成以音符盒存储的红石音乐
|
||||
:param:
|
||||
baseblock: 中继器的下垫方块
|
||||
position_forward: 结构延长方向
|
||||
:return 是否生成成功
|
||||
"""
|
||||
|
||||
from TrimMCStruct import Structure, Block
|
||||
|
||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||
len(commands), max_height
|
||||
)
|
||||
|
||||
struct = Structure(
|
||||
(_sideLength, max_height, _sideLength), # 声明结构大小
|
||||
)
|
||||
|
||||
log = print
|
||||
|
||||
startpos = [0,0,0]
|
||||
|
||||
|
||||
# 1拍 x 2.5 rt
|
||||
def placeNoteBlock():
|
||||
for i in notes:
|
||||
error = True
|
||||
try:
|
||||
struct.set_block(
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
form_note_block_in_NBT_struct(height2note[i[0]], instrument),
|
||||
)
|
||||
struct.set_block(startpos, Block("universal_minecraft", instuments[i[0]][1]),)
|
||||
error = False
|
||||
except ValueError:
|
||||
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
struct.set_block(
|
||||
Block("universal_minecraft", baseblock),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
finally:
|
||||
if error is True:
|
||||
log("无法放置音符:" + str(i) + "于" + str(startpos))
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
struct.set_block(
|
||||
Block("universal_minecraft", baseblock),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
delay = int(i[1] * speed + 0.5)
|
||||
if delay <= 4:
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(delay, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
else:
|
||||
for j in range(int(delay / 4)):
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(4, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
if delay % 4 != 0:
|
||||
startpos[0] += 1
|
||||
struct.set_block(
|
||||
form_repeater_in_NBT_struct(delay % 4, "west"),
|
||||
[startpos[0], startpos[1] + 1, startpos[2]],
|
||||
)
|
||||
struct.set_block(Block("universal_minecraft", baseblock), startpos)
|
||||
startpos[0] += posadder[0]
|
||||
startpos[1] += posadder[1]
|
||||
startpos[2] += posadder[2]
|
||||
|
||||
# e = True
|
||||
try:
|
||||
placeNoteBlock()
|
||||
# e = False
|
||||
except: # ValueError
|
||||
log("无法放置方块了,可能是因为区块未加载叭")
|
||||
|
||||
|
||||
+2145
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,459 @@
|
||||
import math
|
||||
import os
|
||||
|
||||
bdx_key = {
|
||||
"x": [b"\x0f", b"\x0e", b"\x1c", b"\x14", b"\x15"],
|
||||
"y": [b"\x11", b"\x10", b"\x1d", b"\x16", b"\x17"],
|
||||
"z": [b"\x13", b"\x12", b"\x1e", b"\x18", b"\x19"],
|
||||
}
|
||||
"""key存储了方块移动指令的数据,其中可以用key[x|y|z][0|1]来表示xyz的减或增
|
||||
而key[][2+]是用来增加指定数目的"""
|
||||
|
||||
x = "x"
|
||||
y = "y"
|
||||
z = "z"
|
||||
|
||||
|
||||
def bdx_move(axis: str, value: int):
|
||||
if value == 0:
|
||||
return b""
|
||||
if abs(value) == 1:
|
||||
return bdx_key[axis][0 if value == -1 else 1]
|
||||
|
||||
pointer = sum(
|
||||
[
|
||||
1 if i else 0
|
||||
for i in (
|
||||
value != -1,
|
||||
value < -1 or value > 1,
|
||||
value < -128 or value > 127,
|
||||
value < -32768 or value > 32767,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
return bdx_key[axis][pointer] + value.to_bytes(
|
||||
2 ** (pointer - 2), "big", signed=True
|
||||
)
|
||||
|
||||
|
||||
def compress_zipfile(sourceDir, outFilename, compression=8, exceptFile=None):
|
||||
"""使用compression指定的算法打包目录为zip文件\n
|
||||
默认算法为DEFLATED(8),可用算法如下:\n
|
||||
STORED = 0\n
|
||||
DEFLATED = 8\n
|
||||
BZIP2 = 12\n
|
||||
LZMA = 14\n
|
||||
"""
|
||||
import zipfile
|
||||
|
||||
zipf = zipfile.ZipFile(outFilename, "w", compression)
|
||||
pre_len = len(os.path.dirname(sourceDir))
|
||||
for parent, dirnames, filenames in os.walk(sourceDir):
|
||||
for filename in filenames:
|
||||
if filename == exceptFile:
|
||||
continue
|
||||
pathfile = os.path.join(parent, filename)
|
||||
arc_name = pathfile[pre_len:].strip(os.path.sep) # 相对路径
|
||||
zipf.write(pathfile, arc_name)
|
||||
zipf.close()
|
||||
|
||||
|
||||
def form_command_block_in_BDX_bytes(
|
||||
command: str,
|
||||
particularValue: int,
|
||||
impluse: int = 0,
|
||||
condition: bool = False,
|
||||
needRedstone: bool = True,
|
||||
tickDelay: int = 0,
|
||||
customName: str = "",
|
||||
executeOnFirstTick: bool = False,
|
||||
trackOutput: bool = True,
|
||||
):
|
||||
"""
|
||||
使用指定项目返回指定的指令方块放置指令项
|
||||
:param command: `str`
|
||||
指令
|
||||
:param particularValue:
|
||||
方块特殊值,即朝向
|
||||
:0 下 无条件
|
||||
:1 上 无条件
|
||||
:2 z轴负方向 无条件
|
||||
:3 z轴正方向 无条件
|
||||
:4 x轴负方向 无条件
|
||||
:5 x轴正方向 无条件
|
||||
:6 下 无条件
|
||||
:7 下 无条件
|
||||
|
||||
:8 下 有条件
|
||||
:9 上 有条件
|
||||
:10 z轴负方向 有条件
|
||||
:11 z轴正方向 有条件
|
||||
:12 x轴负方向 有条件
|
||||
:13 x轴正方向 有条件
|
||||
:14 下 有条件
|
||||
:14 下 有条件
|
||||
注意!此处特殊值中的条件会被下面condition参数覆写
|
||||
:param impluse: `int 0|1|2`
|
||||
方块类型
|
||||
0脉冲 1循环 2连锁
|
||||
:param condition: `bool`
|
||||
是否有条件
|
||||
:param needRedstone: `bool`
|
||||
是否需要红石
|
||||
:param tickDelay: `int`
|
||||
执行延时
|
||||
:param customName: `str`
|
||||
悬浮字
|
||||
lastOutput: `str`
|
||||
上次输出字符串,注意此处需要留空
|
||||
:param executeOnFirstTick: `bool`
|
||||
首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行)
|
||||
:param trackOutput: `bool`
|
||||
是否输出
|
||||
|
||||
:return:str
|
||||
"""
|
||||
block = b"\x24" + particularValue.to_bytes(2, byteorder="big", signed=False)
|
||||
|
||||
for i in [
|
||||
impluse.to_bytes(4, byteorder="big", signed=False),
|
||||
bytes(command, encoding="utf-8") + b"\x00",
|
||||
bytes(customName, encoding="utf-8") + b"\x00",
|
||||
bytes("", encoding="utf-8") + b"\x00",
|
||||
tickDelay.to_bytes(4, byteorder="big", signed=True),
|
||||
executeOnFirstTick.to_bytes(1, byteorder="big"),
|
||||
trackOutput.to_bytes(1, byteorder="big"),
|
||||
condition.to_bytes(1, byteorder="big"),
|
||||
needRedstone.to_bytes(1, byteorder="big"),
|
||||
]:
|
||||
block += i
|
||||
return block
|
||||
|
||||
|
||||
def bottem_side_length_of_smallest_square_bottom_box(total: int, maxHeight: int):
|
||||
"""给定总方块数量和最大高度,返回所构成的图形外切正方形的边长
|
||||
:param total: 总方块数量
|
||||
:param maxHeight: 最大高度
|
||||
:return: 外切正方形的边长 int"""
|
||||
return math.ceil(math.sqrt(math.ceil(total / maxHeight)))
|
||||
|
||||
|
||||
def commands_to_BDX_bytes(
|
||||
commands: list,
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
:param commands: 指令列表(指令, 延迟)
|
||||
:param max_height: 生成结构最大高度
|
||||
:return 成功与否,成功返回(True,未经过压缩的源,结构占用大小),失败返回(False,str失败原因)
|
||||
"""
|
||||
|
||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||
len(commands), max_height
|
||||
)
|
||||
_bytes = b""
|
||||
|
||||
y_forward = True
|
||||
z_forward = True
|
||||
|
||||
now_y = 0
|
||||
now_z = 0
|
||||
now_x = 0
|
||||
|
||||
for cmd, delay in commands:
|
||||
impluse = 2
|
||||
condition = False
|
||||
needRedstone = False
|
||||
tickDelay = delay
|
||||
customName = ""
|
||||
executeOnFirstTick = False
|
||||
trackOutput = True
|
||||
_bytes += form_command_block_in_BDX_bytes(
|
||||
cmd,
|
||||
(1 if y_forward else 0)
|
||||
if (
|
||||
((now_y != 0) and (not y_forward))
|
||||
or (y_forward and (now_y != (max_height - 1)))
|
||||
)
|
||||
else (3 if z_forward else 2)
|
||||
if (
|
||||
((now_z != 0) and (not z_forward))
|
||||
or (z_forward and (now_z != _sideLength - 1))
|
||||
)
|
||||
else 5,
|
||||
impluse=impluse,
|
||||
condition=condition,
|
||||
needRedstone=needRedstone,
|
||||
tickDelay=tickDelay,
|
||||
customName=customName,
|
||||
executeOnFirstTick=executeOnFirstTick,
|
||||
trackOutput=trackOutput,
|
||||
)
|
||||
|
||||
now_y += 1 if y_forward else -1
|
||||
|
||||
if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)):
|
||||
now_y -= 1 if y_forward else -1
|
||||
|
||||
y_forward = not y_forward
|
||||
|
||||
now_z += 1 if z_forward else -1
|
||||
|
||||
if ((now_z >= _sideLength) and z_forward) or (
|
||||
(now_z < 0) and (not z_forward)
|
||||
):
|
||||
now_z -= 1 if z_forward else -1
|
||||
z_forward = not z_forward
|
||||
_bytes += bdx_key[x][1]
|
||||
now_x += 1
|
||||
else:
|
||||
_bytes += bdx_key[z][int(z_forward)]
|
||||
|
||||
else:
|
||||
_bytes += bdx_key[y][int(y_forward)]
|
||||
|
||||
return (
|
||||
_bytes,
|
||||
[
|
||||
now_x + 1,
|
||||
max_height if now_x or now_z else now_y,
|
||||
_sideLength if now_x else now_z,
|
||||
],
|
||||
[now_x, now_y, now_z],
|
||||
)
|
||||
|
||||
|
||||
def form_note_block_in_NBT_struct(
|
||||
note: int, coordinate: tuple, instrument: str = "note.harp", powered: bool = False
|
||||
):
|
||||
"""生成音符盒方块
|
||||
:param note: `int`(0~24)
|
||||
音符的音高
|
||||
:param coordinate: `tuple[int,int,int]`
|
||||
此方块所在之相对坐标
|
||||
:param instrument: `str`
|
||||
音符盒的乐器
|
||||
:param powered: `bool`
|
||||
是否已被激活
|
||||
:return Block
|
||||
"""
|
||||
|
||||
from TrimMCStruct import Block, TAG_Byte
|
||||
return Block(
|
||||
"minecraft",
|
||||
"noteblock",
|
||||
{
|
||||
"instrument": instrument.replace("note.", ""),
|
||||
"note": note,
|
||||
"powered": powered,
|
||||
},
|
||||
{
|
||||
"block_entity_data": {
|
||||
"note": TAG_Byte(note),
|
||||
"id": "noteblock",
|
||||
"x": coordinate[0],
|
||||
"y": coordinate[1],
|
||||
"z": coordinate[2],
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def form_repeater_in_NBT_struct(
|
||||
delay: int, facing: int
|
||||
):
|
||||
"""生成中继器方块
|
||||
:param facing:
|
||||
:param delay: 1~4
|
||||
:return Block()"""
|
||||
|
||||
from TrimMCStruct import Block
|
||||
|
||||
return Block(
|
||||
"minecraft",
|
||||
"unpowered_repeater",
|
||||
{
|
||||
"repeater_delay": delay,
|
||||
"direction": facing,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def form_command_block_in_NBT_struct(
|
||||
command: str,
|
||||
coordinate: tuple,
|
||||
particularValue: int,
|
||||
impluse: int = 0,
|
||||
condition: bool = False,
|
||||
alwaysRun: bool = True,
|
||||
tickDelay: int = 0,
|
||||
customName: str = "",
|
||||
executeOnFirstTick: bool = False,
|
||||
trackOutput: bool = True,
|
||||
):
|
||||
"""
|
||||
使用指定项目返回指定的指令方块结构
|
||||
:param command: `str`
|
||||
指令
|
||||
:param coordinate: `tuple[int,int,int]`
|
||||
此方块所在之相对坐标
|
||||
:param particularValue:
|
||||
方块特殊值,即朝向
|
||||
:0 下 无条件
|
||||
:1 上 无条件
|
||||
:2 z轴负方向 无条件
|
||||
:3 z轴正方向 无条件
|
||||
:4 x轴负方向 无条件
|
||||
:5 x轴正方向 无条件
|
||||
:6 下 无条件
|
||||
:7 下 无条件
|
||||
|
||||
:8 下 有条件
|
||||
:9 上 有条件
|
||||
:10 z轴负方向 有条件
|
||||
:11 z轴正方向 有条件
|
||||
:12 x轴负方向 有条件
|
||||
:13 x轴正方向 有条件
|
||||
:14 下 有条件
|
||||
:14 下 有条件
|
||||
注意!此处特殊值中的条件会被下面condition参数覆写
|
||||
:param impluse: `int 0|1|2`
|
||||
方块类型
|
||||
0脉冲 1循环 2连锁
|
||||
:param condition: `bool`
|
||||
是否有条件
|
||||
:param alwaysRun: `bool`
|
||||
是否始终执行
|
||||
:param tickDelay: `int`
|
||||
执行延时
|
||||
:param customName: `str`
|
||||
悬浮字
|
||||
:param executeOnFirstTick: `bool`
|
||||
首刻执行(循环指令方块是否激活后立即执行,若为False,则从激活时起延迟后第一次执行)
|
||||
:param trackOutput: `bool`
|
||||
是否输出
|
||||
|
||||
:return:str
|
||||
"""
|
||||
|
||||
from TrimMCStruct import Block, TAG_Long
|
||||
|
||||
return Block(
|
||||
"minecraft",
|
||||
"command_block"
|
||||
if impluse == 0
|
||||
else ("repeating_command_block" if impluse == 1 else "chain_command_block"),
|
||||
states={"conditional_bit": condition, "facing_direction": particularValue},
|
||||
extra_data={
|
||||
"block_entity_data": {
|
||||
"Command": command,
|
||||
"CustomName": customName,
|
||||
"ExecuteOnFirstTick": executeOnFirstTick,
|
||||
"LPCommandMode": 0,
|
||||
"LPCondionalMode": False,
|
||||
"LPRedstoneMode": False,
|
||||
"LastExecution": TAG_Long(0),
|
||||
"LastOutput": "",
|
||||
"LastOutputParams": [],
|
||||
"SuccessCount": 0,
|
||||
"TickDelay": tickDelay,
|
||||
"TrackOutput": trackOutput,
|
||||
"Version": 25,
|
||||
"auto": alwaysRun,
|
||||
"conditionMet": False, # 是否已经满足条件
|
||||
"conditionalMode": condition,
|
||||
"id": "CommandBlock",
|
||||
"isMovable": True,
|
||||
"powered": False, # 是否已激活
|
||||
"x": coordinate[0],
|
||||
"y": coordinate[1],
|
||||
"z": coordinate[2],
|
||||
}
|
||||
},
|
||||
compability_version=17959425,
|
||||
)
|
||||
|
||||
|
||||
def commands_to_structure(
|
||||
commands: list,
|
||||
max_height: int = 64,
|
||||
):
|
||||
"""
|
||||
:param commands: 指令列表(指令, 延迟)
|
||||
:param max_height: 生成结构最大高度
|
||||
:return 成功与否,成功返回(结构类,结构占用大小),失败返回(False,str失败原因)
|
||||
"""
|
||||
|
||||
from TrimMCStruct import Structure
|
||||
|
||||
_sideLength = bottem_side_length_of_smallest_square_bottom_box(
|
||||
len(commands), max_height
|
||||
)
|
||||
|
||||
struct = Structure(
|
||||
(_sideLength, max_height, _sideLength), # 声明结构大小
|
||||
)
|
||||
|
||||
y_forward = True
|
||||
z_forward = True
|
||||
|
||||
now_y = 0
|
||||
now_z = 0
|
||||
now_x = 0
|
||||
|
||||
for cmd, delay in commands:
|
||||
coordinate = (now_x, now_y, now_z)
|
||||
struct.set_block(
|
||||
coordinate,
|
||||
form_command_block_in_NBT_struct(
|
||||
command=cmd,
|
||||
coordinate=coordinate,
|
||||
particularValue=(1 if y_forward else 0)
|
||||
if (
|
||||
((now_y != 0) and (not y_forward))
|
||||
or (y_forward and (now_y != (max_height - 1)))
|
||||
)
|
||||
else (
|
||||
(3 if z_forward else 2)
|
||||
if (
|
||||
((now_z != 0) and (not z_forward))
|
||||
or (z_forward and (now_z != _sideLength - 1))
|
||||
)
|
||||
else 5
|
||||
),
|
||||
impluse=2,
|
||||
condition=False,
|
||||
alwaysRun=True,
|
||||
tickDelay=delay,
|
||||
customName="",
|
||||
executeOnFirstTick=False,
|
||||
trackOutput=True,
|
||||
),
|
||||
)
|
||||
|
||||
now_y += 1 if y_forward else -1
|
||||
|
||||
if ((now_y >= max_height) and y_forward) or ((now_y < 0) and (not y_forward)):
|
||||
now_y -= 1 if y_forward else -1
|
||||
|
||||
y_forward = not y_forward
|
||||
|
||||
now_z += 1 if z_forward else -1
|
||||
|
||||
if ((now_z >= _sideLength) and z_forward) or (
|
||||
(now_z < 0) and (not z_forward)
|
||||
):
|
||||
now_z -= 1 if z_forward else -1
|
||||
z_forward = not z_forward
|
||||
now_x += 1
|
||||
|
||||
return (
|
||||
struct,
|
||||
(
|
||||
now_x + 1,
|
||||
max_height if now_x or now_z else now_y,
|
||||
_sideLength if now_x else now_z,
|
||||
),
|
||||
(now_x, now_y, now_z),
|
||||
)
|
||||
@@ -1,18 +1,133 @@
|
||||
# 请注意
|
||||
***NOTICE***
|
||||
|
||||
|
||||
## 请不要在此处编辑
|
||||
|
||||
***NEVER NEVER EDIT FILES IN THIS REPOSITORY on GITHUB***
|
||||
|
||||
> 此仓库中的编辑信息会被 Gitee 的更新覆盖,您在此做出的更改皆无效
|
||||
> **Editions in *this repo(on GitHub)* will all be covered by the ones on Gitee so it's a MUST NOT to edit this *on GitHub***
|
||||
|
||||
### 若依旧需要在此仓库内查看代码,请前往 `master` 分支,谢谢~
|
||||
**If you really want to view codes in this repository on Github, you can get them in `master` branch.**
|
||||
|
||||
若欲加入开发,请联系[睿乐组织](mailto:TriM-Organization@hotmail.com)或者看一看[Gitee上的音·创](https://gitee.com/EillesWan/Musicreater/)
|
||||
IF YOU WANT TO TAKE PART IN THE DEVELOPMENT OF *Musicreater* , PLEASE CONTACT [TriM Org.](mailto:TriM-Organization@hotmail.com),
|
||||
or you can see [Musicreater on Gitee](https://gitee.com/EillesWan/Musicreater/)
|
||||
|
||||
|
||||
<h1 align="center">
|
||||
音·创 Musicreater
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<img width="128" height="128" src="https://gitee.com/TriM-Organization/Musicreater/raw/master/resources/msctIcon.ico">
|
||||
</img>
|
||||
</p>
|
||||
|
||||
<h3 align="center">一款免费开源的 《我的世界》 MIDI音乐转换库。</h3>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
||||
<a href='https://gitee.com/TriM-Organization/Musicreater'>
|
||||
<img align="right" src='https://gitee.com/TriM-Organization/Musicreater/widgets/widget_1.svg' alt='Fork me on Gitee'>
|
||||
</img>
|
||||
</a>
|
||||
<p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[![][Bilibili: 金羿ELS]](https://space.bilibili.com/397369002/)
|
||||
[![][Bilibili: 诸葛亮与八卦阵]](https://space.bilibili.com/604072474)
|
||||
[![CodeStyle: black]](https://github.com/psf/black)
|
||||
[![][python]](https://www.python.org/)
|
||||
[![][license]](LICENSE)
|
||||
[![][release]](../../releases)
|
||||
|
||||
[](https://gitee.com/TriM-Organization/Musicreater/stargazers)
|
||||
[](https://gitee.com/TriM-Organization/Musicreater/members)
|
||||
[](https://github.com/TriM-Organization/Musicreater/stargazers)
|
||||
[](https://github.com/TriM-Organization/Musicreater/forks)
|
||||
|
||||
|
||||
简体中文🇨🇳 | [English🇬🇧](README_EN.md)
|
||||
|
||||
|
||||
## 介绍🚀
|
||||
|
||||
音·创 是一个免费开源的针对 **《我的世界》** 的MIDI音乐转换库
|
||||
|
||||
欢迎加群:[861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
|
||||
|
||||
## 下载安装
|
||||
|
||||
- 使用pypi
|
||||
```bash
|
||||
pip install Musicreater
|
||||
```
|
||||
|
||||
- 如果出现错误,可以尝试:
|
||||
```bash
|
||||
pip install -i https://pypi.python.org/simple Musicreater
|
||||
```
|
||||
- (对于开发者来说)升级:
|
||||
```bash
|
||||
pip install -i https://pypi.python.org/simple Musicreater --upgrade
|
||||
```
|
||||
|
||||
- 克隆仓库并安装
|
||||
```bash
|
||||
git clone https://gitee.com/TriM-Organization/Musicreater.git
|
||||
cd Musicreater
|
||||
python setup.py install
|
||||
```
|
||||
|
||||
以上命令种 `python`、`pip` 请依照各个环境不同灵活更换,可能为`python3`或`pip3`之类。
|
||||
|
||||
## 文档📄
|
||||
|
||||
[生成文件的使用](./docs/%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)
|
||||
|
||||
[仓库API文档](./docs/%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md)
|
||||
|
||||
## 作者✒
|
||||
|
||||
金羿 Eilles:我的世界基岩版指令师,个人开发者,B站不知名UP主,江西在校高中生。
|
||||
|
||||
诸葛亮与八卦阵 bgArray:我的世界基岩版玩家,喜欢编程和音乐,深圳初二学生。
|
||||
|
||||
## 致谢🙏
|
||||
本致谢列表排名无顺序。
|
||||
|
||||
- 感谢 **昀梦**\<QQ1515399885\> 找出指令生成错误bug并指正
|
||||
- 感谢由 **Charlie_Ping “查理平”** 带来的BDX文件转换参考,以及MIDI-我的世界对应乐器参考表格
|
||||
- 感谢由 **[CMA_2401PT](https://github.com/CMA2401PT)** 为我们的软件开发的一些方面进行指导,同时我们参考了他的BDXworkshop作为BDX结构编辑的参考
|
||||
- 感谢由 **[Dislink Sforza](https://github.com/Dislink) “断联·斯福尔扎”**\<QQ1600515314\> 带来的midi音色解析以及转换指令的算法,我们将其改编并应用;同时,感谢他的[网页版转换器](https://dislink.github.io/midi2bdx/)给我们的开发与更新带来巨大的压力和动力,让我们在原本一骑绝尘的摸鱼道路上转向开发,希望他能考上一个理想的大学!
|
||||
- 感谢 **Touch “偷吃”**\<QQ1793537164\> 提供的BDX导入测试支持,并对程序的改进提供了丰富的意见;同时也感谢他的不断尝试新的内容,使我们的排错更进一步
|
||||
- 感谢 **Mono**\<QQ738893087\> 反馈安装时的问题,辅助我们找到了视窗操作系统下的兼容性问题;感谢其反馈延迟播放器出现的重大问题,让我们得以修改全部延迟播放错误
|
||||
- 感谢 **Ammelia “艾米利亚”**\<QQ2838334637\> 敦促我们进行新的功能开发,并为新功能提出了非常优秀的大量建议,以及提供的BDX导入测试支持,为我们的新结构生成算法提供了大量的实际理论支持
|
||||
- 感谢 **[神羽](https://gitee.com/snowykami) “[SnowyKami](https://github.com/snowyfirefly)”** 对我们项目的支持与宣传,希望他能考的一所优秀的大学!
|
||||
- 感谢 **指令师_苦力怕 playjuice123**\<QQ240667197\>为我们的程序找出错误,并提醒我们修复一个一直存在的大bug。
|
||||
- 感谢 **雷霆**\<QQ3555268519\>为我们的程序找出错误,并提醒修复bug。
|
||||
|
||||
> 感谢广大群友为此程序提供的测试等支持
|
||||
>
|
||||
> 若您对我们有所贡献但您的名字没有显示在此列表中,请联系我们!
|
||||
|
||||
## 联系📞
|
||||
|
||||
若遇到库中的问题,欢迎在[此](https://gitee.com/TriM-Organization/Musicreater/issues/new)提出你的issue。
|
||||
|
||||
如果需要与开发组进行交流,欢迎加入我们的[开发闲聊Q群](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)。
|
||||
|
||||
--------------------------------------------
|
||||
|
||||
此项目并非一个官方 《我的世界》(*Minecraft*)项目
|
||||
|
||||
此项目不隶属或关联于 Mojang Studios 或 微软
|
||||
|
||||
此项目亦不与 网易 相关
|
||||
|
||||
“Minecraft”是 Mojang Synergies AB 的商标,此项目中所有对于“我的世界”、“Minecraft”等相关称呼均为引用性使用
|
||||
|
||||
* 上文提及的 网易 公司,指代的是在中国大陆运营《我的世界:中国版》的上海网之易网络科技发展有限公司
|
||||
|
||||
NOT AN OFFICIAL MINECRAFT PRODUCT.
|
||||
|
||||
NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[Bilibili: 金羿ELS]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
|
||||
[Bilibili: 诸葛亮与八卦阵]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
|
||||
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge
|
||||
[python]: https://img.shields.io/badge/python-3.8-AB70FF?style=for-the-badge
|
||||
[release]: https://img.shields.io/github/v/release/EillesWan/Musicreater?style=for-the-badge
|
||||
[license]: https://img.shields.io/badge/Licence-Apache-228B22?style=for-the-badge
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<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>
|
||||
|
||||
<h3 align="center">a free open-source library of converting midi files into _Minecraft_ formats.</h3>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
||||
<p>
|
||||
|
||||
[![][Bilibili: Eilles]](https://space.bilibili.com/397369002/)
|
||||
[![][Bilibili: bgArray]](https://space.bilibili.com/604072474)
|
||||
[![CodeStyle: black]](https://github.com/psf/black)
|
||||
![][python]
|
||||
[![][license]](LICENSE)
|
||||
[![][release]](../../releases)
|
||||
|
||||
[简体中文🇨🇳](README.md) | English🇬🇧
|
||||
|
||||
**Notice that the language translation of *Musicreater* may be a little SLOW.**
|
||||
|
||||
## Introduction🚀
|
||||
|
||||
Musicreater is a free open-source library used for converting midi file into formats that could be read in *Minecraft*.
|
||||
|
||||
Welcome to join our QQ group: [861684859](https://jq.qq.com/?_wv=1027&k=hpeRxrYr)
|
||||
|
||||
## Documentation📄
|
||||
|
||||
(Not in English yet)
|
||||
|
||||
[生成文件的使用](./docs/%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)
|
||||
|
||||
[仓库API文档](./docs/%E5%BA%93%E7%9A%84%E7%94%9F%E6%88%90%E4%B8%8E%E5%8A%9F%E8%83%BD%E6%96%87%E6%A1%A3.md)
|
||||
|
||||
### Authors✒
|
||||
|
||||
Eilles (金羿):A senior high school student, individual developer, unfamous Bilibili UPer, which knows a little about commands in *Minecraft: Bedrock Edition*
|
||||
|
||||
bgArray "诸葛亮与八卦阵": A junior high school student, player of *Minecraft: Bedrock Edition*, which is a fan of music and programming.
|
||||
|
||||
|
||||
## Thanks🙏
|
||||
This list is not in any order.
|
||||
|
||||
- Thank *昀梦*\<QQ1515399885\> for finding and correcting the bugs in the commands that *Musicreater* generated.
|
||||
- Thank *Charlie_Ping “查理平”* for bdx convert function for reference, and the chart that's used to convert the mid's instruments into Minecraft's instruments.
|
||||
- Thank *[CMA_2401PT](https://github.com/CMA2401PT)* for BDXWorkShop for reference of the .bdx structure's operation, and his guidance in some aspects of our development.
|
||||
- Thank *[Dislink Sforza](https://github.com/Dislink) “断联·斯福尔扎”* \<QQ1600515314\> for his midi analysis algorithm brought to us, we had adapted it and made it applied in one of our working method; Also, thank him for the [WebConvertor](https://dislink.github.io/midi2bdx/) which brought us so much pressure and power to develop as well as update our projects better, instead of loaf on our project. We hope he can get into a good university as he wantted to!
|
||||
- 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
|
||||
- Thank *Ammelia “艾米利亚”*\<QQ2838334637\> for urging us to develop new functions, and put forward a lot of excellent suggestions for new functions, as well as the BDX file's importing test support provided, which has given a lot of practical theoretical support for our new Structure Generating Algorithm
|
||||
- 感谢 *[神羽](https://gitee.com/snowykami) “[SnowyKami](https://github.com/snowyfirefly)”* for supporting and promoting our project
|
||||
|
||||
> Thanks for a lot of groupmates's support and help
|
||||
>
|
||||
> If you have given contribution but haven't been in the list, please contact us!
|
||||
|
||||
## Contact Us📞
|
||||
|
||||
Meet problems? Welcome to give out your issue [here](https://gitee.com/EillesWan/Musicreater/issues/new)!
|
||||
|
||||
Want to get in contact of developers? Welcome to join our [Chat QQ group](https://jq.qq.com/?_wv=1027&k=hpeRxrYr).
|
||||
|
||||
|
||||
--------------------------------------------
|
||||
|
||||
NOT AN OFFICIAL MINECRAFT PRODUCT.
|
||||
|
||||
NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.
|
||||
|
||||
此项目并非一个官方 《我的世界》(*Minecraft*)项目
|
||||
|
||||
此项目不隶属或关联于 Mojang Studios 或 微软
|
||||
|
||||
|
||||
|
||||
|
||||
[Bilibili: Eilles]: https://img.shields.io/badge/Bilibili-%E5%87%8C%E4%BA%91%E9%87%91%E7%BE%BF-00A1E7?style=for-the-badge
|
||||
[Bilibili: bgArray]: https://img.shields.io/badge/Bilibili-%E8%AF%B8%E8%91%9B%E4%BA%AE%E4%B8%8E%E5%85%AB%E5%8D%A6%E9%98%B5-00A1E7?style=for-the-badge
|
||||
[CodeStyle: black]: https://img.shields.io/badge/code%20style-black-121110.svg?style=for-the-badge
|
||||
[python]: https://img.shields.io/badge/python-3.6-AB70FF?style=for-the-badge
|
||||
[release]: https://img.shields.io/github/v/release/EillesWan/Musicreater?style=for-the-badge
|
||||
[license]: https://img.shields.io/badge/Licence-Apache-228B22?style=for-the-badge
|
||||
@@ -0,0 +1,22 @@
|
||||
import shutil
|
||||
import os
|
||||
from rich.console import Console
|
||||
from rich.progress import track
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def main():
|
||||
with console.status("Find the full path of .egg-info folder"):
|
||||
egg_info: list = []
|
||||
for file in os.listdir():
|
||||
if file.endswith(".egg-info"):
|
||||
egg_info.append(file)
|
||||
console.print(file)
|
||||
for file in track(["build", "dist", "logs", *egg_info], description="Deleting files"):
|
||||
if os.path.isdir(file) and os.access(file, os.W_OK):
|
||||
shutil.rmtree(file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,204 @@
|
||||
<h1 align="center">音·创 Musicreater</h1>
|
||||
|
||||
<h2 align="center">库版 Package Version</h2>
|
||||
|
||||
<p align="center">
|
||||
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
|
||||
</p>
|
||||
|
||||
**此为开发相关文档,内容包括:所生成文件结构的详细说明、特殊参数的详细解释**
|
||||
|
||||
# 库的简单调用
|
||||
|
||||
参见[example.py的相关部分](../example.py#L120),使用此库进行MIDI转换非常简单。
|
||||
|
||||
```python
|
||||
import Musicreater # 导入转换库
|
||||
|
||||
old_execute_format = False # 指定是否使用旧的execute指令语法(即1.18及以前的《我的世界:基岩版》语法)
|
||||
|
||||
# 首先新建转换对象。
|
||||
conversion = Musicreater.midiConvert(enable_old_exe_format = old_execute_format)
|
||||
# 值得注意的是,一个转换对象可以转换多个文件。
|
||||
# 也就是在实例化的时候不进行对文件的绑定。
|
||||
# 如果有调试需要,可以在实例化时传入参数 debug = True
|
||||
# 如:conversion = Musicreater.midiConvert(debug=True)
|
||||
|
||||
# 设置输入输出地址,并指定execute指令语法
|
||||
# 地址都为字符串类型,不能传入文件流
|
||||
midi_path = "./where/you/place/.midi/files.mid"
|
||||
output_folder = "./where/you/want2/convert/into/"
|
||||
|
||||
# 设定基本转换参数
|
||||
conversion.convert(midi_path,output_folder)
|
||||
|
||||
# 进行转换并接受输出,具体的参数均在代码之文档中有相关说明
|
||||
method_id = 3 # 指定使用的转换算法
|
||||
|
||||
# 使用计分板播放器,转换为附加包文件
|
||||
convertion_result = conversion.to_mcpack(method_id,*prompts)
|
||||
|
||||
# 使用延迟播放器,转换为附加包文件
|
||||
# 注意,在执行这个功能之前,你需要使用指令
|
||||
# pip install TrimMCStruct
|
||||
# 安装最新版的TrimMCStruct库
|
||||
convertion_result = conversion.to_mcpack_with_delay(method_id,*prompts)
|
||||
|
||||
# 使用计分板播放器,转换为BDX结构文件
|
||||
convertion_result = conversion.to_BDX_file(method_id,*prompts)
|
||||
|
||||
# 使用延迟播放器,转换为BDX结构文件
|
||||
convertion_result = conversion.to_BDX_file_with_delay(method_id,*prompts)
|
||||
|
||||
# 转换结果是一个元组。
|
||||
# 若其转换成功,则前三位必为
|
||||
# True, 指令数量, 最大延迟
|
||||
# 其中,最大延迟可以理解为计分板的最大值
|
||||
# 如果转换失败,暂时还没有定返回值的规则
|
||||
# 但是有一点是肯定的,数据结构必定是元组
|
||||
print(convertion_result)
|
||||
```
|
||||
|
||||
|
||||
# 生成文件结构
|
||||
|
||||
## 名词解释
|
||||
|
||||
|名词|解释|备注|
|
||||
|--------|-----------|----------|
|
||||
|指令区|一个用于放置指令系统的区域,通常是常加载区。|常见于服务器指令系统、好友联机房间中|
|
||||
|指令链(链)|与链式指令方块不同,一个指令链通常指代的是一串由某种非链式指令方块作为开头,后面连着一串链式指令方块的结构。|通常的链都应用于需要“单次激活而多指令”的简单功能|
|
||||
|起始块|链最初的那个非链式指令方块。|此方块为脉冲方块或重复方块皆可|
|
||||
|指令系统(系统)|指令系统通常指的是,由一个或多个指令链以及相关红石机构相互配合、一同组成的,为达到某种特定的功能而构建的整体结构。|通常的系统都应用于需要“综合调配指令”的复杂功能。可由多个实现不同功能的模块构成,不同系统之间可以相互调用各自的模块。|
|
||||
|游戏刻(刻)|游戏的一刻是指《我的世界》的游戏循环运行一次所占用的时间。([详见《我的世界》中文维基](https://minecraft.fandom.com/zh/wiki/%E5%88%BB#%E6%B8%B8%E6%88%8F%E5%88%BB))。指令方块的延迟功能(即指令方块的“延迟刻数”设置项,此项的名称被误译为“已选中项的延迟”)的单位即为`1`游戏刻。|正常情况下,游戏固定以每秒钟20刻的速率运行。但是,由于游戏内的绝大多数操作都是基于刻数而非现实中的时间来计时并进行的,一次游戏循环内也许会发生大量的操作,很多情况下,一秒对应的游戏刻会更少。 |
|
||||
|
||||
## 文件格式
|
||||
|
||||
1. 附加包格式(`.mcpack`)
|
||||
|
||||
使用附加包格式导出音乐,则音乐会以指令函数文件(`.mcfunction`)存储于附加包内。在附加包中,函数文件的存储结构应为:
|
||||
|
||||
- `functions\`
|
||||
- `index.mcfunction`
|
||||
- `mscply\`
|
||||
- `progressShow.mcfunction`
|
||||
- `track1.mcfunction`
|
||||
- `track2.mcfunction`
|
||||
- ...
|
||||
- `trackN.mcfunction`
|
||||
|
||||
如图,其中,`index.mcfunction`文件和`mscply`文件夹存在于函数目录的根下;在`mscply`目录中,包含音乐导出的众多音轨播放文件(`trackX.mcfunction`),同时,若生成此包时选择了带有进度条的选项,则会包含`progressShow.mcfunction`文件。
|
||||
|
||||
`index.mcfunction`用于开始播放,其中包含打开各个音轨对应函数的指令,以及加分指令,这里的加分,是将**播放计分板的值大于等于`1`**的所有**玩家**的播放计分板分数增加`1`。同时,若生成此包时选择了自动重置计分板的选项,则会包含一条重置计分板的指令。
|
||||
|
||||
> 你知道吗?音·创的最早期版本“《我的世界》函数音乐生成器”正是用函数来播放,不过这个版本采取的读入数据的形式大有不同。
|
||||
|
||||
2. 结构格式
|
||||
|
||||
无论是音·创生成的是何种结构,`MCSTRUCTURE`还是`BDX`,都会依照此处的格式来生成。此处我们想说明的结构的格式不是结构文件存储的格式,而是结构导出之后方块将如何摆放的问题。结构文件存储的格式这一点,在各个《我的世界》开发的相关网站上都可能会有说明。
|
||||
|
||||
考虑到进行《我的世界》游戏开发时,为了节约常加载区域,很多游戏会将指令区设立为一种层叠式的结构。这种结构会限制每一层的指令系统的高度,但是虽然长宽也是有限的,却仍然比其纵轴延伸得更加自由。
|
||||
|
||||
所以,结构的生成形状依照给定的高度和内含指令的数量决定。其 $Z$ 轴延伸长度为指令方块数量对于给定高度之商的向下取整结果的平方根的向下取整。用数学公式的方式表达,则是:
|
||||
|
||||
$$MaxZ = \left\lfloor\sqrt{\left\lfloor{\frac{NoC}{MaxH}}\right\rfloor}\right\rfloor$$
|
||||
|
||||
其中,$MaxZ$即生成结构的$Z$轴最大延伸长度,$NoC$表示链结构中所含指令方块的个数,$MaxH$表示给定的生成结构的最大高度。
|
||||
|
||||
我们的结构生成器在生成指令链时,将首先以相对坐标系 $(0, 0, 0)$ (即相对原点)开始,自下向上堆叠高度轴(即 $Y$ 轴)的长,当高度轴达到了限制的高度时,便将 $Z$ 轴向正方向堆叠`1`个方块,并开始自上向下重新堆叠,直至高度轴坐标达到相对为`0`。若当所生成结构的 $Z$ 轴长达到了其最大延伸长度,则此结构生成器将反转 $Z$ 轴的堆叠方向,直至 $Z$ 轴坐标相对为`0`。如此往复,直至指令链堆叠完成。
|
||||
|
||||
## 播放器
|
||||
|
||||
以结构生成的文件可以采用多种方式播放,一类播放方式,我们称其为**播放器**,例如**延迟播放器**和**计分板播放器**等等,以后推出的新的播放器,届时也会在此处更新。
|
||||
|
||||
为什么要设计这么多播放器?是为了适应不同的播放环境需要。通常情况下,一个音乐中含有多个音符,音符与音符之间存在间隔,这里就产生了不一样的,实现音符间时间间隔的方式。而不同的应用环境下,又会产生不一样的要求。接下来将对不同的播放器进行详细介绍。
|
||||
|
||||
1. 计分板播放器
|
||||
|
||||
计分板播放器是一种传统的《我的世界》音乐播放方式。通过对于计分板加分来实现播放不同的音符。一个很简单的原理,就是**用不同的计分板分值对应不同的音符**,再通过加分,来达到那个分值,即播放出来。
|
||||
|
||||
在**音·创**中,用来达到这种效果的指令是这样的:
|
||||
|
||||
```mcfunction
|
||||
execute @a[scores={ScBd=x}] ~ ~ ~ playsound InstID @s ~ ~Ht ~ Vlct Ptc
|
||||
```
|
||||
|
||||
|参数|说明|备注|
|
||||
|--------|-----------|----------|
|
||||
|`ScBd`|指定的计分板名称||
|
||||
|`x`|音发出时对应的分数值||
|
||||
|`InstID`|声音效果ID|不同的声音ID可以对应不同的乐器,详见转换[乐器对照表](./%E8%BD%AC%E6%8D%A2%E4%B9%90%E5%99%A8%E5%AF%B9%E7%85%A7%E8%A1%A8.md)|
|
||||
|`Ht`|播放点对玩家的距离|通过距离来表达声音的响度。以 $S$ 表示此参数`Ht`,以Vol表示音量百分比,则计算公式为: $S = \frac{1}{Vol}-1$ |
|
||||
|`Vlct`|原生我的世界中规定的播放力度|这个参数是一个谜一样的存在,似乎它的值毫不重要……因为无论这个值是多少,我们听起来都差不多。当此音符所在MIDI通道为第一通道,则这个值为0.7倍MIDI指定力度,其他则为0.9倍。|
|
||||
|`Ptc`|音符的音高|这是决定音调的参数。以 $P$ 表示此参数, $n$ 表示其在MIDI中的编号, $x$ 表示一定的音域偏移,则计算公式为: $P = 2^\frac{n-60-x}{12}$ |
|
||||
|
||||
后四个参数决定了这个音的性质,而前两个参数仅仅是为了决定音播放的时间。
|
||||
|
||||
2. 延迟播放器
|
||||
|
||||
延迟播放器是通过《我的世界》游戏中,指令方块的设置项“延迟刻数”来达到定位音符的效果。**将所有的音符依照其播放时距离乐曲开始时的时间(毫秒),放在一个序列内,再计算音符两两之间对应的时间差值,转换为《我的世界》内对应的游戏刻数之后填入指令方块的设置中。**
|
||||
|
||||
在音·创中,由于此方式播放的音乐不需要用计分板,所以播放指令是这样的:
|
||||
|
||||
```mcfunction
|
||||
execute Tg ~ ~ ~ playsound InstID @s ~ ~Ht ~ Vlct Ptc
|
||||
```
|
||||
|
||||
|参数|说明|备注|
|
||||
|--------|-----------|----------|
|
||||
|`Tg`|播放对象|选择器或玩家名|
|
||||
|`InstID`|声音效果ID|不同的声音ID可以对应不同的乐器,详见转换[乐器对照表](./%E8%BD%AC%E6%8D%A2%E4%B9%90%E5%99%A8%E5%AF%B9%E7%85%A7%E8%A1%A8.md)|
|
||||
|`Ht`|播放点对玩家的距离|通过距离来表达声音的响度。以 $S$ 表示此参数`Ht`,以Vol表示音量百分比,则计算公式为: $S = \frac{1}{Vol}-1$ |
|
||||
|`Vlct`|原生我的世界中规定的播放力度|这个参数是一个谜一样的存在,似乎它的值毫不重要……因为无论这个值是多少,我们听起来都差不多。当此音符所在MIDI通道为第一通道,则这个值为0.7倍MIDI指定力度,其他则为0.9倍。|
|
||||
|`Ptc`|音符的音高|这是决定音调的参数。以 $P$ 表示此参数, $n$ 表示其在MIDI中的编号,$x$表示一定的音域偏移,则计算公式为: $P = 2^\frac{n-60-x}{12}$ |
|
||||
|
||||
其中后四个参数决定了这个音的性质。
|
||||
|
||||
由于这样的延迟数据是依赖于指令方块的设置项,所以使用这种播放器所转换出的结果仅可以存储在包含方块NBT信息及方块实体NBT信息的结构文件中,或者直接输出至世界。
|
||||
|
||||
|
||||
|
||||
# 进度条自定义
|
||||
|
||||
因为我们提供了可以自动转换进度条的功能,因此在这里给出进度条自定义参数的详细解释。
|
||||
|
||||
请注意,并非所有的演示样例程序都支持自定义进度条。
|
||||
|
||||
一个进度条,明显地,有**固定部分**和**可变部分**来构成。而可变部分又包括了文字和图形两种(当然,《我的世界》里头的进度条,可变的图形也就是那个“条”了)。这一点你需要了解,因为后文中包含了很多这方面的概念需要你了解。
|
||||
|
||||
进度条的自定义功能使用一个字符串来定义自己的样式,其中包含众多**标识符**来表示可变部分。
|
||||
|
||||
标识符如下(注意大小写):
|
||||
|
||||
| 标识符 | 指定的可变量 |
|
||||
|---------|----------------|
|
||||
| `%%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'))`
|
||||
|
||||
*对了!为了避免生成错误,请尽量避免使用标识符作为定义样式字符串的其他部分*
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<h1 align="center">音·创 Musicreater</h1>
|
||||
|
||||
<h2 align="center">库版 Package Version</h2>
|
||||
|
||||
<p align="center">
|
||||
<img width="128" height="128" src="https://s1.ax1x.com/2022/05/06/Ouhghj.md.png" >
|
||||
</p>
|
||||
|
||||
# 生成文件的使用
|
||||
|
||||
*由于先前的 **读我文件**(README.md) 过于冗杂,现另辟蹊径来给大家全方位的教程。*
|
||||
|
||||
*这是本库所生成文件的使用声明,不是使用本库的教程,若要查看**本库的演示程序**使用教程,可点击[此处](%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md);若要查看有关文件结构的内容,可以点击[此处](./%E7%94%9F%E6%88%90%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E.md)*
|
||||
|
||||
## 附加包格式
|
||||
|
||||
支持的文件后缀:`.MCPACK`
|
||||
|
||||
1. 导入附加包
|
||||
2. 在一个循环方块中输入指令 `function index`
|
||||
3. 将需要聆听音乐的实体的播放所用计分板设置为 `1`
|
||||
4. 激活循环方块
|
||||
5. 若想要暂停播放,可以停止循环指令方块的激活状态
|
||||
6. 若想要重置某实体的播放,可以将其播放用的计分板重置
|
||||
|
||||
> 其中 步骤三 和 步骤四 的顺序可以调换。
|
||||
|
||||
## 结构格式
|
||||
|
||||
支持的文件后缀:`.MCSTRUCTURE`、`.BDX`
|
||||
|
||||
1. 将结构导入世界
|
||||
|
||||
- 延迟播放器
|
||||
|
||||
2. 将结构生成的第一个指令方块之模式更改为**脉冲**
|
||||
3. 激活脉冲方块
|
||||
4. 若欲重置播放,可以停止对此链的激活,例如停止区块加载
|
||||
5. 此播放器不支持暂停
|
||||
|
||||
- 计分板播放器
|
||||
|
||||
2. 在所生成的第一个指令方块前,放置一个循环指令方块,其朝向应当对着所生成的第一个方块
|
||||
3. 在循环指令方块中输入使播放对象的播放用计分板加分的指令,延迟为`0`,每次循环增加`1`分
|
||||
4. 激活循环方块
|
||||
5. 若想要暂停播放,可以停止循环指令方块的激活状态
|
||||
6. 若想要重置某实体的播放,可以将其播放用的计分板重置
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
# 暂无
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 伶伦 开发交流群 861684859
|
||||
|
||||
|
||||
"""
|
||||
音·创 (Musicreater) 演示程序
|
||||
是一款免费开源的针对《我的世界》的midi音乐转换库
|
||||
Musicreater (音·创)
|
||||
A free open source library used for convert midi file into formats that is suitable for **Minecraft**.
|
||||
|
||||
版权所有 © 2023 音·创 开发者
|
||||
Copyright © 2023 all the developers of Musicreater
|
||||
|
||||
开源相关声明请见 ./License.md
|
||||
Terms & Conditions: ./License.md
|
||||
"""
|
||||
|
||||
import os
|
||||
import Musicreater
|
||||
|
||||
|
||||
# 获取midi列表
|
||||
midi_path = input(f"请输入MIDI路径:")
|
||||
|
||||
|
||||
# 获取输出地址
|
||||
out_path = input(f"请输入输出路径:")
|
||||
|
||||
conversion = Musicreater.midiConvert()
|
||||
|
||||
|
||||
def isMethodOK(sth: str):
|
||||
if int(sth) in range(1, len(conversion.methods) + 1):
|
||||
return int(sth)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
|
||||
convert_method = int(input(f"请输入转换算法[1~{len(conversion.methods)}]:"))
|
||||
|
||||
# 选择输出格式
|
||||
fileFormat = int(input(f"请输入输出格式[BDX(1) 或 MCPACK(0)]:").lower())
|
||||
playerFormat = int(input(f"请选择播放方式[计分板(1) 或 延迟(0)]:").lower())
|
||||
|
||||
|
||||
# 真假字符串判断
|
||||
def bool_str(sth: str) -> bool:
|
||||
try:
|
||||
return bool(float(sth))
|
||||
except ValueError:
|
||||
if str(sth).lower() == "true":
|
||||
return True
|
||||
elif str(sth).lower() == "false":
|
||||
return False
|
||||
else:
|
||||
raise ValueError("布尔字符串啊?")
|
||||
|
||||
|
||||
debug = False
|
||||
|
||||
if os.path.exists("./demo_config.json"):
|
||||
import json
|
||||
|
||||
prompts = json.load(open("./demo_config.json", "r", encoding="utf-8"))
|
||||
if prompts[-1] == "debug":
|
||||
debug = True
|
||||
prompts = prompts[:-1]
|
||||
else:
|
||||
prompts = []
|
||||
# 提示语 检测函数 错误提示语
|
||||
for args in [
|
||||
(
|
||||
f"输入音量:",
|
||||
float,
|
||||
),
|
||||
(
|
||||
f"输入播放速度:",
|
||||
float,
|
||||
),
|
||||
(
|
||||
f"是否启用进度条:",
|
||||
bool_str,
|
||||
),
|
||||
(
|
||||
f"计分板名称:",
|
||||
str,
|
||||
)
|
||||
if playerFormat == 1
|
||||
else (
|
||||
f"玩家选择器:",
|
||||
str,
|
||||
),
|
||||
(
|
||||
f"是否自动重置计分板:",
|
||||
bool_str,
|
||||
)
|
||||
if playerFormat == 1
|
||||
else (),
|
||||
(
|
||||
f"作者名称:",
|
||||
str,
|
||||
)
|
||||
if fileFormat == 1
|
||||
else (),
|
||||
(
|
||||
f"最大结构高度:",
|
||||
int,
|
||||
)
|
||||
if fileFormat == 1
|
||||
else (),
|
||||
]:
|
||||
if args:
|
||||
prompts.append(args[1](input(args[0])))
|
||||
|
||||
conversion = Musicreater.midiConvert(debug=debug)
|
||||
|
||||
|
||||
print(f"正在处理 {midi_path} :")
|
||||
conversion.convert(midi_path, out_path)
|
||||
if debug:
|
||||
with open("./records.json", "a", encoding="utf-8") as f:
|
||||
json.dump(conversion.toDICT(), f)
|
||||
f.write(5 * "\n")
|
||||
conversion_result = (
|
||||
conversion.to_mcpack(convert_method, *prompts)
|
||||
if fileFormat == 0
|
||||
else (
|
||||
conversion.to_BDX_file(convert_method, *prompts)
|
||||
if playerFormat == 1
|
||||
else conversion.to_BDX_file_with_delay(convert_method, *prompts)
|
||||
)
|
||||
)
|
||||
|
||||
if conversion_result[0]:
|
||||
print(
|
||||
f" 指令总长:{conversion_result[1]},最高延迟:{conversion_result[2]}{f''',结构大小{conversion_result[3]},最末坐标{conversion_result[4]}''' if fileFormat == 1 else ''}"
|
||||
)
|
||||
else:
|
||||
print(f"失败:{conversion_result}")
|
||||
|
||||
exitSth = input("回车退出").lower()
|
||||
if exitSth == "record":
|
||||
import json
|
||||
|
||||
with open("./demo_config.json", "w", encoding="utf-8") as f:
|
||||
json.dump(prompts, f)
|
||||
elif exitSth == "delrec":
|
||||
os.remove("./demo_config.json")
|
||||
@@ -0,0 +1,8 @@
|
||||
from Musicreater import midiConvert
|
||||
|
||||
conversion = midiConvert(enable_old_exe_format=False)
|
||||
conversion.convert(input("midi路径:"), input("输出路径:"))
|
||||
|
||||
conversion.to_mcstructure_file_with_delay(
|
||||
3,
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
> 是谁把科技的领域布满政治的火药
|
||||
>
|
||||
> 是谁把纯净的蓝天染上暗淡的沉灰
|
||||
>
|
||||
> 中国人民无不热爱自己伟大的祖国
|
||||
>
|
||||
> 我们不会忘记屈辱历史留下的惨痛
|
||||
>
|
||||
> 我们希望世界和平
|
||||
>
|
||||
> 我们希望获得世界的尊重
|
||||
>
|
||||
> 愿世上再也没有战争
|
||||
>
|
||||
> 无论是热还是冷
|
||||
>
|
||||
> 无论是经济还是政治
|
||||
>
|
||||
> 让美妙的和平的优雅的音乐响彻世界
|
||||
>
|
||||
> ——金羿
|
||||
> 2022 5 7
|
||||
|
||||
|
||||
|
||||
> Who has dropped political gunpowder into the technology
|
||||
>
|
||||
> Who has dyed clear blue sky into the dark grey
|
||||
>
|
||||
> All Chinese people love our great homeland
|
||||
>
|
||||
> We *WILL* remember the remain pain of the humiliating history
|
||||
>
|
||||
> We love the whole world but in peace
|
||||
>
|
||||
> We love everyone but under respect
|
||||
>
|
||||
> It is to be hoped that the war ends forever
|
||||
>
|
||||
> Whatever it is cold or hot
|
||||
>
|
||||
> Whatever it is economical or political
|
||||
>
|
||||
> Just let the wonderful music of peace surround the world
|
||||
>
|
||||
> ---- Eilles Wan
|
||||
> 7/5 2022
|
||||
@@ -0,0 +1,2 @@
|
||||
Brotli>=1.0.9
|
||||
mido>=1.2.10
|
||||
@@ -0,0 +1,21 @@
|
||||
# 注意,这里是作者署名文件,文件格式开头为单子启
|
||||
# 紧跟其后,不加空格留下常用名,常用名即常用网名
|
||||
# 而在其后是各个语言下的名字。用 井字符 开头表示
|
||||
# 注释,请注意,注释符号必须在一行之首否则无作用
|
||||
# 每进行一次分段表示一个新的开发者,换行表示一个
|
||||
# 新的语言。请全体开发者就此署名,谢谢!
|
||||
启金羿
|
||||
zh-CN 金羿
|
||||
zh-TW 金羿
|
||||
zh-ME 金羿羿喵
|
||||
zh-HK 金 羿
|
||||
en-GB Eilles Wan
|
||||
en-US EillesWan
|
||||
|
||||
启诸葛亮与八卦阵
|
||||
zh-CN 诸葛亮与八卦阵
|
||||
zh-TW 諸葛亮與八卦陣
|
||||
zh-ME 诸葛八卦喵
|
||||
zh-HK 諸葛亮與八卦陣
|
||||
en-GB Bagua Array
|
||||
en-US bgArray
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.6 MiB |
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import setuptools
|
||||
import Musicreater
|
||||
|
||||
with open("requirements.txt", "r", encoding="utf-8") as fh:
|
||||
dependences = fh.read().strip().split("\n")
|
||||
|
||||
with open("README.md", "r", encoding="utf-8") as fh:
|
||||
long_description = fh.read().replace(
|
||||
"./docs/", "https://github.com/TriM-Organization/Musicreater/blob/master/docs/"
|
||||
)
|
||||
|
||||
setuptools.setup(
|
||||
name="Musicreater",
|
||||
version=Musicreater.__version__,
|
||||
author="Eilles Wan, bgArray",
|
||||
author_email="TriM-Organization@hotmail.com",
|
||||
description="一款免费开源的 《我的世界》 mid音乐转换库。\n"
|
||||
"A free open-source python library used to convert midi into Minecraft.",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/TriM-Organization/Musicreater",
|
||||
packages=setuptools.find_packages(),
|
||||
classifiers=[
|
||||
"Intended Audience :: Developers",
|
||||
"Natural Language :: Chinese (Simplified)",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
],
|
||||
# 需要安装的依赖
|
||||
install_requires=dependences,
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
python -m build
|
||||
python -m twine upload dist/*
|
||||
python clean_update.py
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
python -m build
|
||||
python -m twine upload dist/*
|
||||
python clean_update.py
|
||||
@@ -0,0 +1,3 @@
|
||||
python setup.py sdist bdist_wheel
|
||||
python -m twine upload dist/*
|
||||
python clean_update.py
|
||||
Reference in New Issue
Block a user