From 29cc69519eedd91e5abc88c2362d83544c7386a3 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 17 Nov 2023 14:22:53 +0900 Subject: [PATCH] audio mixer thingy wip --- src/net/torvald/terrarum/App.java | 4 +- .../torvald/terrarum/AudioManagerRunnable.kt | 5 +- .../{AudioManager.kt => audio/AudioMixer.kt} | 77 +++++++++++-------- .../terrarum/audio/TerrarumAudioFilters.kt | 12 +++ .../audio/TerrarumAudioMixerTracks.kt | 55 +++++++++++++ .../modulebasegame/TerrarumMusicGovernor.kt | 5 +- 6 files changed, 117 insertions(+), 41 deletions(-) rename src/net/torvald/terrarum/{AudioManager.kt => audio/AudioMixer.kt} (53%) create mode 100644 src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt create mode 100644 src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt diff --git a/src/net/torvald/terrarum/App.java b/src/net/torvald/terrarum/App.java index d3d8cf0e9..c354b73a9 100644 --- a/src/net/torvald/terrarum/App.java +++ b/src/net/torvald/terrarum/App.java @@ -2,7 +2,6 @@ package net.torvald.terrarum; import com.badlogic.gdx.*; import com.badlogic.gdx.audio.AudioDevice; -import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl3.TerrarumLwjgl3Application; import com.badlogic.gdx.controllers.Controllers; @@ -16,6 +15,7 @@ import com.badlogic.gdx.utils.JsonValue; import com.github.strikerx3.jxinput.XInputDevice; import kotlin.text.Charsets; import net.torvald.getcpuname.GetCpuName; +import net.torvald.terrarum.audio.AudioMixer; import net.torvald.terrarum.controller.GdxControllerAdapter; import net.torvald.terrarum.controller.TerrarumController; import net.torvald.terrarum.controller.XinputControllerAdapter; @@ -1188,7 +1188,7 @@ public class App implements ApplicationListener { } - AudioManager.INSTANCE.getMasterVolume(); + AudioMixer.INSTANCE.getMasterVolume(); audioManagerThread = new Thread(new AudioManagerRunnable(), "TerrarumAudioManager"); audioManagerThread.start(); diff --git a/src/net/torvald/terrarum/AudioManagerRunnable.kt b/src/net/torvald/terrarum/AudioManagerRunnable.kt index f881172ea..3bfe1fcd6 100644 --- a/src/net/torvald/terrarum/AudioManagerRunnable.kt +++ b/src/net/torvald/terrarum/AudioManagerRunnable.kt @@ -1,7 +1,6 @@ package net.torvald.terrarum -import com.badlogic.gdx.Gdx -import net.torvald.terrarum.gamecontroller.InputStrober +import net.torvald.terrarum.audio.AudioMixer /** * Created by minjaesong on 2023-11-08. @@ -17,7 +16,7 @@ class AudioManagerRunnable : Runnable { val T = System.nanoTime() dT = (T - oldT) / 1000000000f oldT = T; - AudioManager.update(dT) + AudioMixer.update(dT) // println("AudioManagerRunnable dT = ${dT * 1000f} ms") Thread.sleep(30L) } diff --git a/src/net/torvald/terrarum/AudioManager.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt similarity index 53% rename from src/net/torvald/terrarum/AudioManager.kt rename to src/net/torvald/terrarum/audio/AudioMixer.kt index c29e9f212..f3e5f8aa2 100644 --- a/src/net/torvald/terrarum/AudioManager.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -1,8 +1,8 @@ -package net.torvald.terrarum +package net.torvald.terrarum.audio import com.badlogic.gdx.Gdx import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio -import net.torvald.terrarum.App.printdbg +import net.torvald.terrarum.App import net.torvald.terrarum.modulebasegame.MusicContainer /** @@ -10,48 +10,58 @@ import net.torvald.terrarum.modulebasegame.MusicContainer * * Created by minjaesong on 2023-11-07. */ -object AudioManager { - const val DEFAULT_FADEOUT_LEN = 2.4f +object AudioMixer { + const val DEFAULT_FADEOUT_LEN = 2.4 /** Returns a master volume */ - val masterVolume: Float - get() = App.getConfigDouble("mastervolume").toFloat() + val masterVolume: Double + get() = App.getConfigDouble("mastervolume") /** Returns a (master volume * bgm volume) */ - val musicVolume: Float - get() = (App.getConfigDouble("bgmvolume") * App.getConfigDouble("mastervolume")).toFloat() + val musicVolume: Double + get() = (App.getConfigDouble("bgmvolume") * App.getConfigDouble("mastervolume")) /** Returns a (master volume * sfx volume */ - val ambientVolume: Float - get() = (App.getConfigDouble("sfxvolume") * App.getConfigDouble("mastervolume")).toFloat() + val ambientVolume: Double + get() = (App.getConfigDouble("sfxvolume") * App.getConfigDouble("mastervolume")) - var currentMusic: MusicContainer? = null - var currentAmbient: MusicContainer? = null + private val tracks = Array(10) { TerrarumAudioMixerTracks() } - private var nextMusic: MusicContainer? = null + private val masterTrack = TerrarumAudioMixerTracks().also { master -> + tracks.forEach { master.sidechainInputs.add(it to 1.0) } + } - private var fadeAkku = 0f + private val musicTrack: TerrarumAudioMixerTracks + get() = tracks[0] + private val ambientTrack: TerrarumAudioMixerTracks + get() = tracks[1] + + private var fadeAkku = 0.0 private var fadeLength = DEFAULT_FADEOUT_LEN private var fadeoutFired = false private var fadeinFired = false + // TODO make sidechaining work + // TODO master volume controls the master track + // TODO fadein/out controls the master track + fun update(delta: Float) { (Gdx.audio as? Lwjgl3Audio)?.update() if (fadeoutFired) { fadeAkku += delta - currentMusic?.gdxMusic?.volume = (musicVolume * (1f - (fadeAkku / fadeLength))).coerceIn(0f, 1f) + musicTrack.volume = (musicVolume * (1.0 - (fadeAkku / fadeLength))).coerceIn(0.0, 1.0) // printdbg(this, "Fadeout fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}") if (fadeAkku >= fadeLength) { fadeoutFired = false - currentMusic?.gdxMusic?.volume = 0f + musicTrack.volume = 0.0 // currentMusic?.gdxMusic?.pause() - currentMusic = null + musicTrack.currentTrack = null // printdbg(this, "Fadeout end") } @@ -59,17 +69,17 @@ object AudioManager { // process fadein request else if (fadeinFired) { fadeAkku += delta - currentMusic?.gdxMusic?.volume = (musicVolume * (fadeAkku / fadeLength)).coerceIn(0f, 1f) + musicTrack.volume = (musicVolume * (fadeAkku / fadeLength)).coerceIn(0.0, 1.0) // printdbg(this, "Fadein fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}") - if (currentMusic?.gdxMusic?.isPlaying == false) { - currentMusic?.gdxMusic?.play() + if (musicTrack.isPlaying == false) { + musicTrack.play() // printdbg(this, "Fadein starting music ${currentMusic?.name}") } if (fadeAkku >= fadeLength) { - currentMusic?.gdxMusic?.volume = musicVolume + musicTrack.volume = musicVolume fadeinFired = false // printdbg(this, "Fadein end") @@ -77,38 +87,37 @@ object AudioManager { } - if (currentMusic?.gdxMusic?.isPlaying != true && nextMusic != null) { + if (musicTrack.isPlaying != true && musicTrack.nextTrack != null) { // printdbg(this, "Playing next music: ${nextMusic!!.name}") - currentMusic = nextMusic - nextMusic = null - currentMusic!!.gdxMusic.volume = musicVolume - currentMusic!!.gdxMusic.play() + musicTrack.queueNext(null) + musicTrack.volume = musicVolume + musicTrack.play() } } fun startMusic(song: MusicContainer) { - if (currentMusic?.gdxMusic?.isPlaying == true) { + if (musicTrack.isPlaying == true) { requestFadeOut(DEFAULT_FADEOUT_LEN) } - nextMusic = song + musicTrack.nextTrack = song } fun stopMusic() { requestFadeOut(DEFAULT_FADEOUT_LEN) } - fun requestFadeOut(length: Float) { + fun requestFadeOut(length: Double) { if (!fadeoutFired) { - fadeLength = length.coerceAtLeast(1f/1024f) - fadeAkku = 0f + fadeLength = length.coerceAtLeast(1.0/1024.0) + fadeAkku = 0.0 fadeoutFired = true } } - fun requestFadeIn(length: Float) { + fun requestFadeIn(length: Double) { if (!fadeinFired) { - fadeLength = length.coerceAtLeast(1f/1024f) - fadeAkku = 0f + fadeLength = length.coerceAtLeast(1.0/1024.0) + fadeAkku = 0.0 fadeinFired = true } } diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt b/src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt new file mode 100644 index 000000000..74f7dc5a0 --- /dev/null +++ b/src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt @@ -0,0 +1,12 @@ +package net.torvald.terrarum.audio + +interface TerrarumAudioFilters { + fun thru(inbufL: FloatArray, inbufR: FloatArray, outbufL: FloatArray, outbufR: FloatArray) +} + +object NullFilter: TerrarumAudioFilters { + override fun thru(inbufL: FloatArray, inbufR: FloatArray, outbufL: FloatArray, outbufR: FloatArray) { + System.arraycopy(inbufL, 0, outbufL, 0, inbufL.size) + System.arraycopy(inbufR, 0, outbufR, 0, inbufL.size) + } +} diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt new file mode 100644 index 000000000..88b09a6fb --- /dev/null +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt @@ -0,0 +1,55 @@ +package net.torvald.terrarum.audio + +import net.torvald.terrarum.getHashStr +import net.torvald.terrarum.modulebasegame.MusicContainer +import net.torvald.terrarum.utils.PasswordBase32 +import kotlin.math.log10 +import kotlin.math.pow + +typealias TrackVolume = Double + +class TerrarumAudioMixerTracks { + + val hash = getHashStr() + + var currentTrack: MusicContainer? = null + var nextTrack: MusicContainer? = null + + var volume: TrackVolume = 1.0 + get() = field + set(value) { + field = value + currentTrack?.gdxMusic?.volume = volume.toFloat() + } + + var pan = 0.0 + + var dBfs: Double + get() = fullscaleToDecibels(volume) + set(value) { volume = decibelsToFullscale(value) } + + val filters = arrayListOf() + val sidechainInputs = arrayListOf>() + + /** + * assign nextTrack to currentTrack, then assign nextNext to nextTrack. + * Whatever is on the currentTrack will be lost. + */ + fun queueNext(nextNext: MusicContainer? = null) { + currentTrack = nextTrack + nextTrack = nextNext + } + + fun play() { + currentTrack?.gdxMusic?.play() + } + + val isPlaying: Boolean? + get() = currentTrack?.gdxMusic?.isPlaying + + + override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTracks).hash +} + +fun fullscaleToDecibels(fs: Double) = 10.0 * log10(fs) +fun decibelsToFullscale(db: Double) = 10.0.pow(db / 10.0) \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt index 6cb4e235d..80836d1f6 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt @@ -5,6 +5,7 @@ import com.badlogic.gdx.audio.Music import com.badlogic.gdx.utils.GdxRuntimeException import net.torvald.terrarum.* import net.torvald.terrarum.App.printdbg +import net.torvald.terrarum.audio.AudioMixer import net.torvald.unicode.EMDASH import java.io.File @@ -67,7 +68,7 @@ class TerrarumMusicGovernor : MusicGovernor() { } private fun startMusic(song: MusicContainer) { - AudioManager.startMusic(song) + AudioMixer.startMusic(song) printdbg(this, "Now playing: $song") INGAME.sendNotification("Now Playing $EMDASH ${song.name}") state = STATE_PLAYING @@ -117,7 +118,7 @@ class TerrarumMusicGovernor : MusicGovernor() { } override fun dispose() { - AudioManager.stopMusic() // explicit call for fade-out when the game instance quits + AudioMixer.stopMusic() // explicit call for fade-out when the game instance quits stopMusic() } }