sound on memory wip

This commit is contained in:
minjaesong
2024-04-02 00:29:59 +09:00
parent a1a70274dd
commit 53f54a450d
6 changed files with 100 additions and 29 deletions

View File

@@ -66,7 +66,7 @@ class AudioMixer : Disposable {
else if (it == 9) "\u00D9Open\u00D9" // convolution1
else if (it == 10) "\u00D9Cave\u00D9" // convolution2
else if (it == 11) "\u00F0 \u00DA \u00F0" // fade
else "Trk${it+1}", trackType = if (it >= 7 || it == 3) TrackType.BUS else TrackType.STATIC_SOURCE, maxVolumeFun = {
else "Trk${it+1}", trackType = if (it >= 6 || it == 3) TrackType.BUS else TrackType.STATIC_SOURCE, maxVolumeFun = {
when (it) {
0 -> { musicVolume }
4 -> { ambientVolume }
@@ -115,10 +115,29 @@ class AudioMixer : Disposable {
ambientTrack1, ambientTrack2, ambientTrack3, ambientTrack4
)
val guiTracks = Array(4) { TerrarumAudioMixerTrack("GUI${it+1}", TrackType.STATIC_SOURCE) }
var processing = false
var actorNowPlaying = Terrarum.ingame?.actorNowPlaying; private set
fun getFreeGuiTrackNoMatterWhat(): TerrarumAudioMixerTrack {
synchronized(this) {
val it = getFreeGuiTrack() ?: guiTracks.minBy { it.playStartedTime }.also { it.checkedOutTime = System.nanoTime() }
println("GuiTrack ${it.name}")
return it
}
}
fun getFreeGuiTrack(): TerrarumAudioMixerTrack? {
synchronized(this) {
return guiTracks.minByOrNull { maxOf(it.checkedOutTime, it.playStartedTime) }
.also {
it?.checkedOutTime = System.nanoTime()
}
}
}
/**
* Return oldest dynamic track, even if the track is currently playing
*/
@@ -169,6 +188,12 @@ class AudioMixer : Disposable {
catch (e: Throwable) { e.printStackTrace() }
}
}
guiTracks.forEach {
if (!it.processor.paused) {
try { it.processor.run() }
catch (e: Throwable) { e.printStackTrace() }
}
}
tracks.forEach {
if (!it.processor.paused) {
try { it.processor.run() }
@@ -230,7 +255,10 @@ class AudioMixer : Disposable {
it.filters[0] = Gain(1f)
}
guiTrack.filters[1] = BinoPan(0f)
guiTracks.forEach {
guiTrack.addSidechainInput(it, 1.0)
it.filters[0] = BinoPan(0f)
}
masterTrack.filters[0] = SoftClp
masterTrack.filters[1] = Buffer
@@ -285,6 +313,7 @@ class AudioMixer : Disposable {
/*parallelProcessingSchedule =
arrayOf(musicTrack, ambientTrack, guiTrack).sliceEvenly(THREAD_COUNT / 2).toTypedArray() +
dynamicTracks.sliceEvenly(THREAD_COUNT / 2).toTypedArray() +
guiTracks +
arrayOf(sfxSumBus, sumBus, convolveBusOpen, convolveBusCave).sliceEvenly(THREAD_COUNT / 2).toTypedArray() +
arrayOf(fadeBus) +
arrayOf(masterTrack)*/
@@ -552,6 +581,7 @@ class AudioMixer : Disposable {
fun reset() {
ambientStopped = true
dynamicTracks.forEach { it.stop() }
guiTracks.forEach { it.stop() }
tracks.filter { it.trackType == TrackType.STATIC_SOURCE }.forEach { it.stop() }
tracks.forEach {
it.processor.purgeBuffer()
@@ -574,6 +604,7 @@ class AudioMixer : Disposable {
// feedingThread.join()
tracks.forEach { it.tryDispose() }
dynamicTracks.forEach { it.tryDispose() }
guiTracks.forEach { it.tryDispose() }
masterTrack.tryDispose()
}
}

View File

@@ -1,6 +1,5 @@
package net.torvald.terrarum.audio
import com.badlogic.gdx.utils.Queue
import net.torvald.reflection.forceInvoke
import net.torvald.terrarum.*
import net.torvald.terrarum.audio.AudioMixer.Companion.DS_FLTIDX_LOW
@@ -102,7 +101,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
bytesRead += read0(buffer, bytesRead)
}
// if isLooping=true, do gapless sampleRead but reads from itself
else if (track.currentTrack?.gdxMusic?.isLooping == true && bytesRead < buffer.size) {
else if (track.currentTrack?.looping == true && bytesRead < buffer.size) {
track.currentTrack?.reset()
bytesRead += read0(buffer, bytesRead)

View File

@@ -12,28 +12,32 @@ 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 net.torvald.terrarum.tryDispose
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
import java.io.File
import java.io.FileInputStream
import javax.sound.sampled.AudioSystem
data class MusicContainer(
val toRAM: Boolean = false,
val name: String,
val file: File,
val loop: Boolean = false,
val looping: Boolean = false,
internal var songFinishedHook: (Music) -> Unit = {}
): Disposable {
val samplingRate: Int
val codec: String
var samplesRead = 0L; internal set
var samplesReadCount = 0L; internal set
val samplesTotal: Long
val gdxMusic = Gdx.audio.newMusic(FileHandle(file))
private val gdxMusic: Music = Gdx.audio.newMusic(FileHandle(file))
private var soundBuf: UnsafePtr? = null; private set
init {
gdxMusic.isLooping = loop
gdxMusic.isLooping = looping
gdxMusic.setOnCompletionListener(songFinishedHook)
@@ -82,6 +86,45 @@ data class MusicContainer(
else -> Long.MAX_VALUE
}
if (toRAM) {
if (samplesTotal == Long.MAX_VALUE) throw IllegalStateException("Could not read sample count")
val readSize = 8192
var readCount = 0L
val readBuf = ByteArray(readSize)
soundBuf = UnsafeHelper.allocate(4L * samplesTotal)
while (readCount < samplesTotal) {
val read = gdxMusic.forceInvoke<Int>("read", arrayOf(readBuf))!!.toLong()
UnsafeHelper.memcpyRaw(readBuf, UnsafeHelper.getArrayOffset(readBuf), null, soundBuf!!.ptr + readCount, read)
readCount += read
}
}
}
fun readBytes(buffer: ByteArray): Int {
if (soundBuf == null) {
val bytesRead = gdxMusic.forceInvoke<Int>("read", arrayOf(buffer)) ?: 0
samplesReadCount += bytesRead / 4
return bytesRead
}
else {
val bytesToRead = minOf(buffer.size.toLong(), 4 * (samplesTotal - samplesReadCount))
UnsafeHelper.memcpyRaw(null, soundBuf!!.ptr, buffer, UnsafeHelper.getArrayOffset(buffer), bytesToRead)
samplesReadCount += bytesToRead / 4
return bytesToRead.toInt()
}
}
fun reset() {
samplesReadCount = 0L
gdxMusic.forceInvoke<Int>("reset", arrayOf())
}
private fun getWavFileSampleCount(file: File): Long {
@@ -133,14 +176,10 @@ data class MusicContainer(
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
override fun dispose() {
gdxMusic.dispose()
soundBuf?.destroy()
}
}