diff --git a/libresvip/plugins/s5p/synthv_editor_parser.py b/libresvip/plugins/s5p/synthv_editor_parser.py index 1282277de..3c9a9ce8a 100644 --- a/libresvip/plugins/s5p/synthv_editor_parser.py +++ b/libresvip/plugins/s5p/synthv_editor_parser.py @@ -228,59 +228,46 @@ def parse_params(self, parameters: S5pParameters, note_list: list[Note]) -> Para def parse_pitch_curve( self, pitch_delta: S5pPoints, interval: int, note_list: list[Note] ) -> list[Point]: - points = sortedcontainers.SortedList(key=operator.attrgetter("x")) - note_start_positions = [note.start_pos for note in note_list] - pitch_intervals = portion.empty() + pitch_raw_data = sortedcontainers.SortedList(key=operator.attrgetter("x")) for s5p_point_group in more_itertools.split_when( pitch_delta.root, lambda p1, p2: p2.offset > p1.offset + 1 ): - pitch_start = None for is_first, is_last, s5p_point in more_itertools.mark_ends(s5p_point_group): if is_first and is_last: continue point_ticks = round(s5p_point.offset * (interval / TICK_RATE)) - point_secs = self.synchronizer.get_actual_secs_from_ticks(point_ticks) - if is_first: - pitch_start = point_secs - elif is_last: - pitch_intervals |= portion.closed(pitch_start, point_secs) point_value = s5p_point.value - if (vibrato_value := self.vibrato_value_interval_dict.get(point_secs)) is not None: - point_value += ( - vibrato_value * self.vibrato_coef_interval_dict[point_secs] * 2000 - ) - points.add( + pitch_raw_data.add( Point( x=point_ticks, y=round(point_value), ) ) - auto_pitch_intervals = self.vibrato_value_interval_dict.domain() - pitch_intervals - self.vibrato_value_interval_dict._last_index = 0 - self.vibrato_coef_interval_dict._last_index = 0 - for sub_interval in auto_pitch_intervals: - start_tick = round(self.synchronizer.get_actual_ticks_from_secs(sub_interval.lower)) - - step_secs = self.synchronizer.get_duration_secs_from_ticks( - start_tick, int(start_tick + interval / TICK_RATE) - ) - for is_first, is_last, vibrato_secs in more_itertools.mark_ends( - portion.iterate( - sub_interval, - step_secs, - ) - ): - vibrato_ticks = int(self.synchronizer.get_actual_ticks_from_secs(vibrato_secs)) - if ( - vibrato_ticks not in note_start_positions - and (vibrato_value := self.vibrato_value_interval_dict.get(vibrato_secs)) - is not None - ): - vibrato_value *= self.vibrato_coef_interval_dict[vibrato_secs] * 2000 - points.add( + points = [] + prev_pos = None + value = None + for pos, value in pitch_raw_data: + pos_secs = self.synchronizer.get_actual_secs_from_ticks(pos) + if prev_pos is not None: + for interp_pos in range(prev_pos + 5, pos, 5): + interp_pos_secs = self.synchronizer.get_actual_secs_from_ticks(interp_pos) + if interp_value_diff := self.vibrato_value_interval_dict.get( + interp_pos_secs, 0 + ): + interp_value_diff *= self.vibrato_coef_interval_dict[interp_pos_secs] * 2000 + points.append( Point( - x=vibrato_ticks, - y=round(vibrato_value), + x=interp_pos, + y=value + round(interp_value_diff), ) ) - return list(points) + if value_diff := self.vibrato_value_interval_dict.get(pos_secs, 0): + value_diff *= self.vibrato_coef_interval_dict[pos_secs] * 2000 + points.append( + Point( + x=pos, + y=value + round(value_diff), + ) + ) + prev_pos = pos + return points