mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
fix: continuous album now plays again
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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() })
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user