diff --git a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt index a82a35368..bdf2b431d 100644 --- a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt +++ b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt @@ -27,6 +27,7 @@ private data class Frac(var nom: Int, val denom: Int) { */ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) -> Int?, val onAudioFinished: () -> Unit) { + var pitch: Float = 1f var playbackSpeed = 1f var jitterMode = 0 // 0: none, 1: phono, 2: tape var jitterIntensity = 0f @@ -47,8 +48,8 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) else 1f / (1f - this) } - private val playRate: Float - get() = playbackSpeed.coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved + internal val playRate: Float + get() = (playbackSpeed * pitch).coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved 1 -> jitterMode1(totalSamplesPlayed.toFloat()) else -> 0f } * jitterIntensity).coerceIn(0.5f, 2f)*/ @@ -133,9 +134,9 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) } } - var validSamplesInBuf = 0 + var validSamplesInBuf = 0; private set - var totalSamplesPlayed = 0L + private var totalSamplesPlayed = 0L private val finL = FloatArray(fetchSize + 2 * PADSIZE) private val finR = FloatArray(fetchSize + 2 * PADSIZE) @@ -155,7 +156,8 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) } fun fetchBytes() { - val readCount = if (validSamplesInBuf < App.audioBufferSize) fetchSize else 0 + val samplesInBuf = validSamplesInBuf + val readCount = if (samplesInBuf < App.audioBufferSize) fetchSize else 0 val writeCount = (readCount / q).roundToInt() fun getFromReadBuf(i: Int, bytesRead: Int) = if (i < bytesRead) readBuf[i].toUint() else 0 @@ -195,16 +197,16 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) resampleBlock(finL, finR, fmidL, fmidR, writeCount) // fill in the output buffers - System.arraycopy(fmidL, 0, foutL, validSamplesInBuf, writeCount) - System.arraycopy(fmidR, 0, foutR, validSamplesInBuf, writeCount) + System.arraycopy(fmidL, 0, foutL, samplesInBuf, writeCount) + System.arraycopy(fmidR, 0, foutR, samplesInBuf, writeCount) } else { // fill in the output buffers - System.arraycopy(finL, 0, foutL, validSamplesInBuf, writeCount) - System.arraycopy(finR, 0, foutR, validSamplesInBuf, writeCount) + System.arraycopy(finL, 0, foutL, samplesInBuf, writeCount) + System.arraycopy(finR, 0, foutR, samplesInBuf, writeCount) } - validSamplesInBuf += writeCount + validSamplesInBuf = samplesInBuf + writeCount totalSamplesPlayed += writeCount } } @@ -216,20 +218,22 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) } fun getLR(): Pair { + val samplesInBuf = validSamplesInBuf + // copy into the out val outL = FloatArray(App.audioBufferSize) val outR = FloatArray(App.audioBufferSize) System.arraycopy(foutL, 0, outL, 0, App.audioBufferSize) System.arraycopy(foutR, 0, outR, 0, App.audioBufferSize) // shift bytes in the fout - System.arraycopy(foutL, App.audioBufferSize, foutL, 0, validSamplesInBuf - App.audioBufferSize) - System.arraycopy(foutR, App.audioBufferSize, foutR, 0, validSamplesInBuf - App.audioBufferSize) - for (i in validSamplesInBuf until App.audioBufferSize) { + System.arraycopy(foutL, App.audioBufferSize, foutL, 0, samplesInBuf - App.audioBufferSize) + System.arraycopy(foutR, App.audioBufferSize, foutR, 0, samplesInBuf - App.audioBufferSize) + for (i in samplesInBuf until App.audioBufferSize) { foutL[i] = 0f foutR[i] = 0f } // decrement necessary variables - validSamplesInBuf -= App.audioBufferSize + validSamplesInBuf = samplesInBuf - App.audioBufferSize return outL to outR } diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 2485acc44..19174c2a4 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -36,8 +36,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud internal var streamBuf: AudioProcessBuf? = null - internal var jitterMode = 0 - internal var jitterIntensity = 0f +// internal var jitterMode = 0 +// internal var jitterIntensity = 0f private var fout1 = listOf(emptyBuf, emptyBuf) @@ -88,8 +88,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud bytesRead }, { purgeStreamBuf() }).also { - it.jitterMode = jitterMode - it.jitterIntensity = jitterIntensity +// it.jitterMode = jitterMode +// it.jitterIntensity = jitterIntensity } } @@ -168,7 +168,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud track.processor.streamBuf?.playbackSpeed = dopplerFactor.toFloat() -// printdbg("dist=$distFromActor\tvol=${fullscaleToDecibels(vol)}\tcutoff=${(track.filters[1] as Lowpass).cutoff}\tdopplerFactor=$dopplerFactor") +// printdbg("dist=$distFromActor\tdopplerFactor=$dopplerFactor") } } else { @@ -208,7 +208,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud } // 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 || streamBuf == null) { + else if (!track.streamPlaying || streamBuf == null || streamBuf!!.validSamplesInBuf < App.audioBufferSize) { samplesL1 = emptyBuf samplesR1 = emptyBuf diff --git a/src/net/torvald/terrarum/gameactors/Actor.kt b/src/net/torvald/terrarum/gameactors/Actor.kt index f070a3131..18b4f197d 100644 --- a/src/net/torvald/terrarum/gameactors/Actor.kt +++ b/src/net/torvald/terrarum/gameactors/Actor.kt @@ -108,6 +108,7 @@ abstract class Actor : Comparable, Runnable { it.stop() it.filters[0] = NullFilter it.filters[1] = NullFilter + it.processor.streamBuf?.pitch = 1f } despawnHook(this) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureFurnaceAndAnvil.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureFurnaceAndAnvil.kt index e793e1037..e1da3a035 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureFurnaceAndAnvil.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureFurnaceAndAnvil.kt @@ -106,6 +106,10 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation { spawnTimer += delta + // update sound randomiser + volRand.update(delta) + + // manage audio getTrackByAudio(static).let { if (it != null && !it.isPlaying) { @@ -118,11 +122,12 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation { if (it.filters[filterIndex] !is Gain) // just in case... it.filters[filterIndex] = Gain(0f) - (it.filters[filterIndex] as Gain).gain = 0.4f // TODO randomsied undulation + (it.filters[filterIndex] as Gain).gain = 0.4f * volRand.get() } } @Transient private val filterIndex = 0 + @Transient private val volRand = ParamRandomiser(0.8f, 0.4f) override fun dispose() { super.dispose() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt index 96837cc24..69cfcdd0f 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt @@ -248,10 +248,10 @@ class FixtureJukebox : Electric, PlaysMusic { } fun setJitter(it: TerrarumAudioMixerTrack?, mode: Int, intensity: Float) { - it?.let { - it.processor.jitterMode = mode - it.processor.jitterIntensity = intensity - } +// it?.let { +// it.processor.jitterMode = mode +// it.processor.jitterIntensity = intensity +// } } fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) { @@ -263,10 +263,10 @@ class FixtureJukebox : Electric, PlaysMusic { } fun unsetJitter(actor: Actor, music: MusicContainer?) { - actor.musicTracks[music]?.let { - it.processor.jitterMode = 0 - it.processor.jitterIntensity = 0f - } +// actor.musicTracks[music]?.let { +// it.processor.jitterMode = 0 +// it.processor.jitterIntensity = 0f +// } } } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSmelterBasic.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSmelterBasic.kt index b6f1acbb1..731fa5f19 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSmelterBasic.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSmelterBasic.kt @@ -4,11 +4,11 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.Input import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.jme3.math.FastMath import net.torvald.gdx.graphics.Cvec import net.torvald.random.HQRNG import net.torvald.spriteanimation.SheetSpriteAnimation import net.torvald.terrarum.* -import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.audio.MusicContainer import net.torvald.terrarum.audio.dsp.Gain @@ -289,6 +289,9 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation { spawnTimer = 0f + // update sound randomiser + volRand.update(delta) + // manage audio getTrackByAudio(static).let { @@ -307,12 +310,13 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation { if (it.filters[filterIndex] !is Gain) // just in case... it.filters[filterIndex] = Gain(0f) - (it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature).toFloat() // TODO randomsied undulation + (it.filters[filterIndex] as Gain).gain = (it.maxVolume * temperature * volRand.get()).toFloat() } } @Transient private val filterIndex = 0 + @Transient private val volRand = ParamRandomiser(0.8f, 0.4f) override fun dispose() { super.dispose() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ParamRandomiser.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ParamRandomiser.kt new file mode 100644 index 000000000..f0160180c --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ParamRandomiser.kt @@ -0,0 +1,38 @@ +package net.torvald.terrarum.modulebasegame.gameactors + +import com.badlogic.gdx.Gdx +import com.jme3.math.FastMath + +/** + * Created by minjaesong on 2024-02-12. + */ +class ParamRandomiser(val base: Float, val mult: Float) { + + @Transient private var rngBase0 = Math.random().toFloat() // initial cycle phase (xxxxFuncX) + @Transient private var rngBase1 = getNewRandom() // flicker P0, etc + @Transient private var rngBase2 = getNewRandom() // flicker P1, etc + @Transient private val domain = 18f/64f + + private fun getNewRandom() = base + Math.random().toFloat() * mult + + fun update(delta: Float) { + // FPS-time compensation + if (Gdx.graphics.framesPerSecond > 0) { + rngBase0 += delta + } + + // reset timer + if (rngBase0 > domain) { + rngBase0 -= domain + + // flicker related + rngBase1 = rngBase2 + rngBase2 = getNewRandom() + } + } + fun get(): Float { + val funcY = FastMath.interpolateLinear(rngBase0 / domain, rngBase1, rngBase2) + return funcY + } + +} \ No newline at end of file