Skip to content

Commit

Permalink
adjust formula for vocaloid portamento
Browse files Browse the repository at this point in the history
  • Loading branch information
SoulMelody committed Sep 26, 2024
1 parent 19c2a2a commit 10d84b7
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
16 changes: 10 additions & 6 deletions libresvip/model/pitch_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ def __post_init__(self, note_list: list[Note]) -> None: # type: ignore[override
return
current_note = note_list[0]
max_portamento_percent = self.portamento.max_inter_time_percent
if self.portamento.vocaloid_mode: # reference: https://github.com/scskarsper/VocalUtau.Formats/blob/master/VocalUtau.Formats/Model.VocalObject/ParamTranslater/PitchCompiler.cs
if self.portamento.vocaloid_mode:
max_portamento_ticks = max_portamento_percent * current_note.length
if max_portamento_ticks >= 60:
max_portamento_ticks = 60
elif current_note.length <= 120:
max_portamento_ticks = current_note.length / 2
max_portamento_time = self.synchronizer.get_duration_secs_from_ticks(
int(current_note.end_pos - max_portamento_ticks * 1.5),
int(current_note.end_pos - max_portamento_ticks * 0.5),
int(current_note.end_pos - max_portamento_ticks * 1.4),
int(current_note.end_pos - max_portamento_ticks * 0.4),
)
else:
max_portamento_time = self.portamento.max_inter_time_in_secs
Expand All @@ -49,6 +49,10 @@ def __post_init__(self, note_list: list[Note]) -> None: # type: ignore[override
if current_note.end_pos > next_note.start_pos:
msg = _("Notes Overlapped")
raise NotesOverlappedError(msg)
elif (
self.portamento.vocaloid_mode and next_note.start_pos - current_note.end_pos >= 480
):
max_portamento_time = 0
next_head = self.synchronizer.get_actual_secs_from_ticks(next_note.start_pos)
next_dur = self.synchronizer.get_duration_secs_from_ticks(
next_note.start_pos, next_note.end_pos
Expand All @@ -59,7 +63,7 @@ def __post_init__(self, note_list: list[Note]) -> None: # type: ignore[override
current_note.end_pos
if next_note.lyric == "-"
else (next_note.start_pos + current_note.end_pos) / 2
) - max_portamento_ticks / 2
) - max_portamento_ticks * 0.4
interval = self.synchronizer.get_duration_secs_from_ticks(
int(middle_pos - max_portamento_ticks), int(middle_pos)
)
Expand Down Expand Up @@ -100,8 +104,8 @@ def __post_init__(self, note_list: list[Note]) -> None: # type: ignore[override
elif current_note.length <= 120:
max_portamento_ticks = current_note.length / 2
max_portamento_time = self.synchronizer.get_duration_secs_from_ticks(
int(middle_pos - max_portamento_ticks * 1.5),
int(middle_pos - max_portamento_ticks * 0.5),
int(middle_pos - max_portamento_ticks * 1.4),
int(middle_pos - max_portamento_ticks * 0.4),
)
self.interval_dict[portion.closedopen(prev_portamento_end, portion.inf)] = (
current_note.key_number
Expand Down
3 changes: 2 additions & 1 deletion libresvip/model/portamento.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
cubic_interpolation,
linear_interpolation,
sigmoid_interpolation,
vocaloid_interpolation,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -40,4 +41,4 @@ def sigmoid_portamento(cls) -> PortamentoPitch:

@classmethod
def vocaloid_portamento(cls) -> PortamentoPitch:
return cls(0.05, 0.15, cosine_easing_in_out_interpolation, True)
return cls(0.05, 0.15, vocaloid_interpolation, True)
9 changes: 9 additions & 0 deletions libresvip/utils/music_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ def cubic_interpolation(r: float) -> float:
return (3 - 2 * r) * r**2


@_transform_interpolation_args
def vocaloid_interpolation(r: float) -> float:
if r <= 0.5:
return math.sin(r * math.pi) / 2
else:
return r
# math.sin((r - 1) * math.pi) / 2 + 1


@_transform_interpolation_args # type: ignore[arg-type]
def sigmoid_interpolation(r: float, k: float) -> float:
return 1 / (1 + math.exp(k * (-2 * r + 1)))
Expand Down

0 comments on commit 10d84b7

Please sign in to comment.