updating Gdx.audio on separate thread

This commit is contained in:
minjaesong
2023-11-08 23:42:17 +09:00
parent beb7f1fb73
commit 2f11988353
8 changed files with 722 additions and 31 deletions

View File

@@ -74,6 +74,11 @@ public class App implements ApplicationListener {
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG) + (snap == null ? "" : (" (" + snap + ")"));
}
public static final String getVERSION_STRING_WITHOUT_SNAPSHOT() {
return String.format("%d.%d.%d", VERSION_RAW >>> 48, (VERSION_RAW & 0xffff000000L) >>> 24, VERSION_RAW & 0xffffffL) +
(VERSION_TAG.isBlank() ? "" : "-"+VERSION_TAG);
}
/**
* when FALSE, some assertion and print code will not execute
*/
@@ -1182,7 +1187,6 @@ public class App implements ApplicationListener {
AudioManager.INSTANCE.getMasterVolume();
audioManagerThread = new Thread(new AudioManagerRunnable(), "TerrarumAudioManager");
audioManagerThread.setPriority(2);
audioManagerThread.start();
Terrarum.initialise();

View File

@@ -1,12 +1,17 @@
package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl3.audio.Lwjgl3Audio
import net.torvald.terrarum.App.printdbg
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 AudioManager {
const val DEFAULT_FADEOUT_LEN = 2.4f
/** Returns a master volume */
val masterVolume: Float
@@ -27,25 +32,28 @@ object AudioManager {
private var nextMusic: MusicContainer? = null
private var fadeAkku = 0f
private var fadeLength = 1f
private var fadeLength = DEFAULT_FADEOUT_LEN
private var fadeoutFired = false
private var fadeinFired = false
fun update(delta: Float) {
(Gdx.audio as? Lwjgl3Audio)?.update()
if (fadeoutFired) {
fadeAkku += delta
currentMusic?.gdxMusic?.volume = musicVolume * (1f - (fadeAkku / fadeLength)).coerceIn(0f, 1f)
currentMusic?.gdxMusic?.volume = (musicVolume * (1f - (fadeAkku / fadeLength))).coerceIn(0f, 1f)
printdbg(this, "Fadeout fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
// printdbg(this, "Fadeout fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
if (fadeAkku >= fadeLength) {
fadeoutFired = false
currentMusic?.gdxMusic?.volume = 0f
currentMusic?.gdxMusic?.pause()
// currentMusic?.gdxMusic?.pause()
currentMusic = null
printdbg(this, "Fadeout end")
// printdbg(this, "Fadeout end")
}
}
// process fadein request
@@ -53,24 +61,24 @@ object AudioManager {
fadeAkku += delta
currentMusic?.gdxMusic?.volume = (musicVolume * (fadeAkku / fadeLength)).coerceIn(0f, 1f)
printdbg(this, "Fadein fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
// printdbg(this, "Fadein fired - akku: $fadeAkku; volume: ${currentMusic?.gdxMusic?.volume}")
if (currentMusic?.gdxMusic?.isPlaying == false) {
currentMusic?.gdxMusic?.play()
printdbg(this, "Fadein starting music ${currentMusic?.name}")
// printdbg(this, "Fadein starting music ${currentMusic?.name}")
}
if (fadeAkku >= fadeLength) {
currentMusic?.gdxMusic?.volume = musicVolume
fadeinFired = false
printdbg(this, "Fadein end")
// printdbg(this, "Fadein end")
}
}
if (currentMusic?.gdxMusic?.isPlaying != true && nextMusic != null) {
printdbg(this, "Playing next music: ${nextMusic!!.name}")
// printdbg(this, "Playing next music: ${nextMusic!!.name}")
currentMusic = nextMusic
nextMusic = null
currentMusic!!.gdxMusic.volume = musicVolume
@@ -80,13 +88,13 @@ object AudioManager {
fun startMusic(song: MusicContainer) {
if (currentMusic?.gdxMusic?.isPlaying == true) {
requestFadeOut(1f)
requestFadeOut(DEFAULT_FADEOUT_LEN)
}
nextMusic = song
}
fun stopMusic() {
requestFadeOut(1f)
requestFadeOut(DEFAULT_FADEOUT_LEN)
}
fun requestFadeOut(length: Float) {

View File

@@ -18,7 +18,8 @@ class AudioManagerRunnable : Runnable {
dT = (T - oldT) / 1000000000f
oldT = T;
AudioManager.update(dT)
Thread.sleep(20L)
// println("AudioManagerRunnable dT = ${dT * 1000f} ms")
Thread.sleep(30L)
}
catch (e: InterruptedException) {
break

View File

@@ -17,7 +17,7 @@ import java.net.http.HttpResponse
*/
object CheckUpdate {
private val versionNumFull = App.getVERSION_STRING()
private val versionNumFull = App.getVERSION_STRING_WITHOUT_SNAPSHOT()
private val versionNumOnly = String.format(
"%d.%d.%d",
App.VERSION_RAW ushr 48,

View File

@@ -40,7 +40,7 @@ class SavegameCollection(files0: List<DiskSkimmer>, prefiltered: Boolean) {
val manualSaves = files.filter { !it.diskFile.extension.matches(Regex("[a-z]")) }
init {
printdbg(this, "Rebuilding skimmers (${files.size})")
// printdbg(this, "Rebuilding skimmers (${files.size})")
// files.forEach { it.rebuild() }
}

View File

@@ -794,7 +794,7 @@ fun AppUpdateListOfSavegames() {
// create list of worlds
printdbg("ListSavegames", "Listing saved worlds...")
// printdbg("ListSavegames", "Listing saved worlds...")
val worldsDirLs = File(worldsDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
try {
DiskSkimmer(file, true)
@@ -820,16 +820,16 @@ fun AppUpdateListOfSavegames() {
}
filteringResults.forEachIndexed { index, list ->
val it = list.first()
printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
// printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
printdbg("ListSavegames", " collecting...")
// printdbg("ListSavegames", " collecting...")
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
printdbg("ListSavegames", " disk rebuilding...")
// printdbg("ListSavegames", " disk rebuilding...")
collection.rebuildLoadable()
printdbg("ListSavegames", " get UUID...")
// printdbg("ListSavegames", " get UUID...")
val worldUUID = collection.getUUID()
printdbg("ListSavegames", " registration...")
// printdbg("ListSavegames", " registration...")
// if multiple valid savegames with same UUID exist, only the most recent one is retained
if (!App.savegameWorlds.contains(worldUUID)) {
App.savegameWorlds[worldUUID] = collection
@@ -840,7 +840,7 @@ fun AppUpdateListOfSavegames() {
// create list of players
printdbg("ListSavegames", "Listing saved players...")
// printdbg("ListSavegames", "Listing saved players...")
val playersDirLs = File(playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.mapNotNull { file ->
try {
DiskSkimmer(file, true)
@@ -866,16 +866,16 @@ fun AppUpdateListOfSavegames() {
}
filteringResults2.forEachIndexed { index, list ->
val it = list.first()
printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
// printdbg("ListSavegames", " ${index+1}.\t${it.diskFile.absolutePath}")
printdbg("ListSavegames", " collecting...")
// printdbg("ListSavegames", " collecting...")
val collection = SavegameCollection.collectFromBaseFilename(list, it.diskFile.name)
printdbg("ListSavegames", " disk rebuilding...")
// printdbg("ListSavegames", " disk rebuilding...")
collection.rebuildLoadable()
printdbg("ListSavegames", " get UUID...")
// printdbg("ListSavegames", " get UUID...")
val playerUUID = collection.getUUID()
printdbg("ListSavegames", " registration...")
// printdbg("ListSavegames", " registration...")
// if multiple valid savegames with same UUID exist, only the most recent one is retained
if (!App.savegamePlayers.contains(playerUUID)) {
App.savegamePlayers[playerUUID] = collection

View File

@@ -25,7 +25,11 @@ class TerrarumMusicGovernor : MusicGovernor() {
MusicContainer(
it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "),
it,
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath))
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath)).also {
it.setOnCompletionListener {
stopMusic()
}
}
)
}
catch (e: GdxRuntimeException) {
@@ -98,9 +102,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
}
}
STATE_PLAYING -> {
if (AudioManager.currentMusic?.gdxMusic?.isPlaying == false) {
// stopMusic()
}
// stopMusic() will be called when the music finishes; it's on the setOnCompletionListener
}
STATE_INTERMISSION -> {
intermissionAkku += delta