From 1a49921c77b26e111cee44c3cad1fd287f526284 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 20 Nov 2023 22:02:57 +0900 Subject: [PATCH] softlimiter filter for master --- src/net/torvald/terrarum/audio/AudioMixer.kt | 37 +++++++++++-------- .../terrarum/audio/MixerTrackProcessor.kt | 15 -------- .../terrarum/audio/TerrarumAudioFilter.kt | 14 +++++++ .../terrarum/audio/TerrarumAudioMixerTrack.kt | 4 +- .../modulebasegame/TerrarumMusicGovernor.kt | 3 +- .../terrarum/ui/BasicDebugInfoWindow.kt | 20 +++++++--- 6 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt index f147bd1c8..51c6b6594 100644 --- a/src/net/torvald/terrarum/audio/AudioMixer.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -5,13 +5,8 @@ import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio import com.badlogic.gdx.utils.Disposable import com.jme3.math.FastMath import net.torvald.terrarum.App -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.INDEX_AMB -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.INDEX_BGM import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.tryDispose import java.lang.Thread.MAX_PRIORITY @@ -100,7 +95,8 @@ object AudioMixer: Disposable { init { - masterTrack.filters[0] = Buffer + masterTrack.filters[0] = SoftLim + masterTrack.filters[1] = Buffer fadeBus.addSidechainInput(musicTrack, 1.0) fadeBus.addSidechainInput(ambientTrack, 1.0) @@ -165,10 +161,13 @@ object AudioMixer: Disposable { if (req.fadeAkku >= req.fadeLength) { req.fadeoutFired = false track.volume = req.fadeTarget - track.volume = req.fadeTarget - if (req.fadeTarget == 0.0) { - track.currentTrack = null + // stop streaming if fadeBus is muted + if (req.fadeTarget == 0.0 && track == fadeBus) { + musicTrack.currentTrack = null + musicTrack.streamPlaying = false + ambientTrack.currentTrack = null + ambientTrack.streamPlaying = false } } } @@ -216,12 +215,17 @@ object AudioMixer: Disposable { } - if (musicTrack.isPlaying != true && musicTrack.nextTrack != null) { -// printdbg(this, "Playing next music: ${nextMusic!!.name}") + if (!musicTrack.isPlaying && musicTrack.nextTrack != null) { musicTrack.queueNext(null) fadeBus.volume = 1.0 musicTrack.play() } + + if (!ambientTrack.isPlaying && ambientTrack.nextTrack != null) { + ambientTrack.queueNext(null) + requestFadeIn(ambientTrack, DEFAULT_FADEOUT_LEN * 4, 1.0, 0.00001) + ambientTrack.play() + } } fun startMusic(song: MusicContainer) { @@ -240,31 +244,32 @@ object AudioMixer: Disposable { requestFadeOut(musicTrack, DEFAULT_FADEOUT_LEN) } ambientTrack.nextTrack = song + // fade will be processed by the update() } fun stopAmb() { - requestFadeOut(musicTrack, DEFAULT_FADEOUT_LEN) + requestFadeOut(ambientTrack, DEFAULT_FADEOUT_LEN * 4) } - fun requestFadeOut(track: TerrarumAudioMixerTrack, length: Double, target: Double = 0.0) { + fun requestFadeOut(track: TerrarumAudioMixerTrack, length: Double, target: Double = 0.0, source: Double? = null) { val req = fadeReqs[track]!! if (!req.fadeoutFired) { req.fadeLength = length.coerceAtLeast(1.0/1024.0) req.fadeAkku = 0.0 req.fadeoutFired = true req.fadeTarget = target * track.maxVolume - req.fadeStart = fadeBus.volume + req.fadeStart = source ?: fadeBus.volume } } - fun requestFadeIn(track: TerrarumAudioMixerTrack, length: Double, target: Double = 1.0) { + fun requestFadeIn(track: TerrarumAudioMixerTrack, length: Double, target: Double = 1.0, source: Double? = null) { val req = fadeReqs[track]!! if (!req.fadeinFired) { req.fadeLength = length.coerceAtLeast(1.0/1024.0) req.fadeAkku = 0.0 req.fadeinFired = true req.fadeTarget = target * track.maxVolume - req.fadeStart = fadeBus.volume + req.fadeStart = source ?: fadeBus.volume } } diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 72a1ee16b..616bd153d 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -2,7 +2,6 @@ package net.torvald.terrarum.audio import com.badlogic.gdx.utils.Queue import net.torvald.reflection.forceInvoke -import org.apache.commons.math3.special.Erf.erf import kotlin.math.absoluteValue import kotlin.math.tanh @@ -105,20 +104,6 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru samplesR1!![i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat() } } - // de-clip using sigmoid function - for (i in samplesL0.indices) { - samplesL0[i] = erf(samplesL0[i].toDouble()).toFloat() - samplesR0[i] = erf(samplesR0[i].toDouble()).toFloat() - samplesL1[i] = erf(samplesL1[i].toDouble()).toFloat() - samplesR1[i] = erf(samplesR1[i].toDouble()).toFloat() - } - - /*track.sidechainInputs[TerrarumAudioMixerTrack.INDEX_BGM]?.let { (side, mix) -> - samplesL0 = side.processor.fout0[0].applyVolume((mix * track.volume).toFloat()) // must not applyVolumeInline - samplesR0 = side.processor.fout0[1].applyVolume((mix * track.volume).toFloat()) - samplesL1 = side.processor.fout1[0].applyVolume((mix * track.volume).toFloat()) - samplesR1 = side.processor.fout1[1].applyVolume((mix * track.volume).toFloat()) - }*/ } // source channel: skip processing if there's no active input // else if (track.getSidechains().any { it != null && !it.isBus && !it.isMaster && !it.streamPlaying } && !track.streamPlaying) { diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt index 47e09f6ba..0f99a20c0 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt @@ -1,6 +1,7 @@ package net.torvald.terrarum.audio import com.jme3.math.FastMath +import kotlin.math.tanh abstract class TerrarumAudioFilter { var bypass = false @@ -23,6 +24,19 @@ object NullFilter : TerrarumAudioFilter() { } } +object SoftLim : TerrarumAudioFilter() { + override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + for (ch in inbuf1.indices) { + val inn = inbuf1[ch] + val out = outbuf1[ch] + + for (i in inn.indices) { + out[i] = tanh(inn[i]) + } + } + } +} + class Lowpass(cutoff0: Float, val rate: Int): TerrarumAudioFilter() { diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index 16fb7379d..b410423b2 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt @@ -115,8 +115,8 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v // currentTrack?.gdxMusic?.play() } - val isPlaying: Boolean? - get() = currentTrack?.gdxMusic?.isPlaying + val isPlaying: Boolean + get() = streamPlaying//currentTrack?.gdxMusic?.isPlaying override fun dispose() { /*if (isMaster) { // uncomment to multithread diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt index 15edf7519..4e036e4f2 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt @@ -50,7 +50,7 @@ class TerrarumMusicGovernor : MusicGovernor() { it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "), it, Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath)) - ) { stopMusic() } + ) { stopAmbient() } } catch (e: GdxRuntimeException) { e.printStackTrace() @@ -123,6 +123,7 @@ class TerrarumMusicGovernor : MusicGovernor() { // val ingame = ingame as TerrarumIngame if (musicState == 0) musicState = STATE_INTERMISSION + if (ambState == 0) ambState = STATE_INTERMISSION when (musicState) { diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index d992a52c0..db81a6827 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -375,9 +375,9 @@ class BasicDebugInfoWindow : UICanvas() { private val stripW = 56 private val stripGap = 1 - private val stripFilterHeight = 32 + private val stripFilterHeight = 16 private val stripFaderHeight = 200 - private val numberOfFilters = 5 + private val numberOfFilters = 10 private val stripH = stripFaderHeight + stripFilterHeight * numberOfFilters + 16 private val COL_WELL = Color(0x374854_aa) @@ -443,17 +443,20 @@ class BasicDebugInfoWindow : UICanvas() { batch.color = COL_FILTER_WELL_BACK Toolkit.fillArea(batch, x, y, stripW, stripFilterHeight * numberOfFilters) + var filterBankYcursor = 0 track.filters.forEachIndexed { i, filter -> if (filter !is NullFilter) { // draw filter title back batch.color = COL_FILTER_TITLE_SHADE - Toolkit.fillArea(batch, x, y + stripFilterHeight * i, stripW, 16) + Toolkit.fillArea(batch, x, y + filterBankYcursor, stripW, 16) batch.color = COL_FILTER_TITLE - Toolkit.fillArea(batch, x, y + stripFilterHeight * i, stripW, 14) + Toolkit.fillArea(batch, x, y + filterBankYcursor, stripW, 14) // draw filter name batch.color = if (filter.bypass) FILTER_BYPASSED else FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, filter.javaClass.simpleName, x + 3f, y + stripFilterHeight * i + 1f) + App.fontSmallNumbers.draw(batch, filter.javaClass.simpleName, x + 3f, y + filterBankYcursor + 1f) - drawFilterParam(batch, x, y + stripFilterHeight * i + 16, filter, track) + drawFilterParam(batch, x, y + filterBankYcursor + stripFilterHeight, filter, track) + + filterBankYcursor += stripFilterHeight + paramViewHeight.getOrDefault(filter.javaClass.simpleName, 0) } } val faderY = y + stripFilterHeight * numberOfFilters @@ -537,6 +540,11 @@ class BasicDebugInfoWindow : UICanvas() { } } + private val paramViewHeight = hashMapOf( + "Lowpass" to 16, + "Buffer" to 32, + ) + private fun drawFilterParam(batch: SpriteBatch, x: Int, y: Int, filter: TerrarumAudioFilter, track: TerrarumAudioMixerTrack) { when (filter) { is Lowpass -> {