diff --git a/assets/graphics/fonts/7x13_Tamzen7x14b.tga b/assets/graphics/fonts/7x13_Tamzen7x14b.tga index f52a7d81e..62c6b7aba 100644 --- a/assets/graphics/fonts/7x13_Tamzen7x14b.tga +++ b/assets/graphics/fonts/7x13_Tamzen7x14b.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8fb01c2b2c2cf356e7aa1e21728cb270167d85f3f681129e51c0a272802e75f5 +oid sha256:1524f71e550bc4c51790d6dbedcf0c2875fb7831c7149793322acacf16e355d1 size 93202 diff --git a/assets/mods/basegame/audio/convolution/EchoThief - Cranbrook Art Museum.bin b/assets/mods/basegame/audio/convolution/EchoThief - Cranbrook Art Museum.bin new file mode 100644 index 000000000..4133b39e6 --- /dev/null +++ b/assets/mods/basegame/audio/convolution/EchoThief - Cranbrook Art Museum.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2008760876a186741e201c752beb957b9e1e91f219e455adf72557abe09c600a +size 578760 diff --git a/assets/mods/basegame/audio/convolution/EchoThief - DivorceBeach.bin b/assets/mods/basegame/audio/convolution/EchoThief - DivorceBeach.bin deleted file mode 100644 index 456842932..000000000 Binary files a/assets/mods/basegame/audio/convolution/EchoThief - DivorceBeach.bin and /dev/null differ diff --git a/assets/mods/basegame/audio/convolution/EchoThief - TransitCenter.bin b/assets/mods/basegame/audio/convolution/EchoThief - TransitCenter.bin deleted file mode 100644 index d8458d661..000000000 Binary files a/assets/mods/basegame/audio/convolution/EchoThief - TransitCenter.bin and /dev/null differ diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt index 273695f2b..c76a2eb17 100644 --- a/src/net/torvald/terrarum/audio/AudioMixer.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -44,13 +44,16 @@ object AudioMixer: Disposable { get() = App.getConfigDouble("guivolume") - val tracks = Array(5) { TerrarumAudioMixerTrack( - if (it == 0) "BGM" - else if (it == 1) "AMB" - else if (it == 2) "SFX" + val tracks = Array(8) { TerrarumAudioMixerTrack( + if (it == 0) "Music" + else if (it == 1) "Ambient" + else if (it == 2) "Player" else if (it == 3) "GUI" - else if (it == 4) "BUS1" - else "Trk${it+1}", isBus = (it == 4), maxVolumeFun = { + else if (it == 4) "\u00F0 \u00E4 \u00F0" // summation + else if (it == 5) "\u00D9Open\u00D9" // convolution1 + else if (it == 6) "\u00D9Cave\u00D9" // convolution2 + else if (it == 7) "\u00F0 \u00DA \u00F0" // fade + else "Trk${it+1}", isBus = (it >= 4), maxVolumeFun = { when (it) { 0 -> { musicVolume } 1 -> { ambientVolume } @@ -61,7 +64,7 @@ object AudioMixer: Disposable { } ) } - val masterTrack = TerrarumAudioMixerTrack("Master", true) { masterVolume } + val masterTrack = TerrarumAudioMixerTrack("\u00DBMASTER", true) { masterVolume } val musicTrack: TerrarumAudioMixerTrack get() = tracks[0] @@ -72,8 +75,14 @@ object AudioMixer: Disposable { val guiTrack: TerrarumAudioMixerTrack get() = tracks[3] - val fadeBus: TerrarumAudioMixerTrack + val sumBus: TerrarumAudioMixerTrack get() = tracks[4] + val convolveBusOpen: TerrarumAudioMixerTrack + get() = tracks[5] + val convolveBusCave: TerrarumAudioMixerTrack + get() = tracks[6] + val fadeBus: TerrarumAudioMixerTrack + get() = tracks[7] var processing = true @@ -102,19 +111,37 @@ object AudioMixer: Disposable { init { -// musicTrack.filters[0] = BinoPan((Math.random() * 2.0 - 1.0).toFloat()) -// musicTrack.filters[1] = Reverb(36f, 0.92f, 1200f) + // initialise audio paths // + +// musicTrack.filters[1] = BinoPan(0f) +// musicTrack.filters[2] = Reverb(36f, 0.92f, 1200f) + + listOf(musicTrack, ambientTrack, sfxMixTrack, guiTrack).forEach { + it.filters[0] = Gain(1f) + } masterTrack.filters[0] = SoftClp masterTrack.filters[1] = Buffer masterTrack.filters[2] = Scope() - fadeBus.addSidechainInput(musicTrack, 1.0) - fadeBus.addSidechainInput(ambientTrack, 1.0) - fadeBus.addSidechainInput(sfxMixTrack, 1.0) - fadeBus.filters[0] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - CedarCreekWinery.bin")) - fadeBus.filters[1] = Gain(10f) - fadeBus.filters[3] = Lowpass(SAMPLING_RATE / 2f) + listOf(sumBus, convolveBusOpen, convolveBusCave).forEach { + it.addSidechainInput(musicTrack, 1.0) + it.addSidechainInput(ambientTrack, 1.0) + it.addSidechainInput(sfxMixTrack, 1.0) + } + + convolveBusOpen.filters[0] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - Cranbrook Art Museum.bin")) + convolveBusOpen.filters[1] = Gain(decibelsToFullscale(21.0).toFloat()) + convolveBusOpen.volume = 0.5 + + convolveBusCave.filters[0] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - CedarCreekWinery.bin")) + convolveBusCave.filters[1] = Gain(decibelsToFullscale(18.0).toFloat()) + convolveBusCave.volume = 0.5 + + fadeBus.addSidechainInput(sumBus, 1.0 / 3.0) + fadeBus.addSidechainInput(convolveBusOpen, 2.0 / 3.0) + fadeBus.addSidechainInput(convolveBusCave, 2.0 / 3.0) + fadeBus.filters[0] = Lowpass(SAMPLING_RATE / 2f) masterTrack.addSidechainInput(fadeBus, 1.0) masterTrack.addSidechainInput(guiTrack, 1.0) @@ -152,7 +179,7 @@ object AudioMixer: Disposable { fun update(delta: Float) { // test the panning - /*(musicTrack.filters[0] as? BinoPan)?.let { + /*musicTrack.getFilter().let { if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { it.pan = (it.pan + 0.001f).coerceIn(-1f, 1f) } @@ -166,10 +193,10 @@ object AudioMixer: Disposable { // the real updates (Gdx.audio as? Lwjgl3Audio)?.update() masterTrack.volume = masterVolume - musicTrack.volume = musicVolume - ambientTrack.volume = ambientVolume - sfxMixTrack.volume = sfxVolume - guiTrack.volume = guiVolume + musicTrack.getFilter().gain = musicVolume.toFloat() + ambientTrack.getFilter().gain = ambientVolume.toFloat() + sfxMixTrack.getFilter().gain = sfxVolume.toFloat() + guiTrack.getFilter().gain = guiVolume.toFloat() // process fades diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 1084893cc..cd5af7638 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -81,54 +81,48 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru } } - var samplesL0: FloatArray? = null - var samplesR0: FloatArray? = null - var samplesL1: FloatArray? = null - var samplesR1: FloatArray? = null + var samplesL1: FloatArray + var samplesR1: FloatArray var bufEmpty = false // get samples and apply the fader if (track.isMaster || track.isBus) { // combine all the inputs - samplesL0 = FloatArray(bufferSize / 4) - samplesR0 = FloatArray(bufferSize / 4) samplesL1 = FloatArray(bufferSize / 4) samplesR1 = FloatArray(bufferSize / 4) val sidechains = track.sidechainInputs.filterNotNull() // add all up sidechains.forEach { (side, mix) -> - for (i in samplesL0!!.indices) { - samplesL1!![i] += side.processor.fout1[0][i] * (mix * track.volume).toFloat() - samplesR1!![i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat() + for (i in samplesL1.indices) { + samplesL1[i] += side.processor.fout1[0][i] * (mix * track.volume).toFloat() + samplesR1[i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat() } } } // source channel: skip processing if there's no active input // else if (track.getSidechains().any { it != null && !it.isBus && !it.isMaster && !it.streamPlaying } && !track.streamPlaying) { else if (!track.streamPlaying) { - samplesL0 = null - samplesR0 = null - samplesL1 = null - samplesR1 = null + samplesL1 = emptyBuf + samplesR1 = emptyBuf + + bufEmpty = true } else { - samplesL0 = streamBuf.getL0(track.volume) - samplesR0 = streamBuf.getR0(track.volume) samplesL1 = streamBuf.getL1(track.volume) samplesR1 = streamBuf.getR1(track.volume) } - if (samplesL0 != null /*&& samplesL1 != null && samplesR0 != null && samplesR1 != null*/) { + if (!bufEmpty) { // run the input through the stack of filters val filterStack = track.filters.filter { !it.bypass && it !is NullFilter } if (filterStack.isEmpty()) { - fout1 = listOf(samplesL1!!, samplesR1!!) + fout1 = listOf(samplesL1, samplesR1) } else { - var fin1 = listOf(samplesL1!!, samplesR1!!) + var fin1 = listOf(samplesL1, samplesR1) fout1 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) filterStack.forEachIndexed { index, it -> @@ -162,6 +156,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru } } else { + fout1 = listOf(samplesL1, samplesR1) // keep pass the so that long-delay filters can empty out its buffer maxSigLevel.fill(0.0) maxRMS.fill(0.0) hasClipping.fill(false) @@ -173,16 +168,14 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru this.pause() } else { - if (samplesL0 != null /*&& samplesL1 != null && samplesR0 != null && samplesR1 != null*/) { - // spin until queue is sufficiently empty - /*while (track.pcmQueue.size >= BACK_BUF_COUNT && running) { // uncomment to multithread - Thread.sleep(1) - }*/ + // spin until queue is sufficiently empty + /*while (track.pcmQueue.size >= BACK_BUF_COUNT && running) { // uncomment to multithread + Thread.sleep(1) + }*/ -// printdbg("PUSHE; Queue size: ${track.pcmQueue.size}") - track.pcmQueue.addLast(fout1) - } +// printdbg("PUSHE; Queue size: ${track.pcmQueue.size}") + track.pcmQueue.addLast(fout1) // spin // Thread.sleep(((1000*bufferSize) / 8L / rate).coerceAtLeast(1L)) // uncomment to multithread diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt index 81d600744..9b9861bab 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt @@ -4,7 +4,6 @@ import com.jme3.math.FastMath import com.jme3.math.FastMath.sin import net.torvald.terrarum.audio.AudioMixer.SPEED_OF_SOUND import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF import net.torvald.terrarum.roundToFloat import java.io.File @@ -58,8 +57,8 @@ object SoftClp : TerrarumAudioFilter() { } class Scope : TerrarumAudioFilter() { - val backbufL = Array((4096f / BUFFER_SIZE * 4).roundToInt()) { FloatArray(BUFFER_SIZE / 4) } - val backbufR = Array((4096f / BUFFER_SIZE * 4).roundToInt()) { FloatArray(BUFFER_SIZE / 4) } + val backbufL = Array((4096f / BUFFER_SIZE * 4).roundToInt().coerceAtLeast(1)) { FloatArray(BUFFER_SIZE / 4) } + val backbufR = Array((4096f / BUFFER_SIZE * 4).roundToInt().coerceAtLeast(1)) { FloatArray(BUFFER_SIZE / 4) } private val sqrt2p = 0.7071067811865475 @@ -445,11 +444,11 @@ object MStoXY: TerrarumAudioFilter() { } } -class Gain(val gain: Float): TerrarumAudioFilter() { +class Gain(var gain: Float): TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { for (i in 0 until BUFFER_SIZE / 4) { - outbuf[0][i] = inbuf[1][i] * gain - outbuf[1][i] = inbuf[0][i] * gain + outbuf[0][i] = inbuf[0][i] * gain + outbuf[1][i] = inbuf[1][i] * gain } } } diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index 4664aeb45..8774a49d3 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt @@ -20,7 +20,7 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v const val SAMPLING_RATE = 48000 const val SAMPLING_RATEF = 48000f const val SAMPLING_RATED = 48000.0 - const val BUFFER_SIZE = 8192 // n ms -> 384 * n + const val BUFFER_SIZE = 16384 // n ms -> 384 * n } val hash = getHashStr() diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 48b5ee452..6f37a017b 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -377,7 +377,7 @@ class BasicDebugInfoWindow : UICanvas() { private val meterTroughHeight = meterGradCountMinusOne * meterGradSize + 5 private val meterHeight = meterTroughHeight - 4 - private val stripW = 56 + private val stripW = 54 private val halfStripW = stripW / 2 private val stripGap = 1 private val stripFilterHeight = 16 @@ -454,7 +454,7 @@ class BasicDebugInfoWindow : UICanvas() { // name text batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, track.name, x + 3f, y + stripH - 13f) + App.fontSmallNumbers.draw(batch, track.name, x + 1f + (stripW - track.name.length * 7) / 2, y + stripH - 13f) // filterbank back @@ -484,6 +484,8 @@ class BasicDebugInfoWindow : UICanvas() { val mixDb = fullscaleToDecibels(mix) val perc = ((mixDb + 24.0).coerceAtLeast(0.0) / 24.0).toFloat() // gauge background + batch.color = COL_METER_TROUGH + Toolkit.fillArea(batch, x.toFloat(), faderY - (i+1)*16f, stripW.toFloat(), 14f) batch.color = COL_SENDS_GRAD2 Toolkit.fillArea(batch, x.toFloat(), faderY - (i+1)*16f, stripW * perc, 14f) batch.color = COL_SENDS_GRAD