fix: continuous album now plays again

This commit is contained in:
minjaesong
2024-07-07 02:53:57 +09:00
parent c211f67e38
commit 63070a19d5
10 changed files with 75 additions and 46 deletions

View File

@@ -709,6 +709,7 @@ class MusicPlayerControl(private val ingame: TerrarumIngame) : UICanvas() {
// debug codes
//// transaction state
if (MusicService.transactionLocked) {
batch.color = Color.RED
Toolkit.drawTextCentered(batch, App.fontSmallNumbers, "LOCKED", Toolkit.drawWidth, 0, _posY.toInt() + height + 5)
@@ -717,11 +718,24 @@ class MusicPlayerControl(private val ingame: TerrarumIngame) : UICanvas() {
batch.color = Color.WHITE
Toolkit.drawTextCentered(batch, App.fontSmallNumbers, "UNLOCKED", Toolkit.drawWidth, 0, _posY.toInt() + height + 5)
}
//// MusicService internal state
batch.color = Color.WHITE
val musicState = MusicService.currentPlaybackState.get()
val str = "State: $musicState Wait: ${MusicService.waitAkku.toIntAndFrac(2)}/${MusicService.waitTime}"
Toolkit.drawTextCentered(batch, App.fontSmallNumbers, str, Toolkit.drawWidth, 0, _posY.toInt() + height + 18)
//// playlist internal indices
MusicService.currentPlaylist?.let {
val indices = it.extortField<ArrayList<Int>>("internalIndices")!!
val currentIndex = it.extortField<Int>("currentIndexCursor")!!
for (k in 0 until indices.size) {
batch.color = if (k == currentIndex) Color.RED else Color.WHITE
App.fontSmallNumbers.draw(batch, "${indices[k]+1}", 28f + 18f * (k), App.scr.hf - 16f)
}
}
batch.color = Color.LIGHT_GRAY
App.fontSmallNumbers.draw(batch, "Playlist InternalIndices", 10f, App.scr.hf - 30f)
App.fontSmallNumbers.draw(batch, "..", 10f, App.scr.hf - 16f)
// end of debug codes
@@ -1347,16 +1361,6 @@ class MusicPlayerControl(private val ingame: TerrarumIngame) : UICanvas() {
private fun loadNewAlbum(albumDir: File): TerrarumMusicPlaylist {
val albumProp = albumPropCache[albumDir]
App.audioMixer.musicTrack.let { track ->
track.doGaplessPlayback = (albumProp.diskJockeyingMode == "continuous")
if (track.doGaplessPlayback) {
track.pullNextTrack = {
track.currentTrack = MusicService.currentPlaylist!!.queueNext()
setMusicName(track.currentTrack?.name ?: "")
}
}
}
currentlySelectedAlbum = albumProp
return registerPlaylist(albumDir.absolutePath, albumProp.fileToName, albumProp.shuffled, albumProp.diskJockeyingMode)

View File

@@ -166,6 +166,7 @@ object MusicService : TransactionListener() {
stopPlaylistPlayback {}
}
/**
* Puts the given playlist to this object if the transaction successes. If the given playlist is same as the
* current playlist, the transaction will successfully finish immediately; otherwise the given playlist will
@@ -213,11 +214,22 @@ object MusicService : TransactionListener() {
oldPlaylist?.dispose()
(state["currentPlaylist"] as TerrarumMusicPlaylist?)?.let {
// set songFinishedHook for every song
it.musicList.forEach {
it.songFinishedHook = {
onMusicFinishing(it)
}
}
// set gaplessness of the Music track
App.audioMixer.musicTrack.let { track ->
track.doGaplessPlayback = (it.diskJockeyingMode == "continuous")
if (track.doGaplessPlayback) {
track.pullNextTrack = {
track.currentTrack = MusicService.currentPlaylist!!.queueNext()
}
}
}
}
onSuccess()
@@ -313,7 +325,9 @@ object MusicService : TransactionListener() {
if (err != null) throw err!!
}
override fun onSuccess(state: TransactionState) { onSuccess() }
override fun onSuccess(state: TransactionState) {
onSuccess()
}
override fun onFailure(e: Throwable, state: TransactionState) {
e.printStackTrace()
}

View File

@@ -26,7 +26,7 @@ class TerrarumMusicPlaylist(
): Disposable {
private val internalIndices = ArrayList<Int>()
private var currentIndexCursor = musicList.size
private var currentIndexCursor = musicList.size - 1
init {
reset()
@@ -36,7 +36,7 @@ class TerrarumMusicPlaylist(
internalIndices.clear()
refillInternalIndices()
refillInternalIndices()
currentIndexCursor = musicList.size
currentIndexCursor = musicList.size - 1
}
private fun checkRefill() {
@@ -50,6 +50,11 @@ class TerrarumMusicPlaylist(
return musicList[internalIndices[currentIndexCursor]]
}
/**
* For Gapless playback, this function is called by track's pullNextTrack callback (defined in [MusicService.createTransactionPlaylistChange])
*
* For intermittent playback, this function is called by the transaction defined in [MusicService.update]
*/
fun queueNext(): MusicContainer {
checkRefill()
currentIndexCursor += 1
@@ -81,16 +86,12 @@ class TerrarumMusicPlaylist(
fun queueNthSong(n: Int): MusicContainer {
checkRefill()
internalIndices.add(currentIndexCursor, n)
currentIndexCursor -= 1
return musicList[internalIndices[currentIndexCursor]]
}
private fun refillInternalIndices() {
if (diskJockeyingMode == "continuous") {
internalIndices.add(0) // playlist is a one long track for the gapless playback
}
else {
internalIndices.addAll(musicList.indices.toMutableList().also { if (shuffled) it.shuffle() })
}
internalIndices.addAll(musicList.indices.toMutableList().also { if (shuffled) it.shuffle() })
}

View File

@@ -250,7 +250,7 @@ class AudioMixer : Disposable {
// initialise audio paths //
listOf(musicTrack, ambientTrack1, ambientTrack2, ambientTrack3, ambientTrack4, guiTrack).forEach {
it.filters[0] = Gain(1f)
it.filters[0] = PreGain(1f)
}
guiTracks.forEach {
@@ -285,11 +285,11 @@ class AudioMixer : Disposable {
}
convolveBusOpen.filters[1] = Convolv("basegame", "audio/convolution/EchoThief - PurgatoryChasm.bin", decibelsToFullscale(-6.0).toFloat())
convolveBusOpen.filters[2] = Gain(decibelsToFullscale(17.0).toFloat()) // don't make it too loud; it'll sound like a shit
convolveBusOpen.filters[2] = PreGain(decibelsToFullscale(17.0).toFloat()) // don't make it too loud; it'll sound like a shit
convolveBusOpen.volume = 0.5 // will be controlled by the other updater which surveys the world
convolveBusCave.filters[1] = Convolv("basegame", "audio/convolution/EchoThief - WaterplacePark-trimmed.bin", decibelsToFullscale(-3.0).toFloat())
convolveBusCave.filters[2] = Gain(decibelsToFullscale(16.0).toFloat())
convolveBusCave.filters[2] = PreGain(decibelsToFullscale(16.0).toFloat())
convolveBusCave.volume = 0.5 // will be controlled by the other updater which surveys the world
fadeBus.addSidechainInput(sumBus, 1.0 / 3.0)
@@ -392,12 +392,12 @@ class AudioMixer : Disposable {
// the real updates
(Gdx.audio as? Lwjgl3Audio)?.update()
masterTrack.volume = masterVolume
musicTrack.getFilter<Gain>().gain = musicVolume.toFloat() * 0.5f
musicTrack.getFilter<PreGain>().gain = musicVolume.toFloat() * 0.5f
ambientTracks.forEach {
it.getFilter<Gain>().gain = ambientVolume.toFloat()
it.getFilter<PreGain>().gain = ambientVolume.toFloat()
}
sfxSumBus.volume = sfxVolume
guiTrack.getFilter<Gain>().gain = guiVolume.toFloat()
guiTrack.getFilter<PreGain>().gain = guiVolume.toFloat()
// process fades

View File

@@ -9,7 +9,7 @@ import kotlin.math.roundToInt
/**
* Created by minjaesong on 2023-11-25.
*/
class Gain(var gain: Float): TerrarumAudioFilter() {
class PreGain(var gain: Float): TerrarumAudioFilter() {
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
for (i in 0 until App.audioBufferSize) {
outbuf[0][i] = inbuf[0][i] * gain
@@ -25,7 +25,7 @@ class Gain(var gain: Float): TerrarumAudioFilter() {
override val debugViewHeight = 16
override fun copyParamsFrom(other: TerrarumAudioFilter) {
if (other is Gain) {
if (other is PreGain) {
this.gain = other.gain
}
}

View File

@@ -9,7 +9,7 @@ import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.audio.audiobank.MusicContainer
import net.torvald.terrarum.audio.dsp.Gain
import net.torvald.terrarum.audio.dsp.PreGain
import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.AVKey
@@ -361,7 +361,7 @@ class FixtureAlloyingFurnace : FixtureBase {
getTrackByAudio(static).let {
if (it == null || (temperature > 0f && !it.isPlaying && !it.playRequested.get())) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
it.filters[filterIndex] = PreGain(0f)
}
}
else if (it != null && it.isPlaying && temperature <= 0f) {
@@ -371,10 +371,10 @@ class FixtureAlloyingFurnace : FixtureBase {
}
if (it != null) {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
if (it.filters[filterIndex] !is PreGain) // just in case...
it.filters[filterIndex] = PreGain(0f)
(it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature * volRand.get()).toFloat()
(it.filters[filterIndex] as PreGain).gain = (it.maxVolume * temperature * volRand.get()).toFloat()
}
}

View File

@@ -4,7 +4,7 @@ import net.torvald.gdx.graphics.Cvec
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.audio.audiobank.MusicContainer
import net.torvald.terrarum.audio.dsp.Gain
import net.torvald.terrarum.audio.dsp.PreGain
import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.AVKey
@@ -112,7 +112,7 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
if (audioStatus == 0) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
it.filters[filterIndex] = PreGain(0f)
audioStatus = 1
}
}
@@ -124,10 +124,10 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
if (it != null) {
if (it.processor.streamBuf != null || it.playRequested.get()) {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
if (it.filters[filterIndex] !is PreGain) // just in case...
it.filters[filterIndex] = PreGain(0f)
(it.filters[filterIndex] as Gain).gain = 0.4f * volRand.get()
(it.filters[filterIndex] as PreGain).gain = 0.4f * volRand.get()
}
else {
audioStatus = 0

View File

@@ -9,7 +9,7 @@ import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.audio.audiobank.MusicContainer
import net.torvald.terrarum.audio.dsp.Gain
import net.torvald.terrarum.audio.dsp.PreGain
import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.AVKey
@@ -348,7 +348,7 @@ class FixtureSmelterBasic : FixtureBase {
getTrackByAudio(static).let {
if (it == null || (temperature > 0f && !it.isPlaying && !it.playRequested.get())) {
startAudio(static) {
it.filters[filterIndex] = Gain(0f)
it.filters[filterIndex] = PreGain(0f)
}
}
else if (it != null && it.isPlaying && temperature <= 0f) {
@@ -358,10 +358,10 @@ class FixtureSmelterBasic : FixtureBase {
}
if (it != null) {
if (it.filters[filterIndex] !is Gain) // just in case...
it.filters[filterIndex] = Gain(0f)
if (it.filters[filterIndex] !is PreGain) // just in case...
it.filters[filterIndex] = PreGain(0f)
(it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature * volRand.get()).toFloat()
(it.filters[filterIndex] as PreGain).gain = (it.maxVolume * temperature * volRand.get()).toFloat()
}
}

View File

@@ -58,6 +58,7 @@ abstract class TransactionListener {
catch (e: Throwable) {
// if failed, notify the failure
System.err.println("Transaction failure: generic")
e.printStackTrace()
transaction.onFailure(e, state)
}
finally {
@@ -67,7 +68,7 @@ abstract class TransactionListener {
}
else {
System.err.println("Transaction failure: locked")
transaction.onFailure(LockedException(this, currentLock), state)
transaction.onFailure(LockedException(transaction, this, currentLock), state)
}
}.start()
}
@@ -76,8 +77,8 @@ abstract class TransactionListener {
protected abstract fun commitTransaction(state: TransactionState)
}
class LockedException(listener: TransactionListener, lockedBy: Transaction) :
Exception("Transaction is rejected because the class '${listener.javaClass.canonicalName}' is locked by '${lockedBy.javaClass.canonicalName}'")
class LockedException(offendingTransaction: Transaction, listener: TransactionListener, lockedBy: Transaction) :
Exception("Transaction '$offendingTransaction' is rejected because the class '$listener' is locked by '$lockedBy'")
@JvmInline value class TransactionState(val valueTable: HashMap<String, Any?>) {
operator fun get(key: String) = valueTable[key]

View File

@@ -665,6 +665,7 @@ class BasicDebugInfoWindow : UICanvas() {
else it
},
//"C:${track.currentTrack?.codec ?: ""}",
"GL:${if (track.doGaplessPlayback) "Y" else "N"}",
"R:${track.currentTrack?.samplingRate ?: ""}",
).forEachIndexed { i, s ->
// gauge background
@@ -680,6 +681,14 @@ class BasicDebugInfoWindow : UICanvas() {
Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, STRIP_W * perc, 2f)
}
// fill the back if the track is in gapless mode
if (i == 1 && track.doGaplessPlayback) {
batch.color = COL_PROGRESS_GRAD2
Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W.toFloat(), 14f)
batch.color = COL_PROGRESS_GRAD
Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, STRIP_W.toFloat(), 2f)
}
batch.color = FILTER_NAME_ACTIVE
App.fontSmallNumbers.draw(batch, s, x + 3f, faderY - (i + 1) * 16f + 1f)
}