mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
working gapless playback but musicplayer anim is not
This commit is contained in:
@@ -86,6 +86,18 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
|
||||
val shuffled = playlistFile.get("shuffled").asBoolean()
|
||||
val fileToName = playlistFile.get("titles")
|
||||
|
||||
|
||||
AudioMixer.musicTrack.let { track ->
|
||||
track.doGaplessPlayback = (diskJockeyingMode == "continuous")
|
||||
if (track.doGaplessPlayback) {
|
||||
track.pullNextTrack = {
|
||||
track.currentTrack = ingame.musicGovernor.pullNextMusicTrack()
|
||||
setMusicName(track.currentTrack?.name ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registerPlaylist(albumDir, fileToName, shuffled, diskJockeyingMode)
|
||||
}
|
||||
|
||||
@@ -109,6 +121,9 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
|
||||
setIntermission()
|
||||
transitionRequest = MODE_IDLE
|
||||
}
|
||||
else if (diskJockeyingMode == "continuous") {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,12 +45,27 @@ class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: Terra
|
||||
|
||||
private fun allocateStreamBuf(track: TerrarumAudioMixerTrack) {
|
||||
printdbg("Allocating a StreamBuf with rate ${track.currentTrack!!.samplingRate}")
|
||||
streamBuf = AudioProcessBuf(track.currentTrack!!.samplingRate, {
|
||||
val l = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(it))
|
||||
track.currentTrack?.let {
|
||||
it.samplesRead += l!! / 4
|
||||
streamBuf = AudioProcessBuf(track.currentTrack!!.samplingRate, { buffer ->
|
||||
var bytesRead = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(buffer)) ?: 0
|
||||
|
||||
// increment samplesRead of the current track
|
||||
track.currentTrack?.let { it.samplesRead += bytesRead / 4 }
|
||||
|
||||
// do gapless fetch if there is space in the buffer
|
||||
if (track.doGaplessPlayback && bytesRead < buffer.size) {
|
||||
track.currentTrack?.reset()
|
||||
track.pullNextTrack()
|
||||
|
||||
val tmpBuf = ByteArray(buffer.size - bytesRead)
|
||||
val newRead = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(tmpBuf)) ?: 0
|
||||
|
||||
track.currentTrack?.let { it.samplesRead += newRead / 4 }
|
||||
System.arraycopy(tmpBuf, 0, buffer, bytesRead, tmpBuf.size)
|
||||
|
||||
bytesRead += newRead
|
||||
}
|
||||
l
|
||||
|
||||
bytesRead
|
||||
}, {
|
||||
track.stop()
|
||||
this.streamBuf = null
|
||||
|
||||
@@ -22,7 +22,14 @@ enum class TrackType {
|
||||
STATIC_SOURCE, DYNAMIC_SOURCE, BUS, MASTER
|
||||
}
|
||||
|
||||
class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var maxVolumeFun: () -> Double = {1.0}): Disposable {
|
||||
class TerrarumAudioMixerTrack(
|
||||
val name: String,
|
||||
val trackType: TrackType,
|
||||
var doGaplessPlayback: Boolean = false, // if true, the audio will be pulled from the `nextTrack` to always fully fill the read-buffer
|
||||
var maxVolumeFun: () -> Double = {1.0}
|
||||
): Disposable {
|
||||
|
||||
var pullNextTrack = {}
|
||||
|
||||
companion object {
|
||||
const val SAMPLING_RATE = 48000
|
||||
@@ -138,8 +145,8 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var ma
|
||||
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
|
||||
|
||||
fun stop() {
|
||||
currentTrack?.samplesRead = 0L
|
||||
currentTrack?.gdxMusic?.forceInvoke<Int>("reset", arrayOf())
|
||||
currentTrack?.reset()
|
||||
|
||||
streamPlaying = false
|
||||
// playStartedTime = 0L
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.jcraft.jorbis.VorbisFile
|
||||
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
|
||||
@@ -129,6 +130,11 @@ data class MusicContainer(
|
||||
}
|
||||
|
||||
override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name
|
||||
|
||||
fun reset() {
|
||||
samplesRead = 0L
|
||||
gdxMusic.forceInvoke<Int>("reset", arrayOf())
|
||||
}
|
||||
}
|
||||
|
||||
class TerrarumMusicGovernor : MusicGovernor() {
|
||||
@@ -270,6 +276,23 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
||||
musicState = STATE_PLAYING
|
||||
}
|
||||
|
||||
// MixerTrackProcessor will call this function externally to make gapless playback work
|
||||
fun pullNextMusicTrack(): MusicContainer {
|
||||
// prevent same song to play twice in row (for the most time)
|
||||
if (musicBin.isEmpty()) {
|
||||
restockMUsicBin()
|
||||
}
|
||||
return songs[musicBin.removeAt(0)]
|
||||
}
|
||||
|
||||
// MixerTrackProcessor will call this function externally to make gapless playback work
|
||||
fun pullNextAmbientTrack(): MusicContainer {
|
||||
// prevent same song to play twice in row (for the most time)
|
||||
if (ambientsBin.isEmpty()) {
|
||||
ambientsBin = ArrayList(ambients.indices.toList().shuffled())
|
||||
}
|
||||
return ambients[ambientsBin.removeAt(0)]
|
||||
}
|
||||
|
||||
private fun stopAmbient() {
|
||||
ambState = STATE_INTERMISSION
|
||||
@@ -297,14 +320,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
||||
STATE_FIREPLAY -> {
|
||||
if (!musicFired) {
|
||||
musicFired = true
|
||||
|
||||
// prevent same song to play twice
|
||||
if (musicBin.isEmpty()) {
|
||||
restockMUsicBin()
|
||||
}
|
||||
val song = songs[musicBin.removeAt(0)]
|
||||
|
||||
startMusic(song)
|
||||
startMusic(pullNextMusicTrack())
|
||||
}
|
||||
}
|
||||
STATE_PLAYING -> {
|
||||
@@ -324,14 +340,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
||||
STATE_FIREPLAY -> {
|
||||
if (!ambFired) {
|
||||
ambFired = true
|
||||
|
||||
// prevent same song to play twice
|
||||
if (ambientsBin.isEmpty()) {
|
||||
ambientsBin = ArrayList(ambients.indices.toList().shuffled())
|
||||
}
|
||||
val song = ambients[ambientsBin.removeAt(0)]
|
||||
|
||||
startAmbient(song)
|
||||
startAmbient(pullNextAmbientTrack())
|
||||
}
|
||||
}
|
||||
STATE_PLAYING -> {
|
||||
|
||||
Reference in New Issue
Block a user