diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt index 0f7023b95..66a3cf0fe 100644 --- a/src/net/torvald/terrarum/audio/AudioMixer.kt +++ b/src/net/torvald/terrarum/audio/AudioMixer.kt @@ -105,15 +105,16 @@ object AudioMixer: Disposable { // musicTrack.filters[0] = BinoPan((Math.random() * 2.0 - 1.0).toFloat()) // musicTrack.filters[1] = Reverb(36f, 0.92f, 1200f) -// masterTrack.filters[0] = SoftClp + 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] = Lowpass(SAMPLING_RATE / 2f) - fadeBus.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/WoodruffLane.bin")) + fadeBus.filters[0] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - CedarCreekWinery.bin")) + fadeBus.filters[1] = Gain(16f) + fadeBus.filters[3] = Lowpass(SAMPLING_RATE / 2f) masterTrack.addSidechainInput(fadeBus, 1.0) masterTrack.addSidechainInput(guiTrack, 1.0) @@ -207,20 +208,20 @@ object AudioMixer: Disposable { if (lpOutFired) { lpAkku += delta val cutoff = linPercToLog(lpAkku / lpLength, lpStart, lpTarget) - (fadeBus.filters[0] as Lowpass).setCutoff(cutoff) + fadeBus.getFilter().setCutoff(cutoff) if (lpAkku >= lpLength) { lpOutFired = false - (fadeBus.filters[0] as Lowpass).setCutoff(lpTarget) + fadeBus.getFilter().setCutoff(lpTarget) } } else if (lpInFired) { lpAkku += delta val cutoff = linPercToLog(lpAkku / lpLength, lpStart, lpTarget) - (fadeBus.filters[0] as Lowpass).setCutoff(cutoff) + fadeBus.getFilter().setCutoff(cutoff) if (lpAkku >= lpLength) { - (fadeBus.filters[0] as Lowpass).setCutoff(lpTarget) + fadeBus.getFilter().setCutoff(lpTarget) lpInFired = false } } @@ -290,7 +291,7 @@ object AudioMixer: Disposable { lpLength = length.coerceAtLeast(1.0/1024.0) lpAkku = 0.0 lpOutFired = true - lpStart = (fadeBus.filters[0] as Lowpass).cutoff + lpStart = fadeBus.getFilter().cutoff lpTarget = SAMPLING_RATED / 2.0 } } @@ -300,7 +301,7 @@ object AudioMixer: Disposable { lpLength = length.coerceAtLeast(1.0/1024.0) lpAkku = 0.0 lpInFired = true - lpStart = (fadeBus.filters[0] as Lowpass).cutoff + lpStart = fadeBus.getFilter().cutoff lpTarget = SAMPLING_RATED / 100.0 } } diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 970522d3c..1084893cc 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -27,7 +27,6 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru internal val streamBuf = AudioProcessBuf(bufferSize) internal val sideChainBufs = Array(track.sidechainInputs.size) { AudioProcessBuf(bufferSize) } - private var fout0 = listOf(emptyBuf, emptyBuf) private var fout1 = listOf(emptyBuf, emptyBuf) val maxSigLevel = arrayOf(0.0, 0.0) @@ -101,8 +100,6 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru // add all up sidechains.forEach { (side, mix) -> for (i in samplesL0!!.indices) { - samplesL0!![i] += side.processor.fout0[0][i] * (mix * track.volume).toFloat() - samplesR0!![i] += side.processor.fout0[1][i] * (mix * track.volume).toFloat() samplesL1!![i] += side.processor.fout1[0][i] * (mix * track.volume).toFloat() samplesR1!![i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat() } @@ -131,17 +128,13 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru fout1 = listOf(samplesL1!!, samplesR1!!) } else { - var fin0 = listOf(samplesL0!!, samplesR0!!) var fin1 = listOf(samplesL1!!, samplesR1!!) - fout0 = fout1 fout1 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) filterStack.forEachIndexed { index, it -> - it(fin0, fin1, fout0, fout1) - fin0 = fout0 + it(fin1, fout1) fin1 = fout1 if (index < filterStack.lastIndex) { - fout0 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) fout1 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) } } diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt index fc10151a5..d0002f6f9 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt @@ -14,21 +14,21 @@ import kotlin.math.tanh abstract class TerrarumAudioFilter { var bypass = false - protected abstract fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) - operator fun invoke(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + protected abstract fun thru(inbuf: List, outbuf: List) + operator fun invoke(inbuf: List, outbuf: List) { if (bypass) { - outbuf1.forEachIndexed { index, outTrack -> - System.arraycopy(inbuf1[index], 0, outTrack, 0, outTrack.size) + outbuf.forEachIndexed { index, outTrack -> + System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) } } - else thru(inbuf0, inbuf1, outbuf0, outbuf1) + else thru(inbuf, outbuf) } } object NullFilter : TerrarumAudioFilter() { - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { - outbuf1.forEachIndexed { index, outTrack -> - System.arraycopy(inbuf1[index], 0, outTrack, 0, outTrack.size) + override fun thru(inbuf: List, outbuf: List) { + outbuf.forEachIndexed { index, outTrack -> + System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) } } } @@ -36,12 +36,12 @@ object NullFilter : TerrarumAudioFilter() { object SoftClp : TerrarumAudioFilter() { val downForce = arrayOf(1.0f, 1.0f) - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { downForce.fill(1.0f) - for (ch in inbuf1.indices) { - val inn = inbuf1[ch] - val out = outbuf1[ch] + for (ch in inbuf.indices) { + val inn = inbuf[ch] + val out = outbuf[ch] for (i in inn.indices) { val u = inn[i] * 0.95f @@ -63,7 +63,7 @@ class Scope : TerrarumAudioFilter() { private val sqrt2p = 0.7071067811865475 - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { // shift buffer for (i in backbufL.lastIndex downTo 1) { backbufL[i] = backbufL[i - 1] @@ -74,8 +74,8 @@ class Scope : TerrarumAudioFilter() { // plot dots for (i in 0 until BUFFER_SIZE/4) { - val y0 = inbuf1[0][i] * 0.7 - val x0 = -inbuf1[1][i] * 0.7 // rotate the domain by -90 deg + val y0 = inbuf[0][i] * 0.7 + val x0 = -inbuf[1][i] * 0.7 // rotate the domain by -90 deg val x = (+x0*sqrt2p -y0*sqrt2p) * 1.414 val y = (-x0*sqrt2p -y0*sqrt2p) * 1.414 // further rotate by -45 deg then flip along the y axis @@ -85,8 +85,8 @@ class Scope : TerrarumAudioFilter() { } // copy samples over - outbuf1.forEachIndexed { index, outTrack -> - System.arraycopy(inbuf1[index], 0, outTrack, 0, outTrack.size) + outbuf.forEachIndexed { index, outTrack -> + System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) } } } @@ -116,16 +116,23 @@ class Lowpass(cutoff0: Float): TerrarumAudioFilter() { this.cutoff = cutoff } - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { - for (ch in outbuf1.indices) { - val out = outbuf1[ch] - val inn = inbuf1[ch] + val in0 = FloatArray(2) + val out0 = FloatArray(2) - out[0] = outbuf0[ch].last() + alpha * (inn[0] - outbuf0[ch].last()) + override fun thru(inbuf: List, outbuf: List) { + for (ch in outbuf.indices) { + val out = outbuf[ch] + val inn = inbuf[ch] + + + out[0] = (out0[ch].div(16f) + alpha * (inn[0].div(16f) - out0[ch].div(16f))).times(16f) - for (i in 1 until outbuf1[ch].size) { - out[i] = out[i-1] + alpha * (inn[i] - out[i-1]) + for (i in 1 until outbuf[ch].size) { + out[i] = (out[i-1].div(16f) + alpha * (inn[i].div(16f) - out[i-1].div(16f))).times(16f) } + + out0[ch] = outbuf[ch].last() + in0[ch] = inbuf[ch].last() } } @@ -137,6 +144,9 @@ class Highpass(cutoff0: Float): TerrarumAudioFilter() { var cutoff = cutoff0.toDouble(); private set private var alpha: Float = 0f + val in0 = FloatArray(2) + val out0 = FloatArray(2) + init { setCutoff(cutoff0) } @@ -157,16 +167,19 @@ class Highpass(cutoff0: Float): TerrarumAudioFilter() { this.cutoff = cutoff } - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { - for (ch in outbuf1.indices) { - val out = outbuf1[ch] - val inn = inbuf1[ch] + override fun thru(inbuf: List, outbuf: List) { + for (ch in outbuf.indices) { + val out = outbuf[ch] + val inn = inbuf[ch] - out[0] = alpha * (outbuf0[ch].last() + inn[0] - inbuf0[ch].last()) + out[0] = alpha * (out0[ch] + inn[0] - in0[ch]) - for (i in 1 until outbuf1[ch].size) { + for (i in 1 until outbuf[ch].size) { out[i] = alpha * (out[i-1] + inn[i] - inn[i-1]) } + + out0[ch] = outbuf[ch].last() + in0[ch] = inbuf[ch].last() } } @@ -178,7 +191,7 @@ object Buffer : TerrarumAudioFilter() { bypass = true } - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { bypass = true } } @@ -194,6 +207,8 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() private val PANNING_CONST = 3.0 // 3dB panning rule + private val delayLine = FloatArray(BUFFER_SIZE / 4) + private fun getFrom(index: Float, buf0: FloatArray, buf1: FloatArray): Float { val index = index.toInt() // TODO resampling return if (index >= 0) buf1[index] @@ -203,8 +218,7 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() private val delays = arrayOf(0f, 0f) private val mults = arrayOf(1f, 1f) - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List - ) { + override fun thru(inbuf: List, outbuf: List) { val angle = pan * 1.5707963f val timeDiffMax = earDist / SPEED_OF_SOUND * SAMPLING_RATEF val delayInSamples = (timeDiffMax * sin(angle)).absoluteValue @@ -232,20 +246,22 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() for (ch in 0..1) { for (i in 0 until BUFFER_SIZE / 4) { - outbuf1[ch][i] = getFrom(i - delays[ch], inbuf0[0], inbuf1[0]) * mults[ch] + outbuf[ch][i] = getFrom(i - delays[ch], delayLine, inbuf[0]) * mults[ch] } } + + push(inbuf[0], delayLine) } } class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() { - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { - for (ch in outbuf1.indices) { + override fun thru(inbuf: List, outbuf: List) { + for (ch in outbuf.indices) { for (i in 0 until BUFFER_SIZE / 4) { - val inn = ((inbuf1[ch][i] * inputGain).coerceIn(-1f, 1f) + 1f) / 2f // 0f..1f + val inn = ((inbuf[ch][i] * inputGain).coerceIn(-1f, 1f) + 1f) / 2f // 0f..1f val stepped = (inn * (steps - 1)).roundToFloat() / (steps - 1) val out = (stepped * 2f) - 1f // -1f..1f - outbuf1[ch][i] = out + outbuf[ch][i] = out } } } @@ -269,16 +285,16 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: private val out0 = FloatArray(2) - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { val RCLo: Float = 1f / (lowpass * FastMath.TWO_PI) val RCHi: Float = 1f / (highpass * FastMath.TWO_PI) val dt: Float = 1f / SAMPLING_RATEF val alphaLo = dt / (RCLo + dt) val alphaHi = RCHi / (RCHi + dt) - for (ch in outbuf1.indices) { + for (ch in outbuf.indices) { for (i in 0 until BUFFER_SIZE / 4) { - val inn = inbuf1[ch][i] + val inn = inbuf[ch][i] // reverb val rev = buf[ch][delay - 1] @@ -289,13 +305,13 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: val lp = lp0 + alphaLo * (out - lp0) unshift(lp, buf[ch]) - outbuf1[ch][i] = out + outbuf[ch][i] = out } } } } -class Convolv(ir: File, val gain: Float = decibelsToFullscale(-24.0).toFloat()): TerrarumAudioFilter() { +class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { private val fftLen: Int private val convFFT: Array> @@ -303,6 +319,8 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-24.0).toFloat()): private val BLOCKSIZE = BUFFER_SIZE / 4 + var processingSpeed = 1f; private set + init { if (!ir.exists()) { throw IllegalArgumentException("Impulse Response file '${ir.path}' does not exist.") @@ -311,7 +329,7 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-24.0).toFloat()): val sampleCount = ir.length().toInt() / 8 fftLen = FastMath.nextPowerOfTwo(sampleCount) - println("IR Sample Count = $sampleCount; FFT Length = $fftLen") +// println("IR Sample Count = $sampleCount; FFT Length = $fftLen") val conv = Array(2) { FloatArray(fftLen) } inbuf = Array(2) { FloatArray(fftLen) } @@ -339,68 +357,77 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-24.0).toFloat()): FFT.fft(conv[it]) } - println("convFFT Length = ${convFFT[0].size}") +// println("convFFT Length = ${convFFT[0].size}") } /** * https://thewolfsound.com/fast-convolution-fft-based-overlap-add-overlap-save-partitioned/ */ - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { // println("Convolv thru") val t1 = System.nanoTime() - for (ch in outbuf1.indices) { - push(inbuf1[ch].applyGain(gain), inbuf[ch]) + for (ch in outbuf.indices) { + push(inbuf[ch].applyGain(gain), this.inbuf[ch]) - val inputFFT = FFT.fft(inbuf[ch]) + val inputFFT = FFT.fft(this.inbuf[ch]) val Y = multiply(inputFFT, convFFT[ch]) val y = FFT.ifftAndGetReal(Y) val u = y.takeLast(BLOCKSIZE).toFloatArray() - System.arraycopy(u, 0, outbuf1[ch], 0, BLOCKSIZE) + System.arraycopy(u, 0, outbuf[ch], 0, BLOCKSIZE) } val t2 = System.nanoTime() - val ptime = (t2 - t1).toDouble() - val realtime = BLOCKSIZE / SAMPLING_RATED * 1000000000L - println("Processing speed: ${realtime / ptime}x") + val ptime = (t2 - t1).toFloat() + val realtime = BLOCKSIZE / SAMPLING_RATEF * 1000000000L + processingSpeed = realtime / ptime } private fun multiply(X: Array, H: Array): Array { return Array(X.size) { X[it] * H[it] } } - private fun push(samples: FloatArray, buf: FloatArray) { - System.arraycopy(buf, samples.size, buf, 0, buf.size - samples.size) - System.arraycopy(samples, 0, buf, buf.size - samples.size, samples.size) - } - - private fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray() } object XYtoMS: TerrarumAudioFilter() { - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { for (i in 0 until BUFFER_SIZE / 4) { - val X = inbuf1[0][i] - val Y = inbuf1[1][i] + val X = inbuf[0][i] + val Y = inbuf[1][i] val M = (X + Y) / 2f val S = (X - Y) / 2f - outbuf1[0][i] = M - outbuf1[1][i] = S + outbuf[0][i] = M + outbuf[1][i] = S } } } object MStoXY: TerrarumAudioFilter() { - override fun thru(inbuf0: List, inbuf1: List, outbuf0: List, outbuf1: List) { + override fun thru(inbuf: List, outbuf: List) { for (i in 0 until BUFFER_SIZE / 4) { - val M = inbuf1[0][i] - val S = inbuf1[1][i] + val M = inbuf[0][i] + val S = inbuf[1][i] val X = M + S val Y = M - S - outbuf1[0][i] = X - outbuf1[1][i] = Y + outbuf[0][i] = X + outbuf[1][i] = Y } } } + +class Gain(val 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 + } + } +} + +fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray() +fun push(samples: FloatArray, buf: FloatArray) { + System.arraycopy(buf, samples.size, buf, 0, buf.size - samples.size) + System.arraycopy(samples, 0, buf, buf.size - samples.size, samples.size) +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index 4dfe89b99..4664aeb45 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 = 512 // n ms -> 384 * n + const val BUFFER_SIZE = 8192 // n ms -> 384 * n } val hash = getHashStr() @@ -49,6 +49,8 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v val filters: Array = Array(4) { NullFilter } + inline fun getFilter() = filters.filterIsInstance().first()!! + internal val sidechainInputs = Array?>(16) { null } internal fun getSidechains(): List = sidechainInputs.map { it?.first } fun addSidechainInput(input: TerrarumAudioMixerTrack, inputVolume: TrackVolume) { diff --git a/src/net/torvald/terrarum/modulebasegame/BuildingMaker.kt b/src/net/torvald/terrarum/modulebasegame/BuildingMaker.kt index eed956915..671caa9f4 100644 --- a/src/net/torvald/terrarum/modulebasegame/BuildingMaker.kt +++ b/src/net/torvald/terrarum/modulebasegame/BuildingMaker.kt @@ -302,7 +302,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) { override fun show() { Gdx.input.inputProcessor = BuildingMakerController(this) - (AudioMixer.fadeBus.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2) + AudioMixer.fadeBus.getFilter().setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2) super.show() } diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 6ce9a9234..fb49c6707 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -292,7 +292,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { IngameRenderer.setRenderedWorld(world) blockMarkingActor.isVisible = true - (AudioMixer.fadeBus.filters[0] as Lowpass).setCutoff(SAMPLING_RATEF / 2) + AudioMixer.fadeBus.getFilter().setCutoff(SAMPLING_RATEF / 2) super.show() // this function sets gameInitialised = true diff --git a/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt b/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt index 864acc143..005a276b2 100644 --- a/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt +++ b/src/net/torvald/terrarum/modulebasegame/TitleScreen.kt @@ -270,7 +270,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) { App.bogoflops = maxOf(App.bogoflops, bogoflops) - (AudioMixer.fadeBus.filters[0] as Lowpass).setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2) + AudioMixer.fadeBus.getFilter().setCutoff(TerrarumAudioMixerTrack.SAMPLING_RATEF / 2) } diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 101eb0215..48b5ee452 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -501,7 +501,7 @@ class BasicDebugInfoWindow : UICanvas() { // slider text val dB = track.dBfs val dBstr = dB.toIntAndFrac(3,1) - val dBfs = dB.coerceIn(-dbLow, 0.0).plus(dbLow).div(dbLow).toFloat() + val faderKnobDbFs = dB.coerceIn(-dbLow, 0.0).plus(dbLow).div(dbLow + dbOver).toFloat() batch.color = FILTER_NAME_ACTIVE App.fontSmallNumbers.draw(batch, dBstr, sliderX - 23f, faderY+1f) @@ -578,7 +578,7 @@ class BasicDebugInfoWindow : UICanvas() { Toolkit.fillArea(batch, sliderX, faderY + 16, 2, meterTroughHeight) // slider handle - drawFaderHandle(batch, sliderX.toFloat(), faderY + 18f + meterHeight - dBfs * meterHeight) + drawFaderHandle(batch, sliderX.toFloat(), faderY + 18f + meterHeight - faderKnobDbFs * meterHeight) // currently streaming if (track.streamPlaying) { @@ -600,6 +600,8 @@ class BasicDebugInfoWindow : UICanvas() { "Lowpass" to 16, "Buffer" to 16, "BinoPan" to 32, + "Convolv" to 16, + "Gain" to 16, "Scope" to stripW, ) @@ -637,6 +639,14 @@ class BasicDebugInfoWindow : UICanvas() { batch.color = FILTER_NAME_ACTIVE App.fontSmallNumbers.draw(batch, "Bs:${BUFFER_SIZE/4}", x+3f, y+1f) } + is Convolv -> { + batch.color = FILTER_NAME_ACTIVE + App.fontSmallNumbers.draw(batch, "P:${filter.processingSpeed.times(100).roundToInt().div(100f)}x", x+3f, y+1f) + } + 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)