MusicContainer extracted out of the modulebasegame

This commit is contained in:
minjaesong
2024-02-10 16:09:00 +09:00
parent ea940e93ba
commit b93e987011
11 changed files with 143 additions and 144 deletions

View File

@@ -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
/**

View File

@@ -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

View File

@@ -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<Wav.WavInputStream>("input")!!.sampleRate
App.printdbg(this, "music $name is WAV; rate = $rate")
rate
}
is Ogg.Music -> {
val rate = gdxMusic.extortField<OggInputStream>("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>("bitstream")!!
val header = bitstream.readFrame()
val rate = header.sampleRate
tempMusic.dispose()
// val bitstream = gdxMusic.extortField<Bitstream>("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<Int>("reset", arrayOf())
}
override fun equals(other: Any?) = this.file.path == (other as MusicContainer).file.path
}

View File

@@ -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