mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
more audio pathing
This commit is contained in:
Binary file not shown.
BIN
assets/mods/basegame/audio/convolution/EchoThief - Cranbrook Art Museum.bin
LFS
Normal file
BIN
assets/mods/basegame/audio/convolution/EchoThief - Cranbrook Art Museum.bin
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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<BinoPan>().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>().gain = musicVolume.toFloat()
|
||||
ambientTrack.getFilter<Gain>().gain = ambientVolume.toFloat()
|
||||
sfxMixTrack.getFilter<Gain>().gain = sfxVolume.toFloat()
|
||||
guiTrack.getFilter<Gain>().gain = guiVolume.toFloat()
|
||||
|
||||
|
||||
// process fades
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<FloatArray>, outbuf: List<FloatArray>) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user