diff --git a/README.md b/README.md index b15dde9..a4f220d 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,8 @@ ## 致谢🙏 - 感谢 昀梦\ 找出指令生成错误bug并指正 -- 感谢由 Charlie_Ping “查理平” 带来的bdx文件转换参考 +- 感谢由 Charlie_Ping “查理平” 带来的bdx文件转换参考, +以及mid转我的世界乐器参考表格 - 感谢由 CMA_2401PT 为我们的软件开发进行指导 - 感谢由 Dislink Sforza \带来的midi音色解析以及转换指令的算法,我们将其加入了我们众多算法之一 - 感谢 Touch \提供的测试支持 diff --git a/README_EN.md b/README_EN.md index 054fb62..2c7ccfe 100644 --- a/README_EN.md +++ b/README_EN.md @@ -123,7 +123,8 @@ This is a default definder parameter: - Thank [Fuckcraft](https://github.com/fuckcraft) *(“鸣凤鸽子” ,etc)* for the function of Creating the Websocket Server for Minecraft: Bedrock Edition. - *!! They have given me the rights to directly copy the lib into Musicreater* - Thank *昀梦*\ for finding and correcting the bugs in the commands that *Musicreater* Created. -- Thank *Charlie_Ping “查理平”* for bdx convert funtion. +- Thank *Charlie_Ping “查理平”* for bdx convert function, and +the data label that's used to convert the mid's instruments into minecraft's instruments. - Thank *CMA_2401PT* for BDXWorkShop as the .bdx structure's operation guide. - Thank *Miracle Plume “神羽”* \ for the Miracle Plume Bedrock Edition Audio Resource Pack - 感谢由 Dislink Sforza \带来的midi转换算法,我们将其加入了我们众多算法之一 diff --git a/example_convert_mcpack.py b/example_convert_mcpack.py index ece9943..7f3202f 100644 --- a/example_convert_mcpack.py +++ b/example_convert_mcpack.py @@ -13,3 +13,10 @@ convertion.tomcpack( float(input('请输入音量(0-1):')), float(input('请输入速度倍率:')), ) + +# for the test +# if __name__ == '__main__': +# convertion = midiConvert() +# convertion.convert(r"C:\Users\lc\Documents\MuseScore3\乐谱\乐谱\victory.mid", ".") +# convertion.tomcpack( +# 1, True, True, "scb", 1, 1) diff --git a/msctPkgver/load_InstrumentLabel.py b/msctPkgver/load_InstrumentLabel.py new file mode 100644 index 0000000..884a2f9 --- /dev/null +++ b/msctPkgver/load_InstrumentLabel.py @@ -0,0 +1,51 @@ +from openpyxl import * + + +def get(): + wb = load_workbook('program音色表.xlsx') + + ws = wb.active + # 所有行 + keys = [] + values = [] + for row in ws.iter_rows(): + for cell in row: + # print(cell.value) + try: + keys.append(int(cell.value)) + except ValueError: + values.append(cell.value) + # # 所有列 + # for column in ws.iter_cols(): + # for cell in column: + # print(cell.value) + out = "" + index = 0 + for i in keys: + out += ", \"" + str(i) + "\": \"" + values[index] + "\"" + index += 1 + + print(out) + + +idList = {"0": "harp", "1": "harp", "2": "pling", "3": "harp", "4": "pling", "5": "pling", "6": "harp", "7": "harp", + "8": "share", "9": "harp", "10": "didgeridoo", "11": "harp", "12": "xylophone", "13": "chime", "14": "harp", + "15": "harp", "16": "bass", "17": "harp", "18": "harp", "19": "harp", "20": "harp", "21": "harp", + "22": "harp", + "23": "guitar", "24": "guitar", "25": "guitar", "26": "guitar", "27": "guitar", "28": "guitar", + "29": "guitar", + "30": "guitar", "31": "bass", "32": "bass", "33": "bass", "34": "bass", "35": "bass", "36": "bass", + "37": "bass", + "38": "bass", "39": "bass", "40": "harp", "41": "harp", "42": "harp", "43": "harp", "44": "iron_xylophone", + "45": "guitar", "46": "harp", "47": "harp", "48": "guitar", "49": "guitar", "50": "bit", "51": "bit", + "52": "harp", "53": "harp", "54": "bit", "55": "flute", "56": "flute", "57": "flute", "58": "flute", + "59": "flute", "60": "flute", "61": "flute", "62": "flute", "63": "flute", "64": "bit", "65": "bit", + "66": "bit", "67": "bit", "68": "flute", "69": "harp", "70": "harp", "71": "flute", "72": "flute", + "73": "flute", "74": "harp", "75": "flute", "76": "harp", "77": "harp", "78": "harp", "79": "harp", + "80": "bit", "81": "bit", "82": "bit", "83": "bit", "84": "bit", "85": "bit", "86": "bit", "87": "bit", + "88": "bit", "89": "bit", "90": "bit", "91": "bit", "92": "bit", "93": "bit", "94": "bit", "95": "bit", + "96": "bit", "97": "bit", "98": "bit", "99": "bit", "100": "bit", "101": "bit", "102": "bit", "103": "bit", + "104": "harp", "105": "banjo", "106": "harp", "107": "harp", "108": "harp", "109": "harp", "110": "harp", + "111": "guitar", "112": "harp", "113": "bell", "114": "harp", "115": "cow_bell", "116": "basedrum", + "117": "bass", "118": "bit", "119": "basedrum", "120": "guitar", "121": "harp", "122": "harp", "123": "harp", + "124": "harp", "125": "hat", "126": "basedrum", "127": "snare"} diff --git a/msctPkgver/main.py b/msctPkgver/main.py index c0758ec..4ed7ae6 100644 --- a/msctPkgver/main.py +++ b/msctPkgver/main.py @@ -88,49 +88,66 @@ class midiConvert: :param default: 如果instrumentID不在范围内,返回的默认我的世界乐器名称 :return: (str我的世界乐器名, int转换算法中的X)""" - if instrumentID == 105: - return 'note.banjo', 6 - if instrumentID in range(32, 40): - return 'note.bass', 8 - if instrumentID in range(115, 119): - return 'note.basedrum', 7 # 注意,这里是底鼓,打击乐器无音域 - if instrumentID == 9 or instrumentID == 14: - return 'note.bell', 4 - if instrumentID == 80 or instrumentID == 81: - return 'note.bit', 6 - if instrumentID == 112: - return 'note.cow_bell', 5 - if instrumentID == -1: - return 'note.didgeridoo', 8 - if instrumentID in range(72, 80): - return 'note.flute', 5 - if instrumentID in range(24, 32): - return 'note.guitar', 7 - if instrumentID == -2: - return 'note.hat', 7 # 注意,这里是击鼓沿,打击乐器无音域 - if instrumentID == 14: - return 'note.chime', 4 - if instrumentID == 8 or instrumentID == 11: - return 'iron_xylophone', 6 - if instrumentID == 2: - return 'note.pling', 6 - if instrumentID == 114: - return 'note.snare', 7 # 注意,这里是小军鼓,打击乐器无音域 - if instrumentID == 13: - return 'note.xylophone', 4 - return 'note.harp', 6 + import msctPkgver.load_InstrumentLabel + X_Range = {"harp": 6, "pling": 6, "banjo": 6, "iron_xylophone": 6, "guitar": 7, "bass": 8, + "didgeridoo": 8, "flute": 5, "xylophone": 4, "cou_bell": 5, "chime": 4, "bell": 4, + "bit": 6, "basedrum": 7, "hat": 7, "snare": 7} + + # 以下为旧版运算算法 + + # if instrumentID == 105: + # return 'note.banjo', 6 + # if instrumentID in range(32, 40): + # return 'note.bass', 8 + # if instrumentID in range(115, 119): + # return 'note.basedrum', 7 # 注意,这里是底鼓,打击乐器无音域 + # if instrumentID == 9 or instrumentID == 14: + # return 'note.bell', 4 + # if instrumentID == 80 or instrumentID == 81: + # return 'note.bit', 6 + # if instrumentID == 112: + # return 'note.cow_bell', 5 + # if instrumentID == -1: + # return 'note.didgeridoo', 8 + # if instrumentID in range(72, 80): + # return 'note.flute', 5 + # if instrumentID in range(24, 32): + # return 'note.guitar', 7 + # if instrumentID == -2: + # return 'note.hat', 7 # 注意,这里是击鼓沿,打击乐器无音域 + # if instrumentID == 14: + # return 'note.chime', 4 + # if instrumentID == 8 or instrumentID == 11: + # return 'iron_xylophone', 6 + # if instrumentID == 2: + # return 'note.pling', 6 + # if instrumentID == 114: + # return 'note.snare', 7 # 注意,这里是小军鼓,打击乐器无音域 + # if instrumentID == 13: + # return 'note.xylophone', 4 + # return 'note.harp', 6 + + # 以下为新版运算算法 + + # print(instrumentID) + # print("note." + msctPkgver.load_InstrumentLabel.idList.get(str(instrumentID))) + # print(X_Range.get(msctPkgver.load_InstrumentLabel.idList.get(str(instrumentID)))) + + return "note." + msctPkgver.load_InstrumentLabel.idList.get(str(instrumentID)), \ + X_Range.get(msctPkgver.load_InstrumentLabel.idList.get(str(instrumentID))) + def __score2time(self, score: int): return str(int(int(score / 20) / 60)) + ':' + str(int(int(score / 20) % 60)) def __formProgressBar( - self, - maxscore: int, - scoreboardname: str, - progressbar: tuple = ( - r'▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]', - ('§e=§r', '§7=§r'), - ), + self, + maxscore: int, + scoreboardname: str, + progressbar: tuple = ( + r'▶ %%N [ %%s/%^s %%% __________ %%t|%^t ]', + ('§e=§r', '§7=§r'), + ), ) -> list: pgsstyle = progressbar[0] @@ -149,7 +166,7 @@ class midiConvert: ''' def __replace( - s: str, tobeReplaced: str, replaceWith: str, times: int, other: str + s: str, tobeReplaced: str, replaceWith: str, times: int, other: str ): if times == 0: return s.replace(tobeReplaced, other) @@ -224,16 +241,16 @@ class midiConvert: return finalprgsbar def __formCMDblk( - self, - command: str, - particularValue: int, - impluse: int = 0, - condition: bool = False, - needRedstone: bool = True, - tickDelay: int = 0, - customName: str = '', - executeOnFirstTick: bool = False, - trackOutput: bool = True, + self, + command: str, + particularValue: int, + impluse: int = 0, + condition: bool = False, + needRedstone: bool = True, + tickDelay: int = 0, + customName: str = '', + executeOnFirstTick: bool = False, + trackOutput: bool = True, ): """ 使用指定项目返回指定的指令方块放置指令项 @@ -296,7 +313,7 @@ class midiConvert: return block def _toCmdList_m1( - self, scoreboardname: str = 'mscplay', volume: float = 1.0, speed: float = 1.0 + self, scoreboardname: str = 'mscplay', volume: float = 1.0, speed: float = 1.0 ) -> list: """ 使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表 @@ -322,12 +339,14 @@ class midiConvert: for msg in track: ticks += msg.time + # print(msg) if msg.is_meta: if msg.type == 'set_tempo': tempo = msg.tempo - if msg.type == 'program_change': - instrumentID = msg.program else: + if msg.type == 'program_change': + # print("TT") + instrumentID = msg.program if msg.type == 'note_on' and msg.velocity != 0: nowscore = round( (ticks * tempo) @@ -341,7 +360,7 @@ class midiConvert: + '=' + 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 if len(singleTrack) != 0: @@ -350,11 +369,11 @@ class midiConvert: return tracks, commands, maxscore def _toCmdList_withDelay_m1( - self, - volume: float = 1.0, - speed: float = 1.0, - player: str = '@a', - isMixedWithPrograssBar=False, + self, + volume: float = 1.0, + speed: float = 1.0, + player: str = '@a', + isMixedWithPrograssBar=False, ) -> list: """ 使用Dislink Sforza的转换思路,将midi转换为我的世界命令列表,并输出每个音符之后的延迟 @@ -398,11 +417,11 @@ class midiConvert: soundID, _X = self.__Inst2soundIDwithX(instrumentID) try: tracks[nowtick].append( - 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)}' ) except: 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()) @@ -425,7 +444,7 @@ class midiConvert: ''' def __replace( - s: str, tobeReplaced: str, replaceWith: str, times: int, other: str + s: str, tobeReplaced: str, replaceWith: str, times: int, other: str ): if times == 0: return s.replace(tobeReplaced, other) @@ -522,13 +541,13 @@ class midiConvert: return math.ceil(math.sqrt(math.ceil(total / maxHeight))) def tomcpack( - self, - method: int = 1, - isAutoReset: bool = False, - progressbar=None, - scoreboardname: str = 'mscplay', - volume: float = 1.0, - speed: float = 1.0, + self, + method: int = 1, + isAutoReset: bool = False, + progressbar=None, + scoreboardname: str = 'mscplay', + volume: float = 1.0, + speed: float = 1.0, ) -> bool: """ 使用method指定的转换算法,将midi转换为我的世界mcpack格式的包 @@ -558,7 +577,7 @@ class midiConvert: # 写入manifest.json if not os.path.exists(f'{self.outputPath}/temp/manifest.json'): with open( - f"{self.outputPath}/temp/manifest.json", "w", encoding='utf-8' + f"{self.outputPath}/temp/manifest.json", "w", encoding='utf-8' ) as f: f.write( "{\n \"format_version\": 1,\n \"header\": {\n \"description\": \"" @@ -575,7 +594,7 @@ class midiConvert: ) else: with open( - f'{self.outputPath}/temp/manifest.json', 'r', encoding='utf-8' + f'{self.outputPath}/temp/manifest.json', 'r', encoding='utf-8' ) as manifest: data = json.loads(manifest.read()) data['header'][ @@ -599,9 +618,9 @@ class midiConvert: 'function mscplay/track' + str(cmdlist.index(track) + 1) + '\n' ) with open( - f'{self.outputPath}/temp/functions/mscplay/track{cmdlist.index(track)+1}.mcfunction', - 'w', - encoding='utf-8', + f'{self.outputPath}/temp/functions/mscplay/track{cmdlist.index(track) + 1}.mcfunction', + 'w', + encoding='utf-8', ) as f: f.write('\n'.join(track)) indexfile.writelines( @@ -612,12 +631,12 @@ class midiConvert: + scoreboardname + ' 1\n', ( - 'scoreboard players reset @a[scores={' - + scoreboardname - + '=' - + str(maxscore + 20) - + '..}]' - + f' {scoreboardname}\n' + 'scoreboard players reset @a[scores={' + + scoreboardname + + '=' + + str(maxscore + 20) + + '..}]' + + f' {scoreboardname}\n' ) if isAutoReset else '', @@ -628,18 +647,18 @@ class midiConvert: if progressbar: if progressbar == True: with open( - f'{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction', - 'w', - encoding='utf-8', + f'{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction', + 'w', + encoding='utf-8', ) as f: f.writelines( '\n'.join(self.__formProgressBar(maxscore, scoreboardname)) ) else: with open( - f'{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction', - 'w', - encoding='utf-8', + f'{self.outputPath}/temp/functions/mscplay/progressShow.mcfunction', + 'w', + encoding='utf-8', ) as f: f.writelines( '\n'.join( @@ -658,15 +677,15 @@ class midiConvert: shutil.rmtree(f'{self.outputPath}/temp/') def toBDXfile( - self, - method: int = 1, - author: str = 'Eilles', - progressbar=False, - maxheight: int = 64, - scoreboardname: str = 'mscplay', - volume: float = 1.0, - speed: float = 1.0, - isAutoReset: bool = False, + self, + method: int = 1, + author: str = 'Eilles', + progressbar=False, + maxheight: int = 64, + scoreboardname: str = 'mscplay', + volume: float = 1.0, + speed: float = 1.0, + isAutoReset: bool = False, ): """ 使用method指定的转换算法,将midi转换为BDX结构文件 @@ -695,9 +714,9 @@ class midiConvert: f.write("BD@") _bytes = ( - b"BDX\x00" - + author.encode("utf-8") - + b" & Musicreater\x00\x01command_block\x00" + b"BDX\x00" + + author.encode("utf-8") + + b" & Musicreater\x00\x01command_block\x00" ) key = { @@ -726,12 +745,12 @@ class midiConvert: if isAutoReset: commands += ( - 'scoreboard players reset @a[scores={' - + scoreboardname - + '=' - + str(maxScore + 20) - + '}] ' - + scoreboardname + 'scoreboard players reset @a[scores={' + + scoreboardname + + '=' + + str(maxScore + 20) + + '}] ' + + scoreboardname ) if progressbar: @@ -747,13 +766,13 @@ class midiConvert: cmd, (1 if yforward else 0) if ( - ((nowy != 0) and (not yforward)) - or ((yforward) and (nowy != maxheight)) + ((nowy != 0) and (not yforward)) + or ((yforward) and (nowy != maxheight)) ) else (3 if zforward else 2) if ( - ((nowz != 0) and (not zforward)) - or ((zforward) and (nowz != _sideLength)) + ((nowz != 0) and (not zforward)) + or ((zforward) and (nowz != _sideLength)) ) else 5, impluse=2, @@ -775,7 +794,7 @@ class midiConvert: nowz += 1 if zforward else -1 if ((nowz > _sideLength) and (zforward)) or ( - (nowz < 0) and (not zforward) + (nowz < 0) and (not zforward) ): nowz -= 1 if zforward else -1 zforward = not zforward @@ -795,14 +814,14 @@ class midiConvert: return (True, _bytes, (nowx, maxheight, _sideLength)) def toBDXfile_withDelay( - self, - method: int = 1, - author: str = 'Eilles', - progressbar=False, - maxheight: int = 64, - volume: float = 1.0, - speed: float = 1.0, - player: str = '@a', + self, + method: int = 1, + author: str = 'Eilles', + progressbar=False, + maxheight: int = 64, + volume: float = 1.0, + speed: float = 1.0, + player: str = '@a', ): """ 使用method指定的转换算法,将midi转换为BDX结构文件 @@ -828,9 +847,9 @@ class midiConvert: f.write("BD@") _bytes = ( - b"BDX\x00" - + author.encode("utf-8") - + b" & Musicreater\x00\x01command_block\x00" + b"BDX\x00" + + author.encode("utf-8") + + b" & Musicreater\x00\x01command_block\x00" ) key = { @@ -857,13 +876,13 @@ class midiConvert: cmd, (1 if yforward else 0) if ( - ((nowy != 0) and (not yforward)) - or ((yforward) and (nowy != maxheight)) + ((nowy != 0) and (not yforward)) + or ((yforward) and (nowy != maxheight)) ) else (3 if zforward else 2) if ( - ((nowz != 0) and (not zforward)) - or ((zforward) and (nowz != _sideLength)) + ((nowz != 0) and (not zforward)) + or ((zforward) and (nowz != _sideLength)) ) else 5, impluse=2, @@ -885,7 +904,7 @@ class midiConvert: nowz += 1 if zforward else -1 if ((nowz > _sideLength) and (zforward)) or ( - (nowz < 0) and (not zforward) + (nowz < 0) and (not zforward) ): nowz -= 1 if zforward else -1 zforward = not zforward diff --git a/msctPkgver/program音色表.xlsx b/msctPkgver/program音色表.xlsx new file mode 100644 index 0000000..b68bcf6 Binary files /dev/null and b/msctPkgver/program音色表.xlsx differ