diff --git a/app/src/main/kotlin/net/jeena/pacer/AudioEngine.kt b/app/src/main/kotlin/net/jeena/pacer/AudioEngine.kt index 58f7b9e..fefc153 100644 --- a/app/src/main/kotlin/net/jeena/pacer/AudioEngine.kt +++ b/app/src/main/kotlin/net/jeena/pacer/AudioEngine.kt @@ -1,6 +1,7 @@ package net.jeena.pacer import android.media.AudioAttributes +import kotlin.math.pow import android.media.AudioFormat import android.media.AudioTrack import android.os.Handler @@ -23,10 +24,16 @@ class AudioEngine { private const val BEEP_DURATION_MS = 40 private const val SILENCE_CHUNK_MS = 10 - // Apply a square curve so the slider feels linear to human hearing. - // AudioTrack.setVolume() takes a linear amplitude; our 0-1 slider - // value is perceived as "all the volume at the bottom" without this. - private fun toAmplitude(linear: Float): Float = linear * linear + // Map the linear 0-1 slider to a perceptually even loudness curve. + // AudioTrack.setVolume() takes a linear amplitude, but human hearing + // is logarithmic: equal dB steps sound like equal volume steps. + // We map the slider to a -40 dB … 0 dB range, so each 25% of travel + // changes perceived loudness by the same amount. + private fun toAmplitude(linear: Float): Float { + if (linear <= 0f) return 0f + val db = -40f * (1f - linear) // 0.0 → -40 dB, 1.0 → 0 dB + return 10f.pow(db / 20f) + } } private val mainHandler = Handler(Looper.getMainLooper())