fix: fade state may get inconsistent on rapid ui open-close; correct logscale impl

This commit is contained in:
minjaesong
2023-11-19 20:05:44 +09:00
parent d77b8087cb
commit 04144fff08
7 changed files with 39 additions and 24 deletions

View File

@@ -11,9 +11,7 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RAT
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF
import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.MusicContainer
import net.torvald.terrarum.tryDispose import net.torvald.terrarum.tryDispose
import kotlin.math.log import kotlin.math.*
import kotlin.math.log10
import kotlin.math.pow
/** /**
* Any audio reference fed into this manager will get lost; you must manually store and dispose of them on your own. * Any audio reference fed into this manager will get lost; you must manually store and dispose of them on your own.
@@ -79,6 +77,8 @@ object AudioMixer: Disposable {
private var lpLength = 0.4 private var lpLength = 0.4
private var lpOutFired = false private var lpOutFired = false
private var lpInFired = false private var lpInFired = false
private var lpStart = SAMPLING_RATED / 2.0
private var lpTarget = SAMPLING_RATED / 2.0
// TODO make sidechaining work // TODO make sidechaining work
// TODO master volume controls the master track // TODO master volume controls the master track
@@ -122,28 +122,30 @@ object AudioMixer: Disposable {
if (lpOutFired) { if (lpOutFired) {
lpAkku += delta lpAkku += delta
val x = lpAkku / lpLength // https://www.desmos.com/calculator/dmhve2awxm
val q = 400.0 val t = (lpAkku / lpLength).coerceIn(0.0, 1.0)
val step = (q.pow(x) - 1) / (q - 1) // https://www.desmos.com/calculator/sttaq2qhzm val b = ln(lpStart / lpTarget) / -1.0
val cutoff = FastMath.interpolateLinear(step, SAMPLING_RATED / 100.0, SAMPLING_RATED) val a = lpStart
val cutoff = a * exp(b * t)
faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(cutoff) } faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(cutoff) }
if (lpAkku >= lpLength) { if (lpAkku >= lpLength) {
lpOutFired = false lpOutFired = false
faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(SAMPLING_RATEF) } faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(lpTarget) }
} }
} }
else if (lpInFired) { else if (lpInFired) {
lpAkku += delta lpAkku += delta
val x = lpAkku / lpLength // https://www.desmos.com/calculator/dmhve2awxm
val q = 400.0 val t = (lpAkku / lpLength).coerceIn(0.0, 1.0)
val step = log((q-1) * x + 1.0, q) // https://www.desmos.com/calculator/sttaq2qhzm val b = ln(lpStart / lpTarget) / -1.0
val cutoff = FastMath.interpolateLinear(step, SAMPLING_RATED, SAMPLING_RATED / 100.0) val a = lpStart
val cutoff = a * exp(b * t)
faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(cutoff) } faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(cutoff) }
if (lpAkku >= lpLength) { if (lpAkku >= lpLength) {
faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(SAMPLING_RATEF / 100.0) } faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(lpTarget) }
lpInFired = false lpInFired = false
} }
} }
@@ -194,6 +196,8 @@ object AudioMixer: Disposable {
lpLength = length.coerceAtLeast(1.0/1024.0) lpLength = length.coerceAtLeast(1.0/1024.0)
lpAkku = 0.0 lpAkku = 0.0
lpOutFired = true lpOutFired = true
lpStart = (musicTrack.filters[0] as Lowpass).cutoff
lpTarget = SAMPLING_RATED / 2.0
} }
} }
@@ -202,6 +206,8 @@ object AudioMixer: Disposable {
lpLength = length.coerceAtLeast(1.0/1024.0) lpLength = length.coerceAtLeast(1.0/1024.0)
lpAkku = 0.0 lpAkku = 0.0
lpInFired = true lpInFired = true
lpStart = (musicTrack.filters[0] as Lowpass).cutoff
lpTarget = SAMPLING_RATED / 100.0
} }
} }

View File

@@ -302,7 +302,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
override fun show() { override fun show() {
Gdx.input.inputProcessor = BuildingMakerController(this) Gdx.input.inputProcessor = BuildingMakerController(this)
(AudioMixer.musicTrack.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF) (AudioMixer.musicTrack.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2)
super.show() super.show()
} }

View File

@@ -292,7 +292,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
IngameRenderer.setRenderedWorld(world) IngameRenderer.setRenderedWorld(world)
blockMarkingActor.isVisible = true blockMarkingActor.isVisible = true
AudioMixer.faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(SAMPLING_RATEF) } AudioMixer.faderTrack.forEach { (it.filters[0] as Lowpass).setCutoff(SAMPLING_RATEF / 2) }
super.show() // this function sets gameInitialised = true super.show() // this function sets gameInitialised = true

View File

@@ -296,7 +296,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
UILoadGovernor.reset() UILoadGovernor.reset()
(AudioMixer.musicTrack.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF) (AudioMixer.musicTrack.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2)
loadThingsWhileIntroIsVisible() loadThingsWhileIntroIsVisible()

View File

@@ -365,8 +365,8 @@ class UIInventoryFull(
INGAME.pause() INGAME.pause()
INGAME.setTooltipMessage(null) INGAME.setTooltipMessage(null)
AudioMixer.requestLowpassIn(0.4) AudioMixer.requestLowpassIn(0.3)
AudioMixer.requestFadeOut(0.4, 0.5) AudioMixer.requestFadeOut(0.3, 0.5)
} }
override fun doClosing(delta: Float) { override fun doClosing(delta: Float) {
@@ -375,8 +375,8 @@ class UIInventoryFull(
INGAME.resume() INGAME.resume()
INGAME.setTooltipMessage(null) INGAME.setTooltipMessage(null)
AudioMixer.requestLowpassOut(0.4) AudioMixer.requestLowpassOut(0.3)
AudioMixer.requestFadeIn(0.4, 1.0) AudioMixer.requestFadeIn(0.3, 1.0)
} }
override fun endOpening(delta: Float) { override fun endOpening(delta: Float) {

View File

@@ -14,6 +14,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.*
import net.torvald.terrarum.audio.MixerTrackProcessor.Companion.BACK_BUF_COUNT import net.torvald.terrarum.audio.MixerTrackProcessor.Companion.BACK_BUF_COUNT
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED
import net.torvald.terrarum.controller.TerrarumController import net.torvald.terrarum.controller.TerrarumController
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.gameworld.fmod
@@ -27,9 +28,7 @@ import net.torvald.terrarum.weather.WeatherStateBox
import net.torvald.terrarum.worlddrawer.LightmapRenderer import net.torvald.terrarum.worlddrawer.LightmapRenderer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import kotlin.math.absoluteValue import kotlin.math.*
import kotlin.math.max
import kotlin.math.roundToInt
/** /**
* Created by minjaesong on 2016-03-14. * Created by minjaesong on 2016-03-14.
@@ -499,6 +498,16 @@ class BasicDebugInfoWindow : UICanvas() {
private fun drawFilterParam(batch: SpriteBatch, x: Int, y: Int, filter: TerrarumAudioFilter, track: TerrarumAudioMixerTrack) { private fun drawFilterParam(batch: SpriteBatch, x: Int, y: Int, filter: TerrarumAudioFilter, track: TerrarumAudioMixerTrack) {
when (filter) { when (filter) {
is Lowpass -> { is Lowpass -> {
// https://www.desmos.com/calculator/dmhve2awxm
val f = filter.cutoff
val b = ln(24 / 24000.0) / -1.0
val a = 24.0
val perc = (ln(f / a) / b).toFloat()
batch.color = COL_METER_GRAD2
Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), stripW * perc, 14f)
batch.color = COL_METER_GRAD
Toolkit.fillArea(batch, x.toFloat(), y+14f, stripW * perc, 2f)
batch.color = FILTER_NAME_ACTIVE batch.color = FILTER_NAME_ACTIVE
App.fontSmallNumbers.draw(batch, "F:${filter.cutoff.toInt()}", x+3f, y+1f) App.fontSmallNumbers.draw(batch, "F:${filter.cutoff.toInt()}", x+3f, y+1f)
} }

View File

@@ -341,7 +341,7 @@ abstract class UICanvas(
} }
companion object { companion object {
const val OPENCLOSE_GENERIC = 0.0666f const val OPENCLOSE_GENERIC = 0.1f
fun doOpeningFade(ui: UICanvas, openCloseTime: Second) { fun doOpeningFade(ui: UICanvas, openCloseTime: Second) {
ui.handler.opacity = max(0f, ui.handler.openCloseCounter - 0.02f) / openCloseTime // fade start 1/50 sec late, it's intended ui.handler.opacity = max(0f, ui.handler.openCloseCounter - 0.02f) / openCloseTime // fade start 1/50 sec late, it's intended