Skip to content

Commit

Permalink
Fix UTAU/OpenUtau pitch import for very close pitch points
Browse files Browse the repository at this point in the history
  • Loading branch information
sdercolin committed Jul 22, 2024
1 parent 9cad76e commit 0e81b7f
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import kotlin.math.roundToInt

private const val SAMPLING_INTERVAL_TICK = 5L

// Not smaller than the sampling interval of the pitch data used in pitch generation targeting any format.
// This is used for placing two key points far enough to ensure they are not merged by the resampling process.
private const val SAFE_SAMPLING_INTERVAL_TICK = 5L

data class OpenUtauNotePitchData(
val points: List<Point>,
val vibrato: UtauNoteVibratoParams,
Expand Down Expand Up @@ -44,12 +48,15 @@ fun pitchFromUstxPart(notes: List<Note>, pitchData: OpenUtauPartPitchData, tempo
// Extract pitch points from notes
val notePointsList = mutableListOf<List<Pair<Long, Double>>>()
val tickTimeTransformer = TickTimeTransformer(tempos)
var lastKeyPos = -SAFE_SAMPLING_INTERVAL_TICK
for ((note, notePitch) in notes.zip(pitchData.notes)) {
val points = mutableListOf<Pair<Long, Double>>()
var lastPointShape = OpenUtauNotePitchData.Shape.EaseInOut
val noteStartInMillis = tickTimeTransformer.tickToMilliSec(note.tickOn)
for (rawPoint in notePitch.points) {
val x = tickTimeTransformer.milliSecToTick(noteStartInMillis + rawPoint.x)
.coerceAtLeast(lastKeyPos + SAFE_SAMPLING_INTERVAL_TICK)
lastKeyPos = x
val y = rawPoint.y / 10
val thisPoint = x to y
val lastPoint = points.lastOrNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import core.util.runIf

private const val SAMPLING_INTERVAL_TICK = 4L

// Not smaller than the sampling interval of the pitch data used in pitch generation targeting any format.
// This is used for placing two key points far enough to ensure they are not merged by the resampling process.
// See also: core.process.pitch.OpenUtauPitchConversion.kt
private const val SAFE_SAMPLING_INTERVAL_TICK = 5L

data class UtauMode2TrackPitchData(
val notes: List<UtauMode2NotePitchData?>,
)
Expand Down Expand Up @@ -87,12 +92,15 @@ fun pitchFromUtauMode2Track(pitchData: UtauMode2TrackPitchData?, notes: List<Not
val pitchPoints = mutableListOf<Pair<Long, Double>>()
var lastNote: Note? = null
var pendingPitchPoints = listOf<Pair<Long, Double>>()
var lastKeyPos = -SAFE_SAMPLING_INTERVAL_TICK
for ((note, notePitch) in notePitches) {
val points = mutableListOf<Pair<Long, Double>>()
val noteStartInMillis = tickTimeTransformer.tickToMilliSec(note.tickOn)
if (notePitch?.start != null) {
var posInMillis = noteStartInMillis + notePitch.start
var tickPos = tickTimeTransformer.milliSecToTick(posInMillis)
.coerceAtLeast(lastKeyPos + SAFE_SAMPLING_INTERVAL_TICK)
lastKeyPos = tickPos
val startShift =
if (note.tickOn == lastNote?.tickOff) {
// always same value as the last note
Expand All @@ -108,6 +116,8 @@ fun pitchFromUtauMode2Track(pitchData: UtauMode2TrackPitchData?, notes: List<Not
val curveType = notePitch.curveTypes.getOrNull(index) ?: ""
posInMillis += width
tickPos = tickTimeTransformer.milliSecToTick(posInMillis)
.coerceAtLeast(lastKeyPos + SAFE_SAMPLING_INTERVAL_TICK)
lastKeyPos = tickPos
val thisPoint = tickPos to (shift / 10)
val lastPoint = points.last()
if (thisPoint.second != lastPoint.second) {
Expand Down
2 changes: 1 addition & 1 deletion src/jsMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ui.strings.Language
import ui.strings.initializeI18n

const val APP_NAME = "UtaFormatix"
const val APP_VERSION = "3.22"
const val APP_VERSION = "3.22.1"

suspend fun main() {
initializeI18n(Language.English)
Expand Down

0 comments on commit 0e81b7f

Please sign in to comment.