Skip to content

Commit 39db41b

Browse files
committed
Fix laggy lyrics issue
coercing AnimationTimeMillis (which is long) into float instead of double caused rounding errors when device uptime is high enough
1 parent 7b8504f commit 39db41b

2 files changed

Lines changed: 30 additions & 13 deletions

File tree

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ object CalculationUtils {
8888
return if (a != b) (value - a) / (b - a) else 0.0f
8989
}
9090

91+
@Suppress("NOTHING_TO_INLINE")
92+
inline fun lerp(start: Double, stop: Double, amount: Double): Double {
93+
return start + (stop - start) * amount
94+
}
95+
96+
/**
97+
* Returns the interpolation scalar (s) that satisfies the equation: `value = `[ ][.lerp]`(a, b, s)`
98+
*
99+
*
100+
* If `a == b`, then this function will return 0.
101+
*/
102+
@Suppress("NOTHING_TO_INLINE")
103+
inline fun lerpInv(a: Double, b: Double, value: Double): Double {
104+
return if (a != b) (value - a) / (b - a) else 0.0
105+
}
106+
91107
/** Returns the single argument constrained between [0.0, 1.0]. */
92108
private fun saturate(value: Float): Float {
93109
return value.coerceAtLeast(0f).coerceAtMost(1f)

app/src/main/java/org/akanework/gramophone/ui/components/NewLyricsView.kt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import kotlin.math.max
4343
import kotlin.math.min
4444
import kotlin.math.roundToInt
4545
import kotlin.properties.Delegates
46+
import kotlin.time.toDuration
4647

4748
private const val TAG = "NewLyricsView"
4849

@@ -78,7 +79,7 @@ class NewLyricsView(context: Context, attrs: AttributeSet?) : ScrollingView2(con
7879
lateinit var instance: Callbacks
7980
private val gestureDetector = GestureDetector(context, this)
8081
private var currentScrollTarget: Int? = null
81-
private var currentSmoothScroll: Pair<Pair<Float, Float>, Pair<Float, Float>>? = null
82+
private var currentSmoothScroll: Pair<Pair<Double, Double>, Pair<Float, Float>>? = null
8283
private var delayedScrollAnimation: Pair<Long, Pair<Int, Int>>? = null
8384
private var stateOverrides = hashMapOf<Int, Float>()
8485
private var stateTime = 0uL
@@ -292,7 +293,7 @@ class NewLyricsView(context: Context, attrs: AttributeSet?) : ScrollingView2(con
292293
canvas.save()
293294
canvas.translate(globalPaddingHorizontal, globalPaddingTop.toFloat())
294295
val width = width - globalPaddingHorizontal * 2
295-
val cat = AnimationUtils.currentAnimationTimeMillis().toFloat()
296+
val cat = AnimationUtils.currentAnimationTimeMillis().toDouble()
296297
spForRender!!.second.forEachIndexed { i, it ->
297298
var spanEnd = -1
298299
var spanStartGradient = -1
@@ -441,20 +442,20 @@ class NewLyricsView(context: Context, attrs: AttributeSet?) : ScrollingView2(con
441442
.second.first + 1, i + 1).find { it.line?.isTranslated != true } != null) {
442443
val ii = spForRender!!.second.subList(delayedScrollAnimation!!.second.first + 1,
443444
i + 1).sumOf { if (it.line?.isTranslated == true) 0 else 1 }
444-
val duration = (lyricAnimTime * 0.278).toLong()
445-
val durationReturn = (lyricAnimTime * 0.722).toLong()
446-
val durationStep = (lyricAnimTime * 0.1).toLong()
447-
val start = delayedScrollAnimation!!.first.toFloat()
445+
val duration = lyricAnimTime * 0.278
446+
val durationReturn = lyricAnimTime * 0.722
447+
val durationStep = lyricAnimTime * 0.1
448+
val start = delayedScrollAnimation!!.first.toDouble()
448449
val end = start + duration + durationReturn + ii * durationStep
449450
if (end > cat) { // animation is still ongoing
450451
if (!culledDown) {
451452
val middle = start + duration
452453
delayedScrollOffset += if (middle <= cat) {
453-
val progress = lerpInv(middle, end, cat)
454+
val progress = lerpInv(middle, end, cat).toFloat()
454455
val p = delayedOutInterpolator.getInterpolation(progress)
455456
lerp(depth, 0f, p)
456457
} else {
457-
val progress = lerpInv(start, middle, cat)
458+
val progress = lerpInv(start, middle, cat).toFloat()
458459
val p = delayedInInterpolator.getInterpolation(progress)
459460
lerp(0f, depth, p)
460461
}.toInt()
@@ -671,8 +672,8 @@ class NewLyricsView(context: Context, attrs: AttributeSet?) : ScrollingView2(con
671672
scrollTo(0, scrollTarget)
672673
} else {
673674
currentScrollTarget = scrollTarget
674-
currentSmoothScroll = (AnimationUtils.currentAnimationTimeMillis().toFloat() to
675-
lyricAnimTime) to (scrollY.toFloat() to scrollTarget.toFloat())
675+
currentSmoothScroll = (AnimationUtils.currentAnimationTimeMillis().toDouble() to
676+
lyricAnimTime.toDouble()) to (scrollY.toFloat() to scrollTarget.toFloat())
676677
runAnimatedScroll(false)
677678
if (scrollY < scrollTarget) {
678679
delayedScrollAnimation = if (scrollTargetIndex != null) AnimationUtils
@@ -961,17 +962,17 @@ class NewLyricsView(context: Context, attrs: AttributeSet?) : ScrollingView2(con
961962
stateTime = to
962963
}
963964

964-
private fun getScrollProgressAt(time: Float): Int {
965+
private fun getScrollProgressAt(time: Double): Int {
965966
val progress = lerpInv(currentSmoothScroll!!.first.first, currentSmoothScroll!!
966-
.first.first + currentSmoothScroll!!.first.second, time)
967+
.first.first + currentSmoothScroll!!.first.second, time).toFloat()
967968
val interpolatedProgress = scrollInterpolator.getInterpolation(min(1f,
968969
progress))
969970
return lerp(currentSmoothScroll!!.second.first, currentSmoothScroll!!
970971
.second.second, interpolatedProgress).toInt()
971972
}
972973

973974
override fun computeScrollInner(): Long {
974-
val cat = AnimationUtils.currentAnimationTimeMillis().toFloat()
975+
val cat = AnimationUtils.currentAnimationTimeMillis().toDouble()
975976
val q = getScrollProgressAt(cat)
976977
val q1 = getScrollProgressAt(cat - 1000f)
977978
val distance = currentSmoothScroll!!.first.second

0 commit comments

Comments
 (0)