Skip to content

Commit

Permalink
Implement Phonemes mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
sdercolin committed Feb 9, 2024
1 parent 22bf304 commit 544a4bf
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/jsMain/kotlin/process/phonemes/PhonemesMapping.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package process.phonemes

import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import model.Note
import model.Project
import model.Track
import process.validateNotes

@Serializable
data class PhonemesMappingRequest(
val mapText: String = "",
) {
val isValid get() = map.isNotEmpty()

@Transient
val map = mapText.lines().mapNotNull { line ->
if (line.contains("=").not()) return@mapNotNull null
val from = line.substringBefore("=").trim()
val to = line.substringAfter("=").trim()
from to to
}.sortedByDescending { it.first.split(" ").size }

companion object {

fun findPreset(name: String) = Presets.find { it.first == name }?.second

fun getPreset(name: String) = requireNotNull(findPreset(name))

val Presets: List<Pair<String, PhonemesMappingRequest>> by lazy {
listOf()
}
}
}

fun Project.mapPhonemes(request: PhonemesMappingRequest) = copy(
tracks = tracks.map { it.replacePhonemes(request) },
)

fun Track.replacePhonemes(request: PhonemesMappingRequest) = copy(
notes = notes.mapNotNull { note -> note.replacePhonemes(request).takeIf { it.lyric.isNotEmpty() } }
.validateNotes(),
)

fun Note.replacePhonemes(request: PhonemesMappingRequest): Note {
val input = phoneme?.split(" ") ?: return this
val output = mutableListOf<String>()
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
break
}
}
if (!matched) {
output += input[pos]
pos++
}
}
return copy(phoneme = output.joinToString(" "))
}
63 changes: 63 additions & 0 deletions src/jsTest/kotlin/process/phonemes/PhonemesMappingTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package process.phonemes

import model.Note
import kotlin.test.Test
import kotlin.test.assertEquals

class PhonemesMappingTest {

private val request = PhonemesMappingRequest(
mapText = """
a=A
b=B
c a=C' A
c=C
d c a=DC' A
d c=DC
""".trimIndent(),
)

private fun createNote(phoneme: String) = Note(
id = 0,
key = 60,
lyric = "",
tickOn = 0L,
tickOff = 480L,
phoneme = phoneme,
)

@Test
fun testNoMatch() {
val note = createNote("l e")
val actual = note.replacePhonemes(request).phoneme
assertEquals("l e", actual)
}

@Test
fun testSingleMatch() {
val note = createNote("b")
val actual = note.replacePhonemes(request).phoneme
assertEquals("B", actual)
}

@Test
fun testSingleInMultipleMatch() {
val note = createNote("l a m b n")
val actual = note.replacePhonemes(request).phoneme
assertEquals("l A m B n", actual)
}

@Test
fun testMultipleMatch() {
val note = createNote("c a")
val actual = note.replacePhonemes(request).phoneme
assertEquals("C' A", actual)
}

@Test
fun testMultipleInMultipleMatch() {
val note = createNote("d c a m d c")
val actual = note.replacePhonemes(request).phoneme
assertEquals("DC' A m DC", actual)
}
}

0 comments on commit 544a4bf

Please sign in to comment.