From b01b2bdcea63a821f3a32991d4db01c589d55738 Mon Sep 17 00:00:00 2001 From: donmai-me <71143298+donmai-me@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:04:10 +0800 Subject: [PATCH] Release 0.14.4 --- CHANGELOG.md | 16 +++++++-- maiconverter/converter/maima2tosimai.py | 4 ++- maiconverter/converter/simaitomaima2.py | 4 ++- maiconverter/maima2/maima2.py | 4 +-- maiconverter/simai/simai.py | 6 ++-- maiconverter/simai/simai_fragment.lark | 2 +- maiconverter/simai/simai_parser.py | 44 +++++++++++++++++-------- scripts/sxt_to_ma2_with_bpms.py | 17 ++++------ 8 files changed, 63 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b34d69f..aa659a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +## [0.14.4] - 2022-01-24 +### Fixed +- Missing new line in BPM and MET lines in ma2. +- Fixed bug in simaitoma2 and ma2tosimai BPM conversion. +- Fixed bug in simai export. + +### Added +- Support for 2Simai quirk where simultaneous slide's duration is optional. + ## [0.14.3] - 2021-12-20 ### Fixed -- Fixed exceptions raised when ma2 TouchHoldNote has a 0 length +- Fixed exceptions raised when ma2 TouchHoldNote has a 0 length. ### Changed - Batch conversions will no longer continue when one fails. @@ -62,7 +73,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ma2 to Sdt conversion and vice versa. - Simai to Sdt conversion and vice versa. -[Unreleased]: https://github.com/donmai-me/MaiConverter/compare/0.14.3...HEAD +[Unreleased]: https://github.com/donmai-me/MaiConverter/compare/0.14.4...HEAD +[0.14.4]: https://github.com/donmai-me/MaiConverter/compare/0.14.3...0.14.4 [0.14.3]: https://github.com/donmai-me/MaiConverter/compare/0.14.2...0.14.3 [0.14.2]: https://github.com/donmai-me/MaiConverter/compare/0.14.1...0.14.2 [0.14.1]: https://github.com/donmai-me/MaiConverter/compare/0.14.0...0.14.1 diff --git a/maiconverter/converter/maima2tosimai.py b/maiconverter/converter/maima2tosimai.py index 6298690..0d62446 100644 --- a/maiconverter/converter/maima2tosimai.py +++ b/maiconverter/converter/maima2tosimai.py @@ -12,7 +12,9 @@ def ma2_to_simai(ma2: MaiMa2) -> SimaiChart: simai_chart = SimaiChart() for bpm in ma2.bpms: - simai_chart.set_bpm(bpm.measure, bpm.bpm) + measure = 1.0 if bpm.measure <= 1.0 else bpm.measure + + simai_chart.set_bpm(measure, bpm.bpm) convert_notes(simai_chart, ma2.notes) diff --git a/maiconverter/converter/simaitomaima2.py b/maiconverter/converter/simaitomaima2.py index d74f5a3..2b04457 100644 --- a/maiconverter/converter/simaitomaima2.py +++ b/maiconverter/converter/simaitomaima2.py @@ -17,7 +17,9 @@ def simai_to_ma2(simai: SimaiChart, fes_mode: bool = False) -> MaiMa2: ma2 = MaiMa2(fes_mode=fes_mode) for bpm in simai.bpms: - ma2.set_bpm(bpm.measure, bpm.bpm) + measure = 0.0 if bpm.measure <= 1.0 else bpm.measure + + ma2.set_bpm(measure, bpm.bpm) ma2.set_meter(0.0, 4, 4) convert_notes(ma2, simai.notes) diff --git a/maiconverter/maima2/maima2.py b/maiconverter/maima2/maima2.py index 2554bc1..73c70a4 100644 --- a/maiconverter/maima2/maima2.py +++ b/maiconverter/maima2/maima2.py @@ -827,9 +827,9 @@ def export(self, resolution: int = 384) -> str: # BPM and meters self.bpms.sort(key=lambda x: x.measure) - result += "\n".join([bpm.to_str(resolution) for bpm in self.bpms]) + result += "\n".join([bpm.to_str(resolution) for bpm in self.bpms]) + "\n" self.meters.sort(key=lambda x: x.measure) - result += "\n".join([meter.to_str(resolution) for meter in self.meters]) + result += "\n".join([meter.to_str(resolution) for meter in self.meters]) + "\n" result += "\n" self.notes.sort() diff --git a/maiconverter/simai/simai.py b/maiconverter/simai/simai.py index 5793b34..e850150 100644 --- a/maiconverter/simai/simai.py +++ b/maiconverter/simai/simai.py @@ -596,7 +596,7 @@ def export(self, max_den: int = 1000) -> str: measures = [event.measure for event in self.notes + self.bpms] measures += [int(i) for i in measures] - measures.append(0.0) + measures.append(1.0) measures = list(set(measures)) last_whole_measure = max([int(measure) for measure in measures]) @@ -614,10 +614,10 @@ def export(self, max_den: int = 1000) -> str: whole_divisors.append(get_measure_divisor(note_measures)) # last_measure takes into account slide and hold notes' end measure - last_measure = 0.0 + last_measure = 1.0 # measure_tick is our time-tracking variable. Used to know what measure # are we in-between rests "," - measure_tick = 0.0 + measure_tick = 1.0 # previous_divisor is used for comparing to current_divisor # to know if we should add a "{}" indicator previous_divisor: Optional[int] = None diff --git a/maiconverter/simai/simai_fragment.lark b/maiconverter/simai/simai_fragment.lark index 6f1f103..2949c03 100644 --- a/maiconverter/simai/simai_fragment.lark +++ b/maiconverter/simai/simai_fragment.lark @@ -27,7 +27,7 @@ tap_hold_note: /[0-8][hbex$]*/ duration? slide_beg: /[0-8][b@x?$!]*([-^<>szvw]|p{1,2}|q{1,2}|V[0-8])[0-8]/ slide_note: slide_beg duration chained_slide_note* -chained_slide_note: "*" /[b@ex?$!]*([-^<>szvw]|p{1,2}|q{1,2}|V[0-8])[0-8]/ duration +chained_slide_note: "*" /[b@ex?$!]*([-^<>szvw]|p{1,2}|q{1,2}|V[0-8])[0-8]/ duration? touch_tap_hold_note: /((C[012]?)|(B[0-8])|(E[0-8])|(A[0-8])|(D[0-8]))[hfe]*/ duration? diff --git a/maiconverter/simai/simai_parser.py b/maiconverter/simai/simai_parser.py index 389bf34..2977a34 100644 --- a/maiconverter/simai/simai_parser.py +++ b/maiconverter/simai/simai_parser.py @@ -168,10 +168,17 @@ def slide_beg(self, items) -> dict: } def chained_slide_note(self, items) -> dict: - ( - text, - duration_dict, - ) = items + if len(items) == 2: + ( + text, + duration_dict, + ) = items + duration = duration_dict["duration"] + equivalent_bpm = duration_dict["equivalent_bpm"] + else: + (text,) = items + duration = None + equivalent_bpm = None # Skip the modifiers in a chained slide for i, char in enumerate(text): @@ -194,12 +201,6 @@ def chained_slide_note(self, items) -> dict: end = int(text[0]) - 1 - if not isinstance(duration_dict, dict): - raise ValueError(f"Not a dict: {duration_dict}") - - duration = duration_dict["duration"] - equivalent_bpm = duration_dict["equivalent_bpm"] - return { "type": "chained_slide_note", "pattern": pattern, @@ -255,7 +256,9 @@ def slide_note(self, items): slides.append(note_dict) if len(chained_slides) != 0: - slides += process_chained_slides(start, modifier + "*", chained_slides) + slides += process_chained_slides( + start, duration, equivalent_bpm, modifier + "*", chained_slides + ) if len(slides) > 0: return slides @@ -389,12 +392,25 @@ def chain(self, items) -> list: return result -def process_chained_slides(start_button, slide_modifier, chained_slides): +def process_chained_slides( + start_button: int, + duration: dict, + equivalent_bpm: dict, + slide_modifier: str, + chained_slides: List[dict], +): complete_slides = [] for slide in chained_slides: if start_button == -1 or slide["reflect"] == -1 or slide["end"] == -1: continue + duration = duration if slide["duration"] is None else slide["duration"] + equivalent_bpm = ( + equivalent_bpm + if slide["equivalent_bpm"] is None + else slide["equivalent_bpm"] + ) + note_dict = { "type": "slide", "start_button": start_button, @@ -402,8 +418,8 @@ def process_chained_slides(start_button, slide_modifier, chained_slides): "pattern": slide["pattern"], "reflect_position": slide["reflect"], "end_button": slide["end"], - "duration": slide["duration"], - "equivalent_bpm": slide["equivalent_bpm"], + "duration": duration, + "equivalent_bpm": equivalent_bpm, } complete_slides.append(note_dict) diff --git a/scripts/sxt_to_ma2_with_bpms.py b/scripts/sxt_to_ma2_with_bpms.py index 1ef27e2..b993e9c 100644 --- a/scripts/sxt_to_ma2_with_bpms.py +++ b/scripts/sxt_to_ma2_with_bpms.py @@ -27,19 +27,16 @@ def main(): conform_ma2 = MaiMa2.open(args.conform) new_notes = [] - offset = 0.0 - conform_ma2.second_to_measure( - ma2.measure_to_second(0.0, decrement=False), increment=False - ) + offset = 0.0 - conform_ma2.second_to_measure(ma2.measure_to_second(0.0)) + print(offset) for note in ma2.notes: current_measure = note.measure - current_time = ma2.measure_to_second(current_measure, decrement=False) - current_conform_measure = conform_ma2.second_to_measure( - current_time, increment=False - ) + current_time = ma2.measure_to_second(current_measure) + current_conform_measure = conform_ma2.second_to_measure(current_time) - scale = conform_ma2.get_bpm( - current_conform_measure, decrement=False - ) / ma2.get_bpm(current_measure, decrement=False) + scale = conform_ma2.get_bpm(current_conform_measure) / ma2.get_bpm( + current_measure + ) note = copy.deepcopy(note) note.measure = quantise(current_conform_measure + offset, args.quantise)