diff --git a/src/jsMain/kotlin/process/phonemes/PhonemesMapping.kt b/src/jsMain/kotlin/process/phonemes/PhonemesMapping.kt index 0781a54..a8d19b8 100644 --- a/src/jsMain/kotlin/process/phonemes/PhonemesMapping.kt +++ b/src/jsMain/kotlin/process/phonemes/PhonemesMapping.kt @@ -19,7 +19,12 @@ data class PhonemesMappingRequest( val from = line.substringBefore("=").trim() val to = line.substringAfter("=").trim() from to to - }.sortedByDescending { it.first.split(" ").size } + }.sortedWith { a, b -> + val countA = a.first.split(" ").count() + val countB = b.first.split(" ").count() + if (countA != countB) return@sortedWith countB - countA // descending order + a.first.length - b.first.length + } companion object { @@ -42,25 +47,21 @@ fun Track.replacePhonemes(request: PhonemesMappingRequest?) = copy( ) fun Note.replacePhonemes(request: PhonemesMappingRequest?): Note { - val input = phoneme?.split(" ") ?: return this if (request == null) return copy(phoneme = null) - val output = mutableListOf() - var pos = 0 - while (pos <= input.lastIndex) { - val restInput = input.drop(pos).joinToString(" ") - var matched = false - for ((key, value) in request.map) { - if (restInput.startsWith(key)) { - output += value.split(" ") - pos += key.split(" ").size - matched = true + var output = phoneme?.split(" ") ?: return this + for ((key, value) in request.map) { + val keySplit = key.split(" ") + for (i in 0..(output.size - keySplit.size)) { + val subList = output.subList(i, i + keySplit.size) + if (subList == keySplit) { + output = output.subList(0, i) + value.split(" ") + + output.subList(i + keySplit.size, output.size) + // once replaced, the count of output is changed, so we could not proceed the replacement. + // this means that multiple occurrences of the same phoneme set in one note get replaced only once. break } } - if (!matched) { - output += input[pos] - pos++ - } } - return copy(phoneme = output.filter { it.isNotBlank() }.joinToString(" ")) + output = output.filter { it.isNotBlank() } + return copy(phoneme = output.joinToString(" ")) } diff --git a/src/jsTest/kotlin/process/phonemes/PhonemesMappingTest.kt b/src/jsTest/kotlin/process/phonemes/PhonemesMappingTest.kt index 4e555c0..7b521b2 100644 --- a/src/jsTest/kotlin/process/phonemes/PhonemesMappingTest.kt +++ b/src/jsTest/kotlin/process/phonemes/PhonemesMappingTest.kt @@ -15,6 +15,10 @@ class PhonemesMappingTest { d c a=DC' A d c=DC sil= + s=S + sh=SH + effff=EF + effff d=EF D """.trimIndent(), ) @@ -29,9 +33,9 @@ class PhonemesMappingTest { @Test fun testNoMatch() { - val note = createNote("l e") + val note = createNote("l o") val actual = note.replacePhonemes(request).phoneme - assertEquals("l e", actual) + assertEquals("l o", actual) } @Test @@ -68,4 +72,18 @@ class PhonemesMappingTest { val actual = note.replacePhonemes(request).phoneme assertEquals("A", actual) } + + @Test + fun testSortLength() { + val note = createNote("sh") + val actual = note.replacePhonemes(request).phoneme + assertEquals("SH", actual) + } + + @Test + fun testSortMultiLength() { + val note = createNote("effff d c a") + val actual = note.replacePhonemes(request).phoneme + assertEquals("EF DC' A", actual) + } }