diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt index b1b0837ad..34eec6d10 100644 --- a/src/net/torvald/terrarum/audio/AudioMixer.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -184,11 +184,11 @@ object AudioMixer: Disposable { it.addSidechainInput(sfxSumBus, 1.0) } - convolveBusOpen.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - PurgatoryChasm.bin")) + convolveBusOpen.filters[1] = Convolv(ModMgr.getFile("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.volume = 0.5 // will be controlled by the other updater which surveys the world - convolveBusCave.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - WaterplacePark-trimmed.bin")) + convolveBusCave.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - WaterplacePark-trimmed.bin"), decibelsToFullscale(-3.0).toFloat()) convolveBusCave.filters[2] = Gain(decibelsToFullscale(16.0).toFloat()) convolveBusCave.volume = 0.5 // will be controlled by the other updater which surveys the world diff --git a/src/net/torvald/terrarum/audio/dsp/BinoPan.kt b/src/net/torvald/terrarum/audio/dsp/BinoPan.kt index 467749cd6..beb4d1788 100644 --- a/src/net/torvald/terrarum/audio/dsp/BinoPan.kt +++ b/src/net/torvald/terrarum/audio/dsp/BinoPan.kt @@ -1,10 +1,20 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath +import net.torvald.terrarum.App import net.torvald.terrarum.audio.AudioMixer import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.audio.decibelsToFullscale +import net.torvald.terrarum.ui.BasicDebugInfoWindow +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2 +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.toIntAndFrac +import net.torvald.terrarum.ui.Toolkit import kotlin.math.absoluteValue +import kotlin.math.roundToInt /** * The input audio must be monaural @@ -62,4 +72,22 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() push(inbuf[0], delayLine) } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + val w = pan * 0.5f * STRIP_W + batch.color = COL_METER_GRAD2 + Toolkit.fillArea(batch, x + STRIP_W / 2f, y.toFloat(), w, 14f) + batch.color = COL_METER_GRAD + Toolkit.fillArea(batch, x + STRIP_W / 2f, y+14f, w, 2f) + + batch.color = FILTER_NAME_ACTIVE + val panLabel = if (pan == 0f) "" + else if (pan < 0) "L${pan.absoluteValue.times(100).toIntAndFrac(3,1)}" + else "R${pan.absoluteValue.times(100).toIntAndFrac(3,1)}" + App.fontSmallNumbers.draw(batch, panLabel, x+3f, y+1f) + + App.fontSmallNumbers.draw(batch, "AS:${AudioMixer.SPEED_OF_SOUND.roundToInt()}", x+3f, y+17f) + } + + override val debugViewHeight = 32 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt b/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt index 5ca01d6c7..8b7a669da 100644 --- a/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt +++ b/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt @@ -1,7 +1,14 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.jme3.math.FastMath +import net.torvald.terrarum.App import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.audio.linToLogPerc import net.torvald.terrarum.roundToFloat +import net.torvald.terrarum.ui.BasicDebugInfoWindow +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.toIntAndFrac +import net.torvald.terrarum.ui.Toolkit class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { @@ -14,4 +21,19 @@ class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() } } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + val perc = linToLogPerc(steps.toDouble(), 2.0, 65536.0).toFloat() + batch.color = BasicDebugInfoWindow.COL_METER_GRAD2 + Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), BasicDebugInfoWindow.STRIP_W * perc, 14f) + batch.color = BasicDebugInfoWindow.COL_METER_GRAD + Toolkit.fillArea(batch, x.toFloat(), y+14f, BasicDebugInfoWindow.STRIP_W * perc, 2f) + + val bits = FastMath.log(steps.toFloat(), 2f).toIntAndFrac(1,2) + + batch.color = BasicDebugInfoWindow.FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "B:$bits", x+3f, y+1f) + } + + override val debugViewHeight = 16 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Buffer.kt b/src/net/torvald/terrarum/audio/dsp/Buffer.kt index bb3bdec48..2a65f4a08 100644 --- a/src/net/torvald/terrarum/audio/dsp/Buffer.kt +++ b/src/net/torvald/terrarum/audio/dsp/Buffer.kt @@ -1,5 +1,10 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.terrarum.App +import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE + object Buffer : TerrarumAudioFilter() { init { bypass = true @@ -8,4 +13,11 @@ object Buffer : TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { bypass = true } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "Bs:${AUDIO_BUFFER_SIZE}", x+3f, y+1f) + } + + override val debugViewHeight = 16 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Convolv.kt b/src/net/torvald/terrarum/audio/dsp/Convolv.kt index 95bec94a3..fe249c7d0 100644 --- a/src/net/torvald/terrarum/audio/dsp/Convolv.kt +++ b/src/net/torvald/terrarum/audio/dsp/Convolv.kt @@ -1,17 +1,34 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath +import net.torvald.terrarum.App import net.torvald.terrarum.App.setDebugTime import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE +import net.torvald.terrarum.ui.BasicDebugInfoWindow +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2 +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2_RED +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2_YELLOW +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD_RED +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD_YELLOW +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W +import net.torvald.terrarum.ui.Toolkit import java.io.File +import kotlin.math.roundToInt -class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { +/** + * @param ir Binary file containing MONO IR + * @param crossfeed The amount of channel crossfeeding to simulate the stereo ID + */ +class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter() { + private val gain: Float = gain / (1f + crossfeed) val fftLen: Int private val convFFT: Array -// private val inbuf: Array - private val sumbuf: ComplexArray + private val sumbuf: Array private val BLOCKSIZE = TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE @@ -31,8 +48,7 @@ class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { println("IR '${ir.path}' Sample Count = $sampleCount; FFT Length = $fftLen") val conv = Array(2) { FloatArray(fftLen) } -// inbuf = Array(2) { ComplexArray(FloatArray(fftLen * 2)) } - sumbuf = ComplexArray(FloatArray(fftLen * 2)) + sumbuf = Array(2) { ComplexArray(FloatArray(fftLen * 2)) } ir.inputStream().let { for (i in 0 until sampleCount) { @@ -93,8 +109,8 @@ class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { pushSum(gain, inbuf[0], inbuf[1], sumbuf) - convolve(sumbuf, convFFT[0], fftOutL) - convolve(sumbuf, convFFT[1], fftOutR) + convolve(sumbuf[0], convFFT[0], fftOutL) + convolve(sumbuf[1], convFFT[1], fftOutR) for (i in 0 until BLOCKSIZE) { outbuf[0][i] = fftOutL[fftLen - BLOCKSIZE + i] @@ -109,7 +125,7 @@ class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { } - fun push(gain: Float, samples: FloatArray, buf: ComplexArray) { + private fun push(gain: Float, samples: FloatArray, buf: ComplexArray) { // shift numbers System.arraycopy(buf.reim, samples.size * 2, buf.reim, 0, buf.reim.size - samples.size * 2) // fill in the shifted area @@ -120,15 +136,42 @@ class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { } } - fun pushSum(gain: Float, sampleL: FloatArray, sampleR: FloatArray, buf: ComplexArray) { + private fun pushSum(gain: Float, sampleL: FloatArray, sampleR: FloatArray, sumbuf: Array) { // shift numbers - System.arraycopy(buf.reim, sampleL.size * 2, buf.reim, 0, buf.reim.size - sampleL.size * 2) + System.arraycopy(sumbuf[0].reim, sampleL.size * 2, sumbuf[0].reim, 0, sumbuf[0].reim.size - sampleL.size * 2) + System.arraycopy(sumbuf[1].reim, sampleL.size * 2, sumbuf[1].reim, 0, sumbuf[1].reim.size - sampleL.size * 2) // fill in the shifted area - val baseI = buf.reim.size - sampleL.size * 2 + val baseI = sumbuf[0].reim.size - sampleL.size * 2 for (index in sampleL.indices) { - buf.reim[baseI + index * 2 + 0] = (sampleL[index] + sampleR[index]) * gain - buf.reim[baseI + index * 2 + 1] = 0f + sumbuf[0].reim[baseI + index * 2 + 0] = (sampleL[index] * 1.000000f + sampleR[index] * crossfeed) * gain + sumbuf[0].reim[baseI + index * 2 + 1] = 0f + sumbuf[1].reim[baseI + index * 2 + 0] = (sampleL[index] * crossfeed + sampleR[index] * 1.000000f) * gain + sumbuf[1].reim[baseI + index * 2 + 1] = 0f } } + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + // processing speed bar + val w = processingSpeed + val perc = w.coerceAtMost(2f) / 2f + batch.color = if (w > 1.5f) COL_METER_GRAD2 else if (w > 1f) COL_METER_GRAD2_YELLOW else COL_METER_GRAD2_RED + Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), STRIP_W * perc, 14f) + batch.color = if (w > 1.5f) COL_METER_GRAD else if (w > 1f) COL_METER_GRAD_YELLOW else COL_METER_GRAD_RED + Toolkit.fillArea(batch, x.toFloat(), y+14f, STRIP_W * perc, 2f) + + // filter length bar + val g = FastMath.intLog2(AUDIO_BUFFER_SIZE) + val perc2 = (FastMath.intLog2(fftLen).minus(g).toFloat() / (16f - g)).coerceIn(0f, 1f) + batch.color = COL_METER_GRAD2 + Toolkit.fillArea(batch, x.toFloat(), y + 16f, STRIP_W * perc2, 14f) + batch.color = COL_METER_GRAD + Toolkit.fillArea(batch, x.toFloat(), y + 16f+14f, STRIP_W * perc2, 2f) + + // texts + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "P:${processingSpeed.times(100).roundToInt().div(100f)}x", x+3f, y+1f) + App.fontSmallNumbers.draw(batch, "L:${fftLen}", x+3f, y+17f) + } + + override val debugViewHeight = 32 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Gain.kt b/src/net/torvald/terrarum/audio/dsp/Gain.kt index 8782521f0..9e0b2a51b 100644 --- a/src/net/torvald/terrarum/audio/dsp/Gain.kt +++ b/src/net/torvald/terrarum/audio/dsp/Gain.kt @@ -1,6 +1,11 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.terrarum.App import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.audio.fullscaleToDecibels +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE +import kotlin.math.roundToInt class Gain(var gain: Float): TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { @@ -9,4 +14,11 @@ class Gain(var gain: Float): TerrarumAudioFilter() { outbuf[1][i] = inbuf[1][i] * gain } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "G:${fullscaleToDecibels(gain.toDouble()).times(100).roundToInt().div(100f)}", x+3f, y+1f) + } + + override val debugViewHeight = 16 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Highpass.kt b/src/net/torvald/terrarum/audio/dsp/Highpass.kt index 2aa14f38f..6c816414d 100644 --- a/src/net/torvald/terrarum/audio/dsp/Highpass.kt +++ b/src/net/torvald/terrarum/audio/dsp/Highpass.kt @@ -1,7 +1,15 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath +import net.torvald.terrarum.App import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.audio.linToLogPerc +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2 +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W +import net.torvald.terrarum.ui.Toolkit class Highpass(cutoff0: Float): TerrarumAudioFilter() { @@ -47,4 +55,17 @@ class Highpass(cutoff0: Float): TerrarumAudioFilter() { } } + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + val perc = 1f - linToLogPerc(cutoff, 2.0, 24000.0).toFloat() + batch.color = COL_METER_GRAD2 + Toolkit.fillArea(batch, x.toFloat() + STRIP_W, y.toFloat(), -STRIP_W * perc, 14f) + batch.color = COL_METER_GRAD + Toolkit.fillArea(batch, x.toFloat() + STRIP_W, y+14f, -STRIP_W * perc, 2f) + + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "F:${cutoff.toInt()}", x+3f, y+1f) + } + + override val debugViewHeight = 16 + } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Lowpass.kt b/src/net/torvald/terrarum/audio/dsp/Lowpass.kt index 20f71162a..b34cb25c1 100644 --- a/src/net/torvald/terrarum/audio/dsp/Lowpass.kt +++ b/src/net/torvald/terrarum/audio/dsp/Lowpass.kt @@ -1,7 +1,15 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath +import net.torvald.terrarum.App import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.audio.linToLogPerc +import net.torvald.terrarum.ui.BasicDebugInfoWindow +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2 +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE +import net.torvald.terrarum.ui.Toolkit class Lowpass(cutoff0: Float): TerrarumAudioFilter() { @@ -47,4 +55,16 @@ class Lowpass(cutoff0: Float): TerrarumAudioFilter() { } } + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + val perc = linToLogPerc(cutoff, 24.0, 24000.0).toFloat() + batch.color = COL_METER_GRAD2 + Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), BasicDebugInfoWindow.STRIP_W * perc, 14f) + batch.color = COL_METER_GRAD + Toolkit.fillArea(batch, x.toFloat(), y+14f, BasicDebugInfoWindow.STRIP_W * perc, 2f) + + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "F:${cutoff.toInt()}", x+3f, y+1f) + } + + override val debugViewHeight = 16 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/NullFilter.kt b/src/net/torvald/terrarum/audio/dsp/NullFilter.kt index 4c6177543..37b19a511 100644 --- a/src/net/torvald/terrarum/audio/dsp/NullFilter.kt +++ b/src/net/torvald/terrarum/audio/dsp/NullFilter.kt @@ -1,9 +1,16 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch + object NullFilter : TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { outbuf.forEachIndexed { index, outTrack -> System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + } + + override val debugViewHeight = 0 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Reverb.kt b/src/net/torvald/terrarum/audio/dsp/Reverb.kt index d7f950ffd..092cefa89 100644 --- a/src/net/torvald/terrarum/audio/dsp/Reverb.kt +++ b/src/net/torvald/terrarum/audio/dsp/Reverb.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import kotlin.math.roundToInt @@ -46,4 +47,9 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: } } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + } + + override val debugViewHeight = 0 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/Scope.kt b/src/net/torvald/terrarum/audio/dsp/Scope.kt index 9bd8e5f71..b46b40827 100644 --- a/src/net/torvald/terrarum/audio/dsp/Scope.kt +++ b/src/net/torvald/terrarum/audio/dsp/Scope.kt @@ -1,6 +1,10 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W +import net.torvald.terrarum.ui.Toolkit import kotlin.math.roundToInt class Scope : TerrarumAudioFilter() { @@ -37,4 +41,26 @@ class Scope : TerrarumAudioFilter() { System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) } } + + private val halfStripW = STRIP_W / 2 + private val scopePlotCol = Color(0x61b3df_33) + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + batch.color = scopePlotCol + val xxs = backbufR + val yys = backbufL + for (t in xxs.lastIndex downTo 0) { + val xs = xxs[t] + val ys = yys[t] + + for (i in xs.indices.reversed()) { + val px = xs[i] * halfStripW + halfStripW + val py = ys[i] * halfStripW + halfStripW + Toolkit.fillArea(batch, x + px, y + py, 1f, 1f) + } + + } + } + + override val debugViewHeight = STRIP_W } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/SoftClp.kt b/src/net/torvald/terrarum/audio/dsp/SoftClp.kt index 96fa483c8..4ba8478ed 100644 --- a/src/net/torvald/terrarum/audio/dsp/SoftClp.kt +++ b/src/net/torvald/terrarum/audio/dsp/SoftClp.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import kotlin.math.absoluteValue import kotlin.math.tanh @@ -25,4 +26,9 @@ object SoftClp : TerrarumAudioFilter() { } } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + } + + override val debugViewHeight = 0 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/dsp/TerrarumAudioFilter.kt b/src/net/torvald/terrarum/audio/dsp/TerrarumAudioFilter.kt index 61a545a10..353ddfd27 100644 --- a/src/net/torvald/terrarum/audio/dsp/TerrarumAudioFilter.kt +++ b/src/net/torvald/terrarum/audio/dsp/TerrarumAudioFilter.kt @@ -1,5 +1,7 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch + abstract class TerrarumAudioFilter { var bypass = false protected abstract fun thru(inbuf: List, outbuf: List) @@ -11,6 +13,8 @@ abstract class TerrarumAudioFilter { } else thru(inbuf, outbuf) } + abstract fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) + abstract val debugViewHeight: Int } fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray() diff --git a/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt b/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt index cc1ac949c..f11542ffc 100644 --- a/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt +++ b/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.audio.dsp +import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.audio.TerrarumAudioMixerTrack object XYtoMS: TerrarumAudioFilter() { @@ -13,6 +14,11 @@ object XYtoMS: TerrarumAudioFilter() { outbuf[1][i] = S } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + } + + override val debugViewHeight = 0 } object MStoXY: TerrarumAudioFilter() { @@ -26,4 +32,9 @@ object MStoXY: TerrarumAudioFilter() { outbuf[1][i] = Y } } + + override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { + } + + override val debugViewHeight = 0 } \ No newline at end of file diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 6592040ce..9419a56d1 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -114,14 +114,6 @@ class BasicDebugInfoWindow : UICanvas() { private infix fun Double.pow(b: Double) = Math.pow(this, b) - private fun Double?.toIntAndFrac(intLen: Int, fracLen: Int = 4): String = - if (this == null) "null" else if (this.isNaN()) "NaN" else if (this.isInfinite()) "${if (this >= 0.0) '+' else '-'}Inf" else - "${((if (this >= 0.0) "" else "-") + "${this.absoluteValue.toInt()}").padStart(intLen)}." + - (10.0 pow fracLen.toDouble()).let { d -> (this.absoluteValue.times(d) % d).toInt().toString().padStart(fracLen, '0').padEnd(fracLen) } - private fun Float?.toIntAndFrac(intLen: Int, fracLen: Int = 4): String = - if (this == null) "null" else if (this.isNaN()) "NaN" else if (this.isInfinite()) "${if (this >= 0.0) '+' else '-'}Inf" else - "${((if (this >= 0.0) "" else "-") + "${this.absoluteValue.toInt()}").padStart(intLen)}." + - (10.0 pow fracLen.toDouble()).let { d -> (this.absoluteValue.times(d) % d).toInt().toString().padStart(fracLen, '0').padEnd(fracLen) } private val gap = 14f @@ -379,44 +371,58 @@ class BasicDebugInfoWindow : UICanvas() { private val meterTroughHeight = meterGradCountMinusOne * meterGradSize + 5 private val meterHeight = meterTroughHeight - 4 - private val stripW = 54 - private val halfStripW = stripW / 2 + companion object { + fun Double?.toIntAndFrac(intLen: Int, fracLen: Int = 4): String = + if (this == null) "null" else if (this.isNaN()) "NaN" else if (this.isInfinite()) "${if (this >= 0.0) '+' else '-'}Inf" else + "${((if (this >= 0.0) "" else "-") + "${this.absoluteValue.toInt()}").padStart(intLen)}." + + (10.0.pow(fracLen)).let { d -> (this.absoluteValue.times(d) % d).toInt().toString().padStart(fracLen, '0').padEnd(fracLen) } + fun Float?.toIntAndFrac(intLen: Int, fracLen: Int = 4): String = + if (this == null) "null" else if (this.isNaN()) "NaN" else if (this.isInfinite()) "${if (this >= 0.0) '+' else '-'}Inf" else + "${((if (this >= 0.0) "" else "-") + "${this.absoluteValue.toInt()}").padStart(intLen)}." + + (10.0.pow(fracLen)).let { d -> (this.absoluteValue.times(d) % d).toInt().toString().padStart(fracLen, '0').padEnd(fracLen) } + + + val STRIP_W = 54 + + val COL_WELL = Color(0x374854_aa) + val COL_WELL2 = Color(0x3f5360_aa) + val COL_WELL3 = Color(0x485437_aa) + val COL_WELL4 = Color(0x543748_aa) + val COL_FILTER_TITLE = Color(0x5e656c_aa) + val COL_FILTER_TITLE_SHADE = Color(0x3b3f43_aa) + val COL_FILTER_WELL_BACK = Color(0x222325_aa) + val COL_MIXER_BACK = Color(0x0f110c_aa) + val COL_METER_TROUGH = Color(0x232527_aa) + + val COL_METER_GRAD = Color(0x1c5075_aa) + val COL_METER_GRAD2 = Color(0x25a0f2_aa) + + val COL_SENDS_GRAD = Color(0x5b711e_aa) + val COL_SENDS_GRAD2 = Color(0xbff12a_aa.toInt()) + + val COL_PROGRESS_GRAD = Color(0x762340_aa.toInt()) + val COL_PROGRESS_GRAD2 = Color(0xf22e7b_aa.toInt()) + + val COL_METER_GRAD_YELLOW = Color(0x62471c_aa) + val COL_METER_GRAD2_YELLOW = Color(0xc68f24_aa.toInt()) + val COL_METER_GRAD_RED = Color(0x921c34_aa.toInt()) + val COL_METER_GRAD2_RED = Color(0xfa687d_aa.toInt()) + val COL_METER_BAR = Color(0x4caee5_aa) + val COL_METER_BAR_OVER = Color(0xef8297_aa.toInt()) + val COL_METER_COMP_BAR = Color(0xf3d458_aa.toInt()) + val COL_METER_COMP_BAR2 = Color(0x7f6b18_aa.toInt()) + + val FILTER_NAME_ACTIVE = Color(0xeeeeee_bf.toInt()) + val FILTER_BYPASSED = Color(0xf1b934_bf.toInt()) + } + + private val halfStripW = STRIP_W / 2 private val stripGap = 1 private val stripFilterHeight = 16 private val stripFaderHeight = meterHeight + 20 private val numberOfFilters = 10 private val stripH = stripFaderHeight + stripFilterHeight * numberOfFilters + 16 - private val COL_WELL = Color(0x374854_aa) - private val COL_WELL2 = Color(0x3f5360_aa) - private val COL_WELL3 = Color(0x485437_aa) - private val COL_WELL4 = Color(0x543748_aa) - private val COL_FILTER_TITLE = Color(0x5e656c_aa) - private val COL_FILTER_TITLE_SHADE = Color(0x3b3f43_aa) - private val COL_FILTER_WELL_BACK = Color(0x222325_aa) - private val COL_MIXER_BACK = Color(0x0f110c_aa) - private val COL_METER_TROUGH = Color(0x232527_aa) - - private val COL_METER_GRAD = Color(0x1c5075_aa) - private val COL_METER_GRAD2 = Color(0x25a0f2_aa) - - private val COL_SENDS_GRAD = Color(0x5b711e_aa) - private val COL_SENDS_GRAD2 = Color(0xbff12a_aa.toInt()) - - private val COL_PROGRESS_GRAD = Color(0x762340_aa.toInt()) - private val COL_PROGRESS_GRAD2 = Color(0xf22e7b_aa.toInt()) - - private val COL_METER_GRAD_YELLOW = Color(0x62471c_aa) - private val COL_METER_GRAD2_YELLOW = Color(0xc68f24_aa.toInt()) - private val COL_METER_GRAD_RED = Color(0x921c34_aa.toInt()) - private val COL_METER_GRAD2_RED = Color(0xfa687d_aa.toInt()) - private val COL_METER_BAR = Color(0x4caee5_aa) - private val COL_METER_BAR_OVER = Color(0xef8297_aa.toInt()) - private val COL_METER_COMP_BAR = Color(0xf3d458_aa.toInt()) - private val COL_METER_COMP_BAR2 = Color(0x7f6b18_aa.toInt()) - - private val FILTER_NAME_ACTIVE = Color(0xeeeeee_bf.toInt()) - private val FILTER_BYPASSED = Color(0xf1b934_bf.toInt()) private val trackBack = listOf(COL_WELL, COL_WELL2) private val trackCount = 16 // cannot call AudioMixer now @@ -425,7 +431,7 @@ class BasicDebugInfoWindow : UICanvas() { private fun drawAudioMixer(batch: SpriteBatch) { - val x = App.scr.width - 186 - (AudioMixer.tracks.size + 1) * (stripW + stripGap) + val x = App.scr.width - 186 - (AudioMixer.tracks.size + 1) * (STRIP_W + stripGap) val y = App.scr.height - 38 - stripH val strips = AudioMixer.tracks + AudioMixer.masterTrack @@ -440,7 +446,7 @@ class BasicDebugInfoWindow : UICanvas() { } // draw - drawStrip(batch, x + index * (stripW + stripGap), y, track, index) + drawStrip(batch, x + index * (STRIP_W + stripGap), y, track, index) } @@ -513,35 +519,35 @@ class BasicDebugInfoWindow : UICanvas() { private fun drawStrip(batch: SpriteBatch, x: Int, y: Int, track: TerrarumAudioMixerTrack, index: Int) { // back batch.color = if (track.trackType == TrackType.MASTER) COL_WELL4 else if (track.trackType == TrackType.BUS) COL_WELL3 else trackBack[index % 2] - Toolkit.fillArea(batch, x, y, stripW, stripH) + Toolkit.fillArea(batch, x, y, STRIP_W, stripH) // strip/name separator batch.color = COL_METER_GRAD2 - Toolkit.fillArea(batch, x, y + stripH - 16, stripW, 2) + Toolkit.fillArea(batch, x, y + stripH - 16, STRIP_W, 2) // track name batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, track.name, x + 1f + (stripW - track.name.length * 7) / 2, y + stripH - 13f) + App.fontSmallNumbers.draw(batch, track.name, x + 1f + (STRIP_W - track.name.length * 7) / 2, y + stripH - 13f) // filterbank back batch.color = COL_FILTER_WELL_BACK - Toolkit.fillArea(batch, x, y, stripW, stripFilterHeight * numberOfFilters) + Toolkit.fillArea(batch, x, y, STRIP_W, stripFilterHeight * numberOfFilters) var filterBankYcursor = 0 track.filters.forEachIndexed { i, filter -> if (filter !is NullFilter) { // draw filter title back batch.color = COL_FILTER_TITLE_SHADE - Toolkit.fillArea(batch, x, y + filterBankYcursor, stripW, 16) + Toolkit.fillArea(batch, x, y + filterBankYcursor, STRIP_W, 16) batch.color = COL_FILTER_TITLE - Toolkit.fillArea(batch, x, y + filterBankYcursor, stripW, 14) + Toolkit.fillArea(batch, x, y + filterBankYcursor, STRIP_W, 14) // draw filter name batch.color = if (filter.bypass) FILTER_BYPASSED else FILTER_NAME_ACTIVE App.fontSmallNumbers.draw(batch, filter.javaClass.simpleName, x + 3f, y + filterBankYcursor + 1f) drawFilterParam(batch, x, y + filterBankYcursor + stripFilterHeight, filter, track) - filterBankYcursor += stripFilterHeight + paramViewHeight.getOrDefault(filter.javaClass.simpleName, 0) + filterBankYcursor += stripFilterHeight + filter.debugViewHeight } } val faderY = y + stripFilterHeight * numberOfFilters @@ -559,15 +565,15 @@ class BasicDebugInfoWindow : UICanvas() { ).forEachIndexed { i, s -> // gauge background batch.color = COL_METER_TROUGH - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, stripW.toFloat(), 14f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W.toFloat(), 14f) // fill the song title line with a progress bar if (i == 0 && track.currentTrack != null) { val perc = (track.currentTrack!!.samplesRead.toFloat() / track.currentTrack!!.samplesTotal).coerceAtMost(1f) batch.color = COL_PROGRESS_GRAD2 - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, stripW * perc, 14f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W * perc, 14f) batch.color = COL_PROGRESS_GRAD - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, stripW * perc, 2f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, STRIP_W * perc, 2f) } batch.color = FILTER_NAME_ACTIVE @@ -580,11 +586,11 @@ class BasicDebugInfoWindow : UICanvas() { 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) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W.toFloat(), 14f) batch.color = COL_SENDS_GRAD2 - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, stripW * perc, 14f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W * perc, 14f) batch.color = COL_SENDS_GRAD - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, stripW * perc, 2f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, STRIP_W * perc, 2f) // label batch.color = FILTER_NAME_ACTIVE @@ -597,11 +603,11 @@ class BasicDebugInfoWindow : UICanvas() { val perc = 1f // gauge background batch.color = COL_METER_TROUGH - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, stripW.toFloat(), 14f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W.toFloat(), 14f) batch.color = COL_SENDS_GRAD2 - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, stripW * perc, 14f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f, STRIP_W * perc, 14f) batch.color = COL_SENDS_GRAD - Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, stripW * perc, 2f) + Toolkit.fillArea(batch, x.toFloat(), faderY - (i + 1) * 16f + 14f, STRIP_W * perc, 2f) // label batch.color = FILTER_NAME_ACTIVE @@ -610,7 +616,7 @@ class BasicDebugInfoWindow : UICanvas() { } // fader - val sliderX = x + stripW - 12 + val sliderX = x + STRIP_W - 12 // slider text val dB = track.dBfs @@ -710,116 +716,9 @@ class BasicDebugInfoWindow : UICanvas() { } } - private val paramViewHeight = hashMapOf( - "Lowpass" to 16, - "Highpass" to 16, - "Buffer" to 16, - "BinoPan" to 32, - "Convolv" to 32, - "Gain" to 16, - "Scope" to stripW, - ) - - - private val scopePlotCol = Color(0x61b3df_33) private fun drawFilterParam(batch: SpriteBatch, x: Int, y: Int, filter: TerrarumAudioFilter, track: TerrarumAudioMixerTrack) { - when (filter) { - is Lowpass -> { - val perc = linToLogPerc(filter.cutoff, 24.0, 24000.0).toFloat() - batch.color = COL_METER_GRAD2 - Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), stripW * perc, 14f) - batch.color = COL_METER_GRAD - Toolkit.fillArea(batch, x.toFloat(), y+14f, stripW * perc, 2f) - - batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "F:${filter.cutoff.toInt()}", x+3f, y+1f) - } - is Highpass -> { - val perc = 1f - linToLogPerc(filter.cutoff, 2.0, 24000.0).toFloat() - batch.color = COL_METER_GRAD2 - Toolkit.fillArea(batch, x.toFloat() + stripW, y.toFloat(), -stripW * perc, 14f) - batch.color = COL_METER_GRAD - Toolkit.fillArea(batch, x.toFloat() + stripW, y+14f, -stripW * perc, 2f) - - batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "F:${filter.cutoff.toInt()}", x+3f, y+1f) - } - is BinoPan -> { - val w = filter.pan * 0.5f * stripW - batch.color = COL_METER_GRAD2 - Toolkit.fillArea(batch, x + stripW / 2f, y.toFloat(), w, 14f) - batch.color = COL_METER_GRAD - Toolkit.fillArea(batch, x + stripW / 2f, y+14f, w, 2f) - - batch.color = FILTER_NAME_ACTIVE - val panLabel = if (filter.pan == 0f) "" - else if (filter.pan < 0) "L${filter.pan.absoluteValue.times(100).toIntAndFrac(3,1)}" - else "R${filter.pan.absoluteValue.times(100).toIntAndFrac(3,1)}" - App.fontSmallNumbers.draw(batch, panLabel, x+3f, y+1f) - - App.fontSmallNumbers.draw(batch, "AS:${AudioMixer.SPEED_OF_SOUND.roundToInt()}", x+3f, y+17f) - } - is Buffer -> { - batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "Bs:${AUDIO_BUFFER_SIZE}", x+3f, y+1f) - } - is Convolv -> { - // processing speed bar - val w = filter.processingSpeed - val perc = w.coerceAtMost(2f) / 2f - batch.color = if (w > 1.5f) COL_METER_GRAD2 else if (w > 1f) COL_METER_GRAD2_YELLOW else COL_METER_GRAD2_RED - Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), stripW * perc, 14f) - batch.color = if (w > 1.5f) COL_METER_GRAD else if (w > 1f) COL_METER_GRAD_YELLOW else COL_METER_GRAD_RED - Toolkit.fillArea(batch, x.toFloat(), y+14f, stripW * perc, 2f) - - // filter length bar - val g = FastMath.intLog2(AUDIO_BUFFER_SIZE) - val perc2 = (FastMath.intLog2(filter.fftLen).minus(g).toFloat() / (16f - g)).coerceIn(0f, 1f) - batch.color = COL_METER_GRAD2 - Toolkit.fillArea(batch, x.toFloat(), y + 16f, stripW * perc2, 14f) - batch.color = COL_METER_GRAD - Toolkit.fillArea(batch, x.toFloat(), y + 16f+14f, stripW * perc2, 2f) - - // texts - batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "P:${filter.processingSpeed.times(100).roundToInt().div(100f)}x", x+3f, y+1f) - App.fontSmallNumbers.draw(batch, "L:${filter.fftLen}", x+3f, y+17f) - } - is Gain -> { - batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "G:${fullscaleToDecibels(filter.gain.toDouble()).times(100).roundToInt().div(100f)}", x+3f, y+1f) - } - is Scope -> { -// batch.color = COL_FILTER_WELL_BACK -// Toolkit.fillArea(batch, 200, 200, 256, 256) - - batch.color = scopePlotCol - val xxs = filter.backbufR - val yys = filter.backbufL -// var scopedSamples = 0 - for (t in xxs.lastIndex downTo 0) { - val xs = xxs[t] - val ys = yys[t] - - for (i in xs.indices.reversed()) { - /*val col = COL_METER_BAR.cpy().also { - it.a *= 0.999f - } - batch.color = col*/ - val px = xs[i] * halfStripW + halfStripW - val py = ys[i] * halfStripW + halfStripW - Toolkit.fillArea(batch, x + px, y + py, 1f, 1f) - - -// Toolkit.fillArea(batch, 328 + xs[i] * 128, 328 + ys[i] * 128, 1f, 1f) - -// scopedSamples++ - } - - } - } - } + filter.drawDebugView(batch, x, y) } private val ICON_GREEN = Color(0x33ff33_bb.toInt())