diff --git a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt index 0050719f7..140c2137f 100644 --- a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt +++ b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt @@ -2,7 +2,7 @@ package net.torvald.terrarum.audio import com.jme3.math.FastMath import net.torvald.terrarum.App.printdbg -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE +import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.floorToInt @@ -33,7 +33,7 @@ class AudioProcessBuf(inputSamplingRate: Int, val audioReadFun: (ByteArray) -> I else 0.0 - private val BS = BUFFER_SIZE / 4 + private val BS = AUDIO_BUFFER_SIZE } private val gcd = FastMath.getGCD(inputSamplingRate, SAMPLING_RATE) // 300 for 44100, 48000 @@ -59,12 +59,12 @@ class AudioProcessBuf(inputSamplingRate: Int, val audioReadFun: (ByteArray) -> I var validSamplesInBuf = 0 - val foutL = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 - val foutR = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 + val foutL = FloatArray(internalBufferSize + samplesOut) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 + val foutR = FloatArray(internalBufferSize + samplesOut) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 fun fetchBytes() { - val readCount = ((internalBufferSize - validSamplesInBuf) / samplesOut) * samplesIn // in samples (441 or 588 for 44100, 48000) - val writeCount = ((internalBufferSize - validSamplesInBuf) / samplesOut) * samplesOut // in samples (480 or 640 for 44100, 48000) + val readCount = ((internalBufferSize - validSamplesInBuf) / samplesOut.toFloat()).ceilToInt() * samplesIn // in samples (441 or 588 for 44100, 48000) + val writeCount = ((internalBufferSize - validSamplesInBuf) / samplesOut.toFloat()).ceilToInt() * samplesOut // in samples (480 or 640 for 44100, 48000) val readBuf = ByteArray(readCount * 4) val finL = FloatArray(readCount) val finR = FloatArray(readCount) @@ -73,47 +73,59 @@ class AudioProcessBuf(inputSamplingRate: Int, val audioReadFun: (ByteArray) -> I fun getFromReadBuf(i: Int, bytesRead: Int) = if (i < bytesRead) readBuf[i].toUint() else 0 - try { - val bytesRead = audioReadFun(readBuf) + if (readCount > 0) { + try { + val bytesRead = audioReadFun(readBuf) + printdbg(this, "Reading audio $readCount samples, got ${bytesRead?.div(4)} samples") - if (bytesRead == null || bytesRead <= 0) { - printdbg(this, "Music finished; bytesRead = $bytesRead") + if (bytesRead == null || bytesRead <= 0) { + printdbg(this, "Music finished; bytesRead = $bytesRead") - onAudioFinished() - } - else { - for(c in 0 until readCount) { - val sl = (getFromReadBuf(4 * c + 0, bytesRead) or getFromReadBuf(4 * c + 1, bytesRead).shl(8)).toShort() - val sr = (getFromReadBuf(4 * c + 2, bytesRead) or getFromReadBuf(4 * c + 3, bytesRead).shl(8)).toShort() + onAudioFinished() + } + else { + for (c in 0 until readCount) { + val sl = (getFromReadBuf(4 * c + 0, bytesRead) or getFromReadBuf( + 4 * c + 1, + bytesRead + ).shl(8)).toShort() + val sr = (getFromReadBuf(4 * c + 2, bytesRead) or getFromReadBuf( + 4 * c + 3, + bytesRead + ).shl(8)).toShort() - val fl = sl / 32767f - val fr = sr / 32767f + val fl = sl / 32767f + val fr = sr / 32767f - finL[c] = fl - finR[c] = fr + finL[c] = fl + finR[c] = fr + } } } - } - catch (e: Throwable) { - e.printStackTrace() - } - finally { - if (doResample) { - // perform resampling - resampleBlock(finL, foutL) - resampleBlock(finR, foutR) - - // fill in the output buffers - System.arraycopy(foutL, 0, this.foutL, validSamplesInBuf, writeCount) - System.arraycopy(foutR, 0, this.foutR, validSamplesInBuf, writeCount) - } - else { - // fill in the output buffers - System.arraycopy(finL, 0, this.foutL, validSamplesInBuf, writeCount) - System.arraycopy(finR, 0, this.foutR, validSamplesInBuf, writeCount) + catch (e: Throwable) { + e.printStackTrace() } + finally { + if (doResample) { + // perform resampling + resampleBlock(finL, foutL) + resampleBlock(finR, foutR) - validSamplesInBuf += writeCount + // fill in the output buffers + System.arraycopy(foutL, 0, this.foutL, validSamplesInBuf, writeCount) + System.arraycopy(foutR, 0, this.foutR, validSamplesInBuf, writeCount) + } + else { + // fill in the output buffers + System.arraycopy(finL, 0, this.foutL, validSamplesInBuf, writeCount) + System.arraycopy(finR, 0, this.foutR, validSamplesInBuf, writeCount) + } + + validSamplesInBuf += writeCount + } + } + else { + printdbg(this, "Reading audio zero samples; Buffer: $validSamplesInBuf / $internalBufferSize samples") } } diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 995fce26f..81cae1cd6 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -1,16 +1,11 @@ package net.torvald.terrarum.audio -import com.badlogic.gdx.backends.lwjgl3.audio.Mp3 import com.badlogic.gdx.utils.Queue -import javazoom.jl.decoder.Bitstream -import javazoom.jl.decoder.MP3Decoder -import net.torvald.reflection.extortField import net.torvald.reflection.forceInvoke import net.torvald.terrarum.App import net.torvald.terrarum.audio.dsp.BinoPan import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.gameactors.ActorWithBody -import net.torvald.terrarum.printStackTrace import net.torvald.terrarum.relativeXposition import net.torvald.terrarum.sqr import kotlin.math.* @@ -18,7 +13,7 @@ import kotlin.math.* /** * Created by minjaesong on 2023-11-17. */ -class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: TerrarumAudioMixerTrack): Runnable { +class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: TerrarumAudioMixerTrack): Runnable { companion object { val BACK_BUF_COUNT = 1 @@ -29,7 +24,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru private val pauseLock = java.lang.Object() - private val emptyBuf = FloatArray(bufferSize / 4) + private val emptyBuf = FloatArray(buffertaille) internal var streamBuf: AudioProcessBuf? = null @@ -123,8 +118,8 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru // get samples and apply the fader if (track.trackType == TrackType.MASTER || track.trackType == TrackType.BUS) { // combine all the inputs - samplesL1 = FloatArray(bufferSize / 4) - samplesR1 = FloatArray(bufferSize / 4) + samplesL1 = FloatArray(buffertaille) + samplesR1 = FloatArray(buffertaille) val sidechains = track.sidechainInputs // add all up @@ -159,13 +154,13 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru } else { var fin1 = listOf(samplesL1, samplesR1) - fout1 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) + fout1 = listOf(FloatArray(buffertaille), FloatArray(buffertaille)) filterStack.forEachIndexed { index, it -> it(fin1, fout1) fin1 = fout1 if (index < filterStack.lastIndex) { - fout1 = listOf(FloatArray(bufferSize / 4), FloatArray(bufferSize / 4)) + fout1 = listOf(FloatArray(buffertaille), FloatArray(buffertaille)) } } } @@ -176,7 +171,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru maxSigLevel[index] = fl.toDouble() } fout1.map { it.sumOf { it.sqr().toDouble() } }.forEachIndexed { index, fl -> - maxRMS[index] = sqrt(fl / (bufferSize / 4)) + maxRMS[index] = sqrt(fl / (buffertaille)) } hasClipping.fill(false) fout1.forEachIndexed { index, floats -> diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index 30d29f8b6..f7ec0a4ea 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt @@ -10,7 +10,6 @@ import net.torvald.terrarum.App import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter import net.torvald.terrarum.gameactors.Actor -import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.getHashStr import net.torvald.terrarum.hashStrMap import net.torvald.terrarum.modulebasegame.MusicContainer @@ -29,7 +28,7 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var ma const val SAMPLING_RATE = 48000 const val SAMPLING_RATEF = 48000f const val SAMPLING_RATED = 48000.0 - val BUFFER_SIZE = 4 * App.getConfigInt("audio_buffer_size") // n ms -> 384 * n + val AUDIO_BUFFER_SIZE = App.getConfigInt("audio_buffer_size") // n ms -> 384 * n } val hash = getHashStr() @@ -162,7 +161,7 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var ma // 1st ring of the hell: the THREADING HELL // - internal var processor = MixerTrackProcessor(BUFFER_SIZE, SAMPLING_RATE, this) + internal var processor = MixerTrackProcessor(AUDIO_BUFFER_SIZE, SAMPLING_RATE, this) /*private val processorThread = Thread(processor).also { // uncomment to multithread it.priority = MAX_PRIORITY // higher = more predictable; audio delay is very noticeable so it gets high priority it.start() @@ -172,8 +171,8 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var ma private lateinit var queueDispatcherThread: Thread init { - pcmQueue.addLast(listOf(FloatArray(BUFFER_SIZE / 4), FloatArray(BUFFER_SIZE / 4))) - pcmQueue.addLast(listOf(FloatArray(BUFFER_SIZE / 4), FloatArray(BUFFER_SIZE / 4))) + pcmQueue.addLast(listOf(FloatArray(AUDIO_BUFFER_SIZE), FloatArray(AUDIO_BUFFER_SIZE))) + pcmQueue.addLast(listOf(FloatArray(AUDIO_BUFFER_SIZE), FloatArray(AUDIO_BUFFER_SIZE))) /*if (isMaster) { // uncomment to multithread queueDispatcher = FeedSamplesToAdev(BUFFER_SIZE, SAMPLING_RATE, this) diff --git a/src/net/torvald/terrarum/audio/dsp/BinoPan.kt b/src/net/torvald/terrarum/audio/dsp/BinoPan.kt index 1dad2b2b7..467749cd6 100644 --- a/src/net/torvald/terrarum/audio/dsp/BinoPan.kt +++ b/src/net/torvald/terrarum/audio/dsp/BinoPan.kt @@ -17,7 +17,7 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() private val PANNING_CONST = 3.0 // 3dB panning rule - private val delayLine = FloatArray(TerrarumAudioMixerTrack.BUFFER_SIZE / 4) + private val delayLine = FloatArray(TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) private fun getFrom(index: Float, buf0: FloatArray, buf1: FloatArray): Float { val index = index.toInt() // TODO resampling @@ -55,7 +55,7 @@ class BinoPan(var pan: Float, var earDist: Float = 0.18f): TerrarumAudioFilter() } for (ch in 0..1) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { outbuf[ch][i] = getFrom(i - delays[ch], delayLine, inbuf[0]) * mults[ch] } } diff --git a/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt b/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt index 8e3032441..5ca01d6c7 100644 --- a/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt +++ b/src/net/torvald/terrarum/audio/dsp/Bitcrush.kt @@ -6,7 +6,7 @@ import net.torvald.terrarum.roundToFloat class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { for (ch in outbuf.indices) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { 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 diff --git a/src/net/torvald/terrarum/audio/dsp/Convolv.kt b/src/net/torvald/terrarum/audio/dsp/Convolv.kt index 7bd38a843..bb1a94c99 100644 --- a/src/net/torvald/terrarum/audio/dsp/Convolv.kt +++ b/src/net/torvald/terrarum/audio/dsp/Convolv.kt @@ -1,10 +1,9 @@ package net.torvald.terrarum.audio.dsp import com.jme3.math.FastMath -import net.torvald.terrarum.App.measureDebugTime import net.torvald.terrarum.App.setDebugTime import net.torvald.terrarum.audio.* -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE +import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE import java.io.File class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { @@ -13,7 +12,7 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { private val convFFT: Array private val inbuf: Array - private val BLOCKSIZE = TerrarumAudioMixerTrack.BUFFER_SIZE / 4 + private val BLOCKSIZE = TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE var processingSpeed = 1f; private set @@ -60,7 +59,7 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { // fill up part* dictionary // define "master" array - var c = BUFFER_SIZE / 4 + var c = AUDIO_BUFFER_SIZE val master0 = arrayListOf(c) while (c < fftLen) { master0.add(c) diff --git a/src/net/torvald/terrarum/audio/dsp/Gain.kt b/src/net/torvald/terrarum/audio/dsp/Gain.kt index c92cb86d9..8782521f0 100644 --- a/src/net/torvald/terrarum/audio/dsp/Gain.kt +++ b/src/net/torvald/terrarum/audio/dsp/Gain.kt @@ -4,7 +4,7 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack class Gain(var gain: Float): TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { outbuf[0][i] = inbuf[0][i] * gain outbuf[1][i] = inbuf[1][i] * gain } diff --git a/src/net/torvald/terrarum/audio/dsp/Reverb.kt b/src/net/torvald/terrarum/audio/dsp/Reverb.kt index 4e890e855..d7f950ffd 100644 --- a/src/net/torvald/terrarum/audio/dsp/Reverb.kt +++ b/src/net/torvald/terrarum/audio/dsp/Reverb.kt @@ -30,7 +30,7 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: val alphaHi = RCHi / (RCHi + dt) for (ch in outbuf.indices) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { val inn = inbuf[ch][i] // reverb diff --git a/src/net/torvald/terrarum/audio/dsp/Scope.kt b/src/net/torvald/terrarum/audio/dsp/Scope.kt index e9b42ef08..9bd8e5f71 100644 --- a/src/net/torvald/terrarum/audio/dsp/Scope.kt +++ b/src/net/torvald/terrarum/audio/dsp/Scope.kt @@ -4,10 +4,10 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import kotlin.math.roundToInt class Scope : TerrarumAudioFilter() { - val backbufL = Array((4096f / TerrarumAudioMixerTrack.BUFFER_SIZE * 4).roundToInt().coerceAtLeast(1)) { FloatArray( - TerrarumAudioMixerTrack.BUFFER_SIZE / 4) } - val backbufR = Array((4096f / TerrarumAudioMixerTrack.BUFFER_SIZE * 4).roundToInt().coerceAtLeast(1)) { FloatArray( - TerrarumAudioMixerTrack.BUFFER_SIZE / 4) } + val backbufL = Array((4096f / TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) { FloatArray( + TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) } + val backbufR = Array((4096f / TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) { FloatArray( + TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) } private val sqrt2p = 0.7071067811865475 @@ -17,11 +17,11 @@ class Scope : TerrarumAudioFilter() { backbufL[i] = backbufL[i - 1] backbufR[i] = backbufR[i - 1] } - backbufL[0] = FloatArray(TerrarumAudioMixerTrack.BUFFER_SIZE / 4) - backbufR[0] = FloatArray(TerrarumAudioMixerTrack.BUFFER_SIZE / 4) + backbufL[0] = FloatArray(TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) + backbufR[0] = FloatArray(TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) // plot dots - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE /4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { val y0 = inbuf[0][i] * 0.7 val x0 = -inbuf[1][i] * 0.7 // rotate the domain by -90 deg diff --git a/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt b/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt index c14691529..cc1ac949c 100644 --- a/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt +++ b/src/net/torvald/terrarum/audio/dsp/XYtoMS.kt @@ -4,7 +4,7 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack object XYtoMS: TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { val X = inbuf[0][i] val Y = inbuf[1][i] val M = (X + Y) / 2f @@ -17,7 +17,7 @@ object XYtoMS: TerrarumAudioFilter() { object MStoXY: TerrarumAudioFilter() { override fun thru(inbuf: List, outbuf: List) { - for (i in 0 until TerrarumAudioMixerTrack.BUFFER_SIZE / 4) { + for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { val M = inbuf[0][i] val S = inbuf[1][i] val X = M + S diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 38f8987f4..c98bf3b2e 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -14,7 +14,7 @@ import net.torvald.terrarum.Terrarum.mouseTileY import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.AudioMixer.dynamicSourceCount -import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE +import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE import net.torvald.terrarum.audio.dsp.* import net.torvald.terrarum.controller.TerrarumController import net.torvald.terrarum.gameworld.GameWorld @@ -454,7 +454,7 @@ class BasicDebugInfoWindow : UICanvas() { private val oldRMS = Array(trackCount) { arrayOf(0.0, 0.0) } private val oldComp = Array(trackCount) { arrayOf(0.0, 0.0) } - private fun getSmoothingFactor(sampleCount: Int) = 1.0 - (BUFFER_SIZE / (4.0 * sampleCount)) + private fun getSmoothingFactor(sampleCount: Int) = 1.0 - (AUDIO_BUFFER_SIZE / sampleCount) private val PEAK_SMOOTHING_FACTOR = getSmoothingFactor(640) private val LAMP_SMOOTHING_FACTOR = getSmoothingFactor(3200) private val RMS_SMOOTHING_FACTOR = getSmoothingFactor(12000) @@ -756,7 +756,7 @@ class BasicDebugInfoWindow : UICanvas() { } is Buffer -> { batch.color = FILTER_NAME_ACTIVE - App.fontSmallNumbers.draw(batch, "Bs:${BUFFER_SIZE/4}", x+3f, y+1f) + App.fontSmallNumbers.draw(batch, "Bs:${AUDIO_BUFFER_SIZE}", x+3f, y+1f) } is Convolv -> { // processing speed bar @@ -768,7 +768,7 @@ class BasicDebugInfoWindow : UICanvas() { Toolkit.fillArea(batch, x.toFloat(), y+14f, stripW * perc, 2f) // filter length bar - val g = FastMath.intLog2(BUFFER_SIZE / 4) + 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)