Skip to content

Commit 20103b9

Browse files
committed
Correctly parse translations for blank lyrics
Some lyrics providers have lyrics that use duplicated timestamps for formatting reasons, causing the blank line to be parsed as the main lyric, and the second (actual line) to be parsed as a translation. After this change, blank lines will not be eligible for translation. See the following for an example: [00:23.73]I see the world through eyes covered in ink and bleach [00:29.70]Cross out the ones who heard my cries and watched me weep [00:35.64] [00:35.64]I love everything [00:38.51]Fire's spreading all around my room [00:43.13]My world's so bright [00:44.42]It's hard to breathe but that's alright [00:47.32]Hush [00:59.22] [00:59.22]Shh [01:11.46] [01:11.46]Tape my eyes open to force reality (oh no, no) [01:17.99]Why can't you just let me eat my weight in glee?
1 parent 9f3f006 commit 20103b9

File tree

3 files changed

+33
-8
lines changed

3 files changed

+33
-8
lines changed

app/src/main/java/org/akanework/gramophone/logic/utils/SemanticLyrics.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -705,20 +705,21 @@ fun parseLrc(lyricText: String, trimEnabled: Boolean, multiLineEnabled: Boolean)
705705
}
706706
}
707707
out.sortBy { it.start }
708-
var previousTimestamp = ULong.MAX_VALUE
708+
var previousLyric: LyricLine? = null
709709
val defaultIsWalaokeM = out.find { it.speaker?.isWalaoke == true } != null &&
710710
out.find { it.speaker?.isWalaoke == false } == null
711711
out.forEachIndexed { i, lyric ->
712712
if (defaultIsWalaokeM && lyric.speaker == null)
713713
lyric.speaker = SpeakerEntity.Male
714714
lyric.end = lyric.end.takeIf { it != 0uL }
715715
?: lyric.words?.lastOrNull()?.timeRange?.last
716-
?: (if (lyric.start == previousTimestamp) out.find { it.start == lyric.start }
716+
?: (if (lyric.start == previousLyric?.start) out.find { it.start == lyric.start }
717717
?.words?.lastOrNull()?.timeRange?.last else null)
718718
?: out.find { it.start > lyric.start }?.start?.minus(1uL)
719719
?: Long.MAX_VALUE.toULong()
720-
lyric.isTranslated = lyric.start == previousTimestamp
721-
previousTimestamp = lyric.start
720+
lyric.isTranslated = lyric.start == previousLyric?.start
721+
&& (previousLyric.text.isNotBlank() || lyric.text.isBlank())
722+
previousLyric = lyric
722723
}
723724
while (out.firstOrNull()?.text?.isBlank() == true)
724725
out.removeAt(0)

app/src/test/java/org/akanework/gramophone/LrcTestData.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ object LrcTestData {
324324
[00:13.000]In the shape of an "L" on her forehead
325325
[00:18.300]Well, the hits start coming and they don't stop coming
326326
[00:21.600]Head to the rules and ya hit the ground running
327-
[00:24.300]Didn't make sense just to live for fun,
327+
[00:24.300]
328328
[00:26.300]You're brain gets smart but your head gets dumb
329329
[00:28.600]So much to do so much to see
330330
[00:30.600]So what's wrong with takin the backstreets
@@ -377,7 +377,7 @@ object LrcTestData {
377377
[00:13.000]她手指在额头前摆出的“L”的形状
378378
[00:18.300]好了 新的时代正在来临 他们无法阻止
379379
[00:21.600]早已厌烦了老套的规则 奔跑着用双脚撞击地面
380-
[00:24.300]没有意义只是为了好玩
380+
[00:24.300]
381381
[00:26.300]你的大脑变得又聪明又愚蠢
382382
[00:28.600]那么多事要做 那么多话要说
383383
[00:30.600]让我们代替后街男孩又如何
@@ -435,8 +435,8 @@ object LrcTestData {
435435
LyricLine(start = 18300uL, text = """好了 新的时代正在来临 他们无法阻止""", words = null, speaker = null, end = 21599uL, isTranslated = true),
436436
LyricLine(start = 21600uL, text = """Head to the rules and ya hit the ground running""", words = null, speaker = null, end = 24299uL, isTranslated = false),
437437
LyricLine(start = 21600uL, text = """早已厌烦了老套的规则 奔跑着用双脚撞击地面""", words = null, speaker = null, end = 24299uL, isTranslated = true),
438-
LyricLine(start = 24300uL, text = """Didn't make sense just to live for fun,""", words = null, speaker = null, end = 26299uL, isTranslated = false),
439-
LyricLine(start = 24300uL, text = """没有意义只是为了好玩""", words = null, speaker = null, end = 26299uL, isTranslated = true),
438+
LyricLine(start = 24300uL, text = """""", words = null, speaker = null, end = 26299uL, isTranslated = false),
439+
LyricLine(start = 24300uL, text = """""", words = null, speaker = null, end = 26299uL, isTranslated = true),
440440
LyricLine(start = 26300uL, text = """You're brain gets smart but your head gets dumb""", words = null, speaker = null, end = 28599uL, isTranslated = false),
441441
LyricLine(start = 26300uL, text = """你的大脑变得又聪明又愚蠢""", words = null, speaker = null, end = 28599uL, isTranslated = true),
442442
LyricLine(start = 28600uL, text = """So much to do so much to see""", words = null, speaker = null, end = 30599uL, isTranslated = false),

app/src/test/java/org/akanework/gramophone/LrcUtilsTest.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.akanework.gramophone
33
import androidx.media3.common.MimeTypes
44
import org.akanework.gramophone.logic.utils.LrcUtils
55
import org.akanework.gramophone.logic.utils.SemanticLyrics
6+
import org.akanework.gramophone.logic.utils.SemanticLyrics.LyricLine
67
import org.junit.Assert.assertEquals
78
import org.junit.Assert.assertFalse
89
import org.junit.Assert.assertNotEquals
@@ -230,6 +231,29 @@ class LrcUtilsTest {
230231
assertEquals(204uL, lrc[1].start)
231232
}
232233

234+
@Test
235+
fun testEmptyLyricNoTranslation() {
236+
val lrc = parseSynced("[00:00.29]It's hard to breathe but that's alright\n[00:04.45]\n[00:04.45]Hush\n[00:14.23]\n[00:16.25]Shh")
237+
assertNotNull(lrc)
238+
assertEquals(5, lrc!!.size)
239+
240+
assertEquals("It's hard to breathe but that's alright", lrc[0].text)
241+
assertEquals(290uL, lrc[0].start)
242+
assertEquals(false, lrc[0].isTranslated)
243+
assertEquals("", lrc[1].text)
244+
assertEquals(4450uL, lrc[1].start)
245+
assertEquals(false, lrc[1].isTranslated)
246+
assertEquals("Hush", lrc[2].text)
247+
assertEquals(4450uL, lrc[2].start)
248+
assertEquals(false, lrc[2].isTranslated)
249+
assertEquals("", lrc[3].text)
250+
assertEquals(14230uL, lrc[3].start)
251+
assertEquals(false, lrc[3].isTranslated)
252+
assertEquals("Shh", lrc[4].text)
253+
assertEquals(16250uL, lrc[4].start)
254+
assertEquals(false, lrc[4].isTranslated)
255+
}
256+
233257
@Test
234258
fun testOnlyWordSyncPoints() {
235259
val lrc = parseSynced("<00:00.02>a<00:01.00>l\n<00:03.00>b")

0 commit comments

Comments
 (0)