mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-16 21:44:05 +09:00
audio mixer thingy wip
This commit is contained in:
125
src/net/torvald/terrarum/audio/AudioMixer.kt
Normal file
125
src/net/torvald/terrarum/audio/AudioMixer.kt
Normal file
@@ -0,0 +1,125 @@
|
||||
package net.torvald.terrarum.audio
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.modulebasegame.MusicContainer
|
||||
|
||||
/**
|
||||
* Any audio reference fed into this manager will get lost; you must manually store and dispose of them on your own.
|
||||
*
|
||||
* Created by minjaesong on 2023-11-07.
|
||||
*/
|
||||
object AudioMixer {
|
||||
const val DEFAULT_FADEOUT_LEN = 2.4
|
||||
|
||||
/** Returns a master volume */
|
||||
val masterVolume: Double
|
||||
get() = App.getConfigDouble("mastervolume")
|
||||
|
||||
/** Returns a (master volume * bgm volume) */
|
||||
val musicVolume: Double
|
||||
get() = (App.getConfigDouble("bgmvolume") * App.getConfigDouble("mastervolume"))
|
||||
|
||||
/** Returns a (master volume * sfx volume */
|
||||
val ambientVolume: Double
|
||||
get() = (App.getConfigDouble("sfxvolume") * App.getConfigDouble("mastervolume"))
|
||||
|
||||
|
||||
private val tracks = Array(10) { TerrarumAudioMixerTracks() }
|
||||
|
||||
private val masterTrack = TerrarumAudioMixerTracks().also { master ->
|
||||
tracks.forEach { master.sidechainInputs.add(it to 1.0) }
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
musicTrack.volume = 0.0
|
||||
// currentMusic?.gdxMusic?.pause()
|
||||
musicTrack.currentTrack = null
|
||||
|
||||
// printdbg(this, "Fadeout end")
|
||||
}
|
||||
}
|
||||
// process fadein request
|
||||
else if (fadeinFired) {
|
||||
fadeAkku += delta
|
||||
musicTrack.volume = (musicVolume * (fadeAkku / fadeLength)).coerceIn(0.0, 1.0)
|
||||
|
||||
// printdbg(this, "Fadein fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
|
||||
|
||||
if (musicTrack.isPlaying == false) {
|
||||
musicTrack.play()
|
||||
// printdbg(this, "Fadein starting music ${currentMusic?.name}")
|
||||
}
|
||||
|
||||
if (fadeAkku >= fadeLength) {
|
||||
musicTrack.volume = musicVolume
|
||||
fadeinFired = false
|
||||
|
||||
// printdbg(this, "Fadein end")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (musicTrack.isPlaying != true && musicTrack.nextTrack != null) {
|
||||
// printdbg(this, "Playing next music: ${nextMusic!!.name}")
|
||||
musicTrack.queueNext(null)
|
||||
musicTrack.volume = musicVolume
|
||||
musicTrack.play()
|
||||
}
|
||||
}
|
||||
|
||||
fun startMusic(song: MusicContainer) {
|
||||
if (musicTrack.isPlaying == true) {
|
||||
requestFadeOut(DEFAULT_FADEOUT_LEN)
|
||||
}
|
||||
musicTrack.nextTrack = song
|
||||
}
|
||||
|
||||
fun stopMusic() {
|
||||
requestFadeOut(DEFAULT_FADEOUT_LEN)
|
||||
}
|
||||
|
||||
fun requestFadeOut(length: Double) {
|
||||
if (!fadeoutFired) {
|
||||
fadeLength = length.coerceAtLeast(1.0/1024.0)
|
||||
fadeAkku = 0.0
|
||||
fadeoutFired = true
|
||||
}
|
||||
}
|
||||
|
||||
fun requestFadeIn(length: Double) {
|
||||
if (!fadeinFired) {
|
||||
fadeLength = length.coerceAtLeast(1.0/1024.0)
|
||||
fadeAkku = 0.0
|
||||
fadeinFired = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
12
src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt
Normal file
12
src/net/torvald/terrarum/audio/TerrarumAudioFilters.kt
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
55
src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt
Normal file
55
src/net/torvald/terrarum/audio/TerrarumAudioMixerTracks.kt
Normal file
@@ -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<TerrarumAudioFilters>()
|
||||
val sidechainInputs = arrayListOf<Pair<TerrarumAudioMixerTracks, TrackVolume>>()
|
||||
|
||||
/**
|
||||
* 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)
|
||||
Reference in New Issue
Block a user