mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 12:04:06 +09:00
music playlist is working again
This commit is contained in:
@@ -32,7 +32,7 @@ object AudioMixer: Disposable {
|
|||||||
|
|
||||||
private val masterTrack = TerrarumAudioMixerTrack("Master", true).also { master ->
|
private val masterTrack = TerrarumAudioMixerTrack("Master", true).also { master ->
|
||||||
tracks.forEach { master.addSidechainInput(it, 1.0) }
|
tracks.forEach { master.addSidechainInput(it, 1.0) }
|
||||||
// master.filters[0] = Lowpass(240, TerrarumAudioMixerTrack.SAMPLING_RATE)
|
master.filters[0] = Lowpass(48000, TerrarumAudioMixerTrack.SAMPLING_RATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val musicTrack: TerrarumAudioMixerTrack
|
private val musicTrack: TerrarumAudioMixerTrack
|
||||||
|
|||||||
@@ -34,6 +34,28 @@ class AudioProcessBuf(val size: Int) {
|
|||||||
updateFloats()
|
updateFloats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reusing a buffer causes tons of blips in the sound? how??
|
||||||
|
/*private val L0buf = FloatArray(size / 4)
|
||||||
|
private val R0buf = FloatArray(size / 4)
|
||||||
|
private val L1buf = FloatArray(size / 4)
|
||||||
|
private val R1buf = FloatArray(size / 4)
|
||||||
|
|
||||||
|
fun getL0(volume: Double): FloatArray {
|
||||||
|
for (i in L0buf.indices) { L0buf[i] = (volume * fbuf0[2*i]).toFloat() }
|
||||||
|
return L0buf
|
||||||
|
}
|
||||||
|
fun getR0(volume: Double): FloatArray {
|
||||||
|
for (i in R0buf.indices) { R0buf[i] = (volume * fbuf0[2*i+1]).toFloat() }
|
||||||
|
return R0buf
|
||||||
|
}
|
||||||
|
fun getL1(volume: Double): FloatArray {
|
||||||
|
for (i in L1buf.indices) { L1buf[i] = (volume * fbuf1[2*i]).toFloat() }
|
||||||
|
return L1buf
|
||||||
|
}
|
||||||
|
fun getR1(volume: Double): FloatArray {
|
||||||
|
for (i in R1buf.indices) { R1buf[i] = (volume * fbuf1[2*i+1]).toFloat() }
|
||||||
|
return R1buf
|
||||||
|
}*/
|
||||||
fun getL0(volume: Double) = FloatArray(size / 4) { (volume * fbuf0[2*it]).toFloat() }
|
fun getL0(volume: Double) = FloatArray(size / 4) { (volume * fbuf0[2*it]).toFloat() }
|
||||||
fun getR0(volume: Double) = FloatArray(size / 4) { (volume * fbuf0[2*it+1]).toFloat() }
|
fun getR0(volume: Double) = FloatArray(size / 4) { (volume * fbuf0[2*it+1]).toFloat() }
|
||||||
fun getL1(volume: Double) = FloatArray(size / 4) { (volume * fbuf1[2*it]).toFloat() }
|
fun getL1(volume: Double) = FloatArray(size / 4) { (volume * fbuf1[2*it]).toFloat() }
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.audio
|
|||||||
import com.badlogic.gdx.utils.Queue
|
import com.badlogic.gdx.utils.Queue
|
||||||
import net.torvald.reflection.forceInvoke
|
import net.torvald.reflection.forceInvoke
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-11-17.
|
* Created by minjaesong on 2023-11-17.
|
||||||
@@ -22,6 +23,8 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
private var fout0 = listOf(emptyBuf, emptyBuf)
|
private var fout0 = listOf(emptyBuf, emptyBuf)
|
||||||
private var fout1 = listOf(emptyBuf, emptyBuf)
|
private var fout1 = listOf(emptyBuf, emptyBuf)
|
||||||
|
|
||||||
|
var maxSigLevel = arrayOf(0.0, 0.0); private set
|
||||||
|
|
||||||
private var breakBomb = false
|
private var breakBomb = false
|
||||||
|
|
||||||
private fun printdbg(msg: Any) {
|
private fun printdbg(msg: Any) {
|
||||||
@@ -58,7 +61,13 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
// fetch deviceBufferSize amount of sample from the disk
|
// fetch deviceBufferSize amount of sample from the disk
|
||||||
if (!track.isMaster && track.streamPlaying) {
|
if (!track.isMaster && track.streamPlaying) {
|
||||||
streamBuf.fetchBytes {
|
streamBuf.fetchBytes {
|
||||||
track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(it))
|
val bytesRead = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(it))
|
||||||
|
if (bytesRead == null || bytesRead <= 0) { // some class (namely Mp3) may return 0 instead of negative value
|
||||||
|
// printdbg("Finished reading audio stream")
|
||||||
|
track.currentTrack?.gdxMusic?.forceInvoke<Int>("reset", arrayOf())
|
||||||
|
track.streamPlaying = false
|
||||||
|
track.fireSongFinishHook()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +155,8 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
|
|
||||||
// by this time, the output buffer is filled with processed results, pause the execution
|
// by this time, the output buffer is filled with processed results, pause the execution
|
||||||
if (!track.isMaster) {
|
if (!track.isMaster) {
|
||||||
|
fout1.map { it.maxBy { it.absoluteValue } }.forEachIndexed { index, fl -> maxSigLevel[index] = fl.toDouble() }
|
||||||
|
|
||||||
this.pause()
|
this.pause()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -156,7 +167,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
Thread.sleep(1)
|
Thread.sleep(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// printdbg("Pushing to queue (queue size: ${track.pcmQueue.size})")
|
// printdbg("PUSHE; Queue size: ${track.pcmQueue.size}")
|
||||||
track.pcmQueue.addLast(fout1)
|
track.pcmQueue.addLast(fout1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,20 +227,18 @@ class FeedSamplesToAdev(val bufferSize: Int, val rate: Int, val track: TerrarumA
|
|||||||
while (!exit) {
|
while (!exit) {
|
||||||
|
|
||||||
val writeQueue = track.pcmQueue
|
val writeQueue = track.pcmQueue
|
||||||
|
val queueSize = writeQueue.size
|
||||||
if (writeQueue.notEmpty()) {
|
if (queueSize > 0) {
|
||||||
// printdbg("Taking samples from queue (queue size: ${writeQueue.size})")
|
// printdbg("PULL; Queue size: $queueSize")
|
||||||
|
|
||||||
val samples = writeQueue.removeFirst()
|
val samples = writeQueue.removeFirst()
|
||||||
track.adev!!.writeSamples(samples)
|
track.adev!!.writeSamples(samples)
|
||||||
}
|
}
|
||||||
else if (writeQueue.isEmpty) {
|
// else {
|
||||||
// printdbg("!! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED ")
|
// printdbg("QUEUE EMPTY QUEUE EMPTY QUEUE EMPTY ")
|
||||||
}
|
// }
|
||||||
|
|
||||||
Thread.sleep((bufferSize / 8L / rate).coerceAtLeast(1L))
|
Thread.sleep((bufferSize / 8L / rate).coerceAtLeast(1L))
|
||||||
}
|
}
|
||||||
// printdbg("FeedSamplesToAdev EXIT")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
|
|||||||
@@ -46,4 +46,4 @@ class Lowpass(cutoff: Int, rate: Int): TerrarumAudioFilter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,10 +116,14 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false):
|
|||||||
|
|
||||||
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
|
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
|
||||||
|
|
||||||
|
fun fireSongFinishHook() {
|
||||||
|
currentTrack?.songFinishedHook?.invoke(currentTrack!!.gdxMusic)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 1st ring of the hell: the THREADING HELL //
|
// 1st ring of the hell: the THREADING HELL //
|
||||||
|
|
||||||
val BUFFER_SIZE = 8192
|
val BUFFER_SIZE = 16384
|
||||||
|
|
||||||
internal var processor = MixerTrackProcessor(BUFFER_SIZE, SAMPLING_RATE, this)
|
internal var processor = MixerTrackProcessor(BUFFER_SIZE, SAMPLING_RATE, this)
|
||||||
private val processorThread = Thread(processor).also {
|
private val processorThread = Thread(processor).also {
|
||||||
|
|||||||
@@ -12,8 +12,13 @@ import java.io.File
|
|||||||
data class MusicContainer(
|
data class MusicContainer(
|
||||||
val name: String,
|
val name: String,
|
||||||
val file: File,
|
val file: File,
|
||||||
val gdxMusic: Music
|
val gdxMusic: Music,
|
||||||
|
val songFinishedHook: (Music) -> Unit
|
||||||
) {
|
) {
|
||||||
|
init {
|
||||||
|
gdxMusic.setOnCompletionListener(songFinishedHook)
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name
|
override fun toString() = if (name.isEmpty()) file.nameWithoutExtension else name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,11 +31,8 @@ class TerrarumMusicGovernor : MusicGovernor() {
|
|||||||
MusicContainer(
|
MusicContainer(
|
||||||
it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "),
|
it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "),
|
||||||
it,
|
it,
|
||||||
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath)).also {
|
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath)),
|
||||||
it.setOnCompletionListener {
|
{ stopMusic() }
|
||||||
stopMusic()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
catch (e: GdxRuntimeException) {
|
catch (e: GdxRuntimeException) {
|
||||||
|
|||||||
Reference in New Issue
Block a user