From b93e987011b070972d18877d0d249efc259309d8 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 10 Feb 2024 16:09:00 +0900 Subject: [PATCH] MusicContainer extracted out of the modulebasegame --- .../terrarum/musicplayer/gui/MusicPlayer.kt | 2 - assets/mods/musicplayer/metadata.properties | 2 +- src/net/torvald/terrarum/App.java | 4 +- src/net/torvald/terrarum/audio/AudioCodex.kt | 1 - src/net/torvald/terrarum/audio/AudioMixer.kt | 3 +- .../torvald/terrarum/audio/MusicContainer.kt | 135 ++++++++++++++++++ .../terrarum/audio/TerrarumAudioMixerTrack.kt | 1 - src/net/torvald/terrarum/gameactors/Actor.kt | 2 +- .../modulebasegame/TerrarumMusicGovernor.kt | 133 +---------------- .../gameactors/FixtureJukebox.kt | 2 +- .../gameactors/FixtureMusicalTurntable.kt | 2 +- 11 files changed, 143 insertions(+), 144 deletions(-) create mode 100644 src/net/torvald/terrarum/audio/MusicContainer.kt diff --git a/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt index e09f7186e..39323efa9 100644 --- a/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt +++ b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt @@ -10,10 +10,8 @@ import com.badlogic.gdx.utils.JsonValue import com.jme3.math.FastMath import net.torvald.reflection.extortField import net.torvald.terrarum.* -import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.audio.* import net.torvald.terrarum.gameworld.fmod -import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.gameactors.PlaysMusic import net.torvald.terrarum.ui.BasicDebugInfoWindow diff --git a/assets/mods/musicplayer/metadata.properties b/assets/mods/musicplayer/metadata.properties index 71f947452..def20f866 100644 --- a/assets/mods/musicplayer/metadata.properties +++ b/assets/mods/musicplayer/metadata.properties @@ -6,5 +6,5 @@ entrypoint=net.torvald.terrarum.musicplayer.EntryPoint releasedate=2024-02-10 version=1.0.0 jar=MusicPlayer.jar -jarhash=7cadf1c1ffb8c87563413cabd3bab08c5111b045a7f02e770888188bca576445 +jarhash=3b8db936a76ffbd3fb4909de9582254e2ffc6eab7c4587ced0a738b21d05202a dependency=basegame 0.4.0 diff --git a/src/net/torvald/terrarum/App.java b/src/net/torvald/terrarum/App.java index ad0426b5d..065c3a74b 100644 --- a/src/net/torvald/terrarum/App.java +++ b/src/net/torvald/terrarum/App.java @@ -1221,7 +1221,7 @@ public class App implements ApplicationListener { audioBufferSize = getConfigInt("audio_buffer_size"); - audioMixer = new AudioMixer(audioBufferSize); + audioMixer = new AudioMixer(); audioMixerInitialised = true; audioManagerThread = new Thread(new AudioManagerRunnable(audioMixer), "TerrarumAudioManager"); audioManagerThread.setPriority(MAX_PRIORITY); // higher = more predictable; audio delay is very noticeable so it gets high priority @@ -1257,7 +1257,7 @@ public class App implements ApplicationListener { audioMixer.dispose(); audioBufferSize = bufferSize; - audioMixer = new AudioMixer(audioBufferSize); + audioMixer = new AudioMixer(); // paste music tracks for (int i = 0; i < audioMixer.getDynamicTracks().length; i++) { diff --git a/src/net/torvald/terrarum/audio/AudioCodex.kt b/src/net/torvald/terrarum/audio/AudioCodex.kt index 369b07b2e..36e7dccbf 100644 --- a/src/net/torvald/terrarum/audio/AudioCodex.kt +++ b/src/net/torvald/terrarum/audio/AudioCodex.kt @@ -2,7 +2,6 @@ package net.torvald.terrarum.audio import com.badlogic.gdx.Gdx import com.badlogic.gdx.files.FileHandle -import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.tryDispose /** diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt index 46f23a440..8e75b09bf 100644 --- a/src/net/torvald/terrarum/audio/AudioMixer.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -13,7 +13,6 @@ import net.torvald.terrarum.audio.dsp.* import net.torvald.terrarum.concurrent.ThreadExecutor import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.modulebasegame.BuildingMaker -import net.torvald.terrarum.modulebasegame.MusicContainer import java.lang.Thread.MAX_PRIORITY import java.util.* import kotlin.math.* @@ -23,7 +22,7 @@ import kotlin.math.* * * Created by minjaesong on 2023-11-07. */ -class AudioMixer(val bufferSize: Int): Disposable { +class AudioMixer : Disposable { companion object { const val SPEED_OF_SOUND_AIR = 340f diff --git a/src/net/torvald/terrarum/audio/MusicContainer.kt b/src/net/torvald/terrarum/audio/MusicContainer.kt new file mode 100644 index 000000000..0313283f6 --- /dev/null +++ b/src/net/torvald/terrarum/audio/MusicContainer.kt @@ -0,0 +1,135 @@ +package net.torvald.terrarum.audio + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.audio.Music +import com.badlogic.gdx.backends.lwjgl3.audio.Mp3 +import com.badlogic.gdx.backends.lwjgl3.audio.Ogg +import com.badlogic.gdx.backends.lwjgl3.audio.OggInputStream +import com.badlogic.gdx.backends.lwjgl3.audio.Wav +import com.jcraft.jorbis.VorbisFile +import javazoom.jl.decoder.Bitstream +import net.torvald.reflection.extortField +import net.torvald.reflection.forceInvoke +import net.torvald.terrarum.App +import java.io.File +import java.io.FileInputStream +import javax.sound.sampled.AudioSystem + +data class MusicContainer( + val name: String, + val file: File, + val gdxMusic: Music, + internal var songFinishedHook: (Music) -> Unit = {} +) { + val samplingRate: Int + val codec: String + + var samplesRead = 0L; internal set + val samplesTotal: Long + + init { + gdxMusic.setOnCompletionListener(songFinishedHook) + + samplingRate = when (gdxMusic) { + is Wav.Music -> { + val rate = gdxMusic.extortField("input")!!.sampleRate + + App.printdbg(this, "music $name is WAV; rate = $rate") + rate + } + is Ogg.Music -> { + val rate = gdxMusic.extortField("input")!!.sampleRate + + App.printdbg(this, "music $name is OGG; rate = $rate") + rate + } + is Mp3.Music -> { + val tempMusic = Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath)) + val bitstream = tempMusic.extortField("bitstream")!! + val header = bitstream.readFrame() + val rate = header.sampleRate + tempMusic.dispose() + +// val bitstream = gdxMusic.extortField("bitstream")!! +// val header = bitstream.readFrame() +// val rate = header.sampleRate +// gdxMusic.reset() + + App.printdbg(this, "music $name is MP3; rate = $rate") + rate + } + else -> { + App.printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default") + TerrarumAudioMixerTrack.SAMPLING_RATE + } + } + + codec = gdxMusic::class.qualifiedName!!.split('.').let { + if (it.last() == "Music") it.dropLast(1).last() else it.last() + } + + samplesTotal = when (gdxMusic) { + is Wav.Music -> getWavFileSampleCount(file) + is Ogg.Music -> getOggFileSampleCount(file) + is Mp3.Music -> getMp3FileSampleCount(file) + else -> Long.MAX_VALUE + } + + } + + private fun getWavFileSampleCount(file: File): Long { + return try { + val ais = AudioSystem.getAudioInputStream(file) + val r = ais.frameLength + ais.close() + r + } + catch (e: Throwable) { + Long.MAX_VALUE + } + } + + private fun getOggFileSampleCount(file: File): Long { + return try { + val vorbisFile = VorbisFile(file.absolutePath) + vorbisFile.pcm_total(0) + } + catch (e: Throwable) { + Long.MAX_VALUE + } + } + + private fun getMp3FileSampleCount(file: File): Long { + return try { + val fis = FileInputStream(file) + val bs = Bitstream(fis) + + var header = bs.readFrame() + val rate = header.frequency() + var totalSamples = 0L + + while (header != null) { + totalSamples += (header.ms_per_frame() * rate / 1000).toLong() + bs.closeFrame() + header = bs.readFrame() + } + + bs.close() + fis.close() + + totalSamples + } + catch (_: Throwable) { + Long.MAX_VALUE + } + } + + override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name + + fun reset() { + samplesRead = 0L + gdxMusic.forceInvoke("reset", arrayOf()) + } + + override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index 6f8c0c25d..0c3e09993 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt @@ -10,7 +10,6 @@ import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.getHashStr import net.torvald.terrarum.hashStrMap -import net.torvald.terrarum.modulebasegame.MusicContainer import kotlin.math.log10 import kotlin.math.pow diff --git a/src/net/torvald/terrarum/gameactors/Actor.kt b/src/net/torvald/terrarum/gameactors/Actor.kt index a807dfc47..9157df242 100644 --- a/src/net/torvald/terrarum/gameactors/Actor.kt +++ b/src/net/torvald/terrarum/gameactors/Actor.kt @@ -4,9 +4,9 @@ import net.torvald.random.HQRNG import net.torvald.terrarum.App import net.torvald.terrarum.INGAME import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.audio.TrackVolume -import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.Pocketed import net.torvald.terrarum.savegame.toBigEndian diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt index e8eaf639b..670df3ac2 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt @@ -1,145 +1,14 @@ package net.torvald.terrarum.modulebasegame import com.badlogic.gdx.Gdx -import com.badlogic.gdx.audio.Music -import com.badlogic.gdx.backends.lwjgl3.audio.Mp3 -import com.badlogic.gdx.backends.lwjgl3.audio.Ogg -import com.badlogic.gdx.backends.lwjgl3.audio.OggInputStream -import com.badlogic.gdx.backends.lwjgl3.audio.Wav -import com.badlogic.gdx.backends.lwjgl3.audio.Wav.WavInputStream import com.badlogic.gdx.utils.GdxRuntimeException -import com.jcraft.jorbis.VorbisFile import com.jme3.math.FastMath -import javazoom.jl.decoder.Bitstream -import net.torvald.reflection.extortField -import net.torvald.reflection.forceInvoke import net.torvald.terrarum.* import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.audio.AudioMixer -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE +import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.gameworld.WorldTime.Companion.DAY_LENGTH import java.io.File -import java.io.FileInputStream -import javax.sound.sampled.AudioSystem - -data class MusicContainer( - val name: String, - val file: File, - val gdxMusic: Music, - internal var songFinishedHook: (Music) -> Unit = {} -) { - val samplingRate: Int - val codec: String - - var samplesRead = 0L; internal set - val samplesTotal: Long - - init { - gdxMusic.setOnCompletionListener(songFinishedHook) - - samplingRate = when (gdxMusic) { - is Wav.Music -> { - val rate = gdxMusic.extortField("input")!!.sampleRate - - printdbg(this, "music $name is WAV; rate = $rate") - rate - } - is Ogg.Music -> { - val rate = gdxMusic.extortField("input")!!.sampleRate - - printdbg(this, "music $name is OGG; rate = $rate") - rate - } - is Mp3.Music -> { - val tempMusic = Gdx.audio.newMusic(Gdx.files.absolute(file.absolutePath)) - val bitstream = tempMusic.extortField("bitstream")!! - val header = bitstream.readFrame() - val rate = header.sampleRate - tempMusic.dispose() - -// val bitstream = gdxMusic.extortField("bitstream")!! -// val header = bitstream.readFrame() -// val rate = header.sampleRate -// gdxMusic.reset() - - printdbg(this, "music $name is MP3; rate = $rate") - rate - } - else -> { - printdbg(this, "music $name is ${gdxMusic::class.qualifiedName}; rate = default") - SAMPLING_RATE - } - } - - codec = gdxMusic::class.qualifiedName!!.split('.').let { - if (it.last() == "Music") it.dropLast(1).last() else it.last() - } - - samplesTotal = when (gdxMusic) { - is Wav.Music -> getWavFileSampleCount(file) - is Ogg.Music -> getOggFileSampleCount(file) - is Mp3.Music -> getMp3FileSampleCount(file) - else -> Long.MAX_VALUE - } - - } - - private fun getWavFileSampleCount(file: File): Long { - return try { - val ais = AudioSystem.getAudioInputStream(file) - val r = ais.frameLength - ais.close() - r - } - catch (e: Throwable) { - Long.MAX_VALUE - } - } - - private fun getOggFileSampleCount(file: File): Long { - return try { - val vorbisFile = VorbisFile(file.absolutePath) - vorbisFile.pcm_total(0) - } - catch (e: Throwable) { - Long.MAX_VALUE - } - } - - private fun getMp3FileSampleCount(file: File): Long { - return try { - val fis = FileInputStream(file) - val bs = Bitstream(fis) - - var header = bs.readFrame() - val rate = header.frequency() - var totalSamples = 0L - - while (header != null) { - totalSamples += (header.ms_per_frame() * rate / 1000).toLong() - bs.closeFrame() - header = bs.readFrame() - } - - bs.close() - fis.close() - - totalSamples - } - catch (_: Throwable) { - Long.MAX_VALUE - } - } - - override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name - - fun reset() { - samplesRead = 0L - gdxMusic.forceInvoke("reset", arrayOf()) - } - - override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path -} class TerrarumMusicGovernor : MusicGovernor() { private val STATE_INIT = 0 diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt index fabd18a90..718fed80c 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt @@ -11,6 +11,7 @@ import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN +import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.Phono @@ -20,7 +21,6 @@ import net.torvald.terrarum.gameactors.Hitbox import net.torvald.terrarum.gameactors.Lightbox import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.langpack.Lang -import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.TerrarumMusicGovernor import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt index 111e4231b..b520aea25 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt @@ -5,12 +5,12 @@ import net.torvald.spriteanimation.SheetSpriteAnimation import net.torvald.terrarum.* import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.audio.AudioMixer +import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.ItemID import net.torvald.terrarum.langpack.Lang -import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.TerrarumMusicGovernor import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef