# -*- coding: utf-8 -*- """ 功能测试 若非已知 请勿更改 此文件仅供功能测试,并非实际调用的文件 请注意,此处的文件均为测试使用 不要更改 不要更改 不要更改 请注意这里的一切均需要其原作者更改 这里用于放置一些新奇的点子 用于测试 不要更改 不要更改 不要更改! """ # 音·创 开发交流群 861684859 # Email TriM-Organization@hotmail.com # 版权所有 金羿("Eilles") & 诸葛亮与八卦阵("bgArray") & 鸣凤鸽子("MingFengPigeon") # 若需转载或借鉴 许可声明请查看仓库目录下的 License.md """ 音·创 (Musicreater) 是一款免费开源的针对《我的世界》的midi音乐转换库 Musicreater (音·创) A free open source library used for convert midi file into formats that is suitable for **Minecraft**. 版权所有 © 2025 金羿 & 诸葛亮与八卦阵 Copyright © 2025 Eilles & bgArray 开源相关声明请见 ../License.md Terms & Conditions: ../License.md """ # ============================ 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 Literal from ..constants import x, y, z # 不要用 没写完 def delay_to_note_blocks( baseblock: str = "stone", position_forward: Literal["x", "y", "z"] = z, ): """传入音符,生成以音符盒存储的红石音乐 :param: baseblock: 中继器的下垫方块 position_forward: 结构延长方向 :return 是否生成成功 """ from TrimMCStruct import Block, Structure struct = Structure( (_sideLength, max_height, _sideLength), # 声明结构大小 ) log = print startpos = [0, 0, 0] # 1拍 x 2.5 rt 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]