mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 08:36:07 +09:00
volume randomiser for smelter and furnace
This commit is contained in:
@@ -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) {
|
class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) -> Int?, val onAudioFinished: () -> Unit) {
|
||||||
|
|
||||||
|
var pitch: Float = 1f
|
||||||
var playbackSpeed = 1f
|
var playbackSpeed = 1f
|
||||||
var jitterMode = 0 // 0: none, 1: phono, 2: tape
|
var jitterMode = 0 // 0: none, 1: phono, 2: tape
|
||||||
var jitterIntensity = 0f
|
var jitterIntensity = 0f
|
||||||
@@ -47,8 +48,8 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
|
|||||||
else 1f / (1f - this)
|
else 1f / (1f - this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val playRate: Float
|
internal val playRate: Float
|
||||||
get() = playbackSpeed.coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved
|
get() = (playbackSpeed * pitch).coerceIn(0.5f, 2f)/*(playbackSpeed * when (jitterMode) { // disabled until arraycopy negative length bug is resolved
|
||||||
1 -> jitterMode1(totalSamplesPlayed.toFloat())
|
1 -> jitterMode1(totalSamplesPlayed.toFloat())
|
||||||
else -> 0f
|
else -> 0f
|
||||||
} * jitterIntensity).coerceIn(0.5f, 2f)*/
|
} * 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 finL = FloatArray(fetchSize + 2 * PADSIZE)
|
||||||
private val finR = 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() {
|
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()
|
val writeCount = (readCount / q).roundToInt()
|
||||||
|
|
||||||
fun getFromReadBuf(i: Int, bytesRead: Int) = if (i < bytesRead) readBuf[i].toUint() else 0
|
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)
|
resampleBlock(finL, finR, fmidL, fmidR, writeCount)
|
||||||
|
|
||||||
// fill in the output buffers
|
// fill in the output buffers
|
||||||
System.arraycopy(fmidL, 0, foutL, validSamplesInBuf, writeCount)
|
System.arraycopy(fmidL, 0, foutL, samplesInBuf, writeCount)
|
||||||
System.arraycopy(fmidR, 0, foutR, validSamplesInBuf, writeCount)
|
System.arraycopy(fmidR, 0, foutR, samplesInBuf, writeCount)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// fill in the output buffers
|
// fill in the output buffers
|
||||||
System.arraycopy(finL, 0, foutL, validSamplesInBuf, writeCount)
|
System.arraycopy(finL, 0, foutL, samplesInBuf, writeCount)
|
||||||
System.arraycopy(finR, 0, foutR, validSamplesInBuf, writeCount)
|
System.arraycopy(finR, 0, foutR, samplesInBuf, writeCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
validSamplesInBuf += writeCount
|
validSamplesInBuf = samplesInBuf + writeCount
|
||||||
totalSamplesPlayed += writeCount
|
totalSamplesPlayed += writeCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,20 +218,22 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getLR(): Pair<FloatArray, FloatArray> {
|
fun getLR(): Pair<FloatArray, FloatArray> {
|
||||||
|
val samplesInBuf = validSamplesInBuf
|
||||||
|
|
||||||
// copy into the out
|
// copy into the out
|
||||||
val outL = FloatArray(App.audioBufferSize)
|
val outL = FloatArray(App.audioBufferSize)
|
||||||
val outR = FloatArray(App.audioBufferSize)
|
val outR = FloatArray(App.audioBufferSize)
|
||||||
System.arraycopy(foutL, 0, outL, 0, App.audioBufferSize)
|
System.arraycopy(foutL, 0, outL, 0, App.audioBufferSize)
|
||||||
System.arraycopy(foutR, 0, outR, 0, App.audioBufferSize)
|
System.arraycopy(foutR, 0, outR, 0, App.audioBufferSize)
|
||||||
// shift bytes in the fout
|
// shift bytes in the fout
|
||||||
System.arraycopy(foutL, App.audioBufferSize, foutL, 0, validSamplesInBuf - App.audioBufferSize)
|
System.arraycopy(foutL, App.audioBufferSize, foutL, 0, samplesInBuf - App.audioBufferSize)
|
||||||
System.arraycopy(foutR, App.audioBufferSize, foutR, 0, validSamplesInBuf - App.audioBufferSize)
|
System.arraycopy(foutR, App.audioBufferSize, foutR, 0, samplesInBuf - App.audioBufferSize)
|
||||||
for (i in validSamplesInBuf until App.audioBufferSize) {
|
for (i in samplesInBuf until App.audioBufferSize) {
|
||||||
foutL[i] = 0f
|
foutL[i] = 0f
|
||||||
foutR[i] = 0f
|
foutR[i] = 0f
|
||||||
}
|
}
|
||||||
// decrement necessary variables
|
// decrement necessary variables
|
||||||
validSamplesInBuf -= App.audioBufferSize
|
validSamplesInBuf = samplesInBuf - App.audioBufferSize
|
||||||
|
|
||||||
return outL to outR
|
return outL to outR
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
|
|||||||
|
|
||||||
internal var streamBuf: AudioProcessBuf? = null
|
internal var streamBuf: AudioProcessBuf? = null
|
||||||
|
|
||||||
internal var jitterMode = 0
|
// internal var jitterMode = 0
|
||||||
internal var jitterIntensity = 0f
|
// internal var jitterIntensity = 0f
|
||||||
|
|
||||||
private var fout1 = listOf(emptyBuf, emptyBuf)
|
private var fout1 = listOf(emptyBuf, emptyBuf)
|
||||||
|
|
||||||
@@ -88,8 +88,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
|
|||||||
|
|
||||||
bytesRead
|
bytesRead
|
||||||
}, { purgeStreamBuf() }).also {
|
}, { purgeStreamBuf() }).also {
|
||||||
it.jitterMode = jitterMode
|
// it.jitterMode = jitterMode
|
||||||
it.jitterIntensity = jitterIntensity
|
// it.jitterIntensity = jitterIntensity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
|
|||||||
|
|
||||||
track.processor.streamBuf?.playbackSpeed = dopplerFactor.toFloat()
|
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 {
|
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
|
// 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.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
|
samplesL1 = emptyBuf
|
||||||
samplesR1 = emptyBuf
|
samplesR1 = emptyBuf
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ abstract class Actor : Comparable<Actor>, Runnable {
|
|||||||
it.stop()
|
it.stop()
|
||||||
it.filters[0] = NullFilter
|
it.filters[0] = NullFilter
|
||||||
it.filters[1] = NullFilter
|
it.filters[1] = NullFilter
|
||||||
|
it.processor.streamBuf?.pitch = 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
despawnHook(this)
|
despawnHook(this)
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
|
|||||||
spawnTimer += delta
|
spawnTimer += delta
|
||||||
|
|
||||||
|
|
||||||
|
// update sound randomiser
|
||||||
|
volRand.update(delta)
|
||||||
|
|
||||||
|
|
||||||
// manage audio
|
// manage audio
|
||||||
getTrackByAudio(static).let {
|
getTrackByAudio(static).let {
|
||||||
if (it != null && !it.isPlaying) {
|
if (it != null && !it.isPlaying) {
|
||||||
@@ -118,11 +122,12 @@ class FixtureFurnaceAndAnvil : FixtureBase, CraftingStation {
|
|||||||
if (it.filters[filterIndex] !is Gain) // just in case...
|
if (it.filters[filterIndex] !is Gain) // just in case...
|
||||||
it.filters[filterIndex] = Gain(0f)
|
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 filterIndex = 0
|
||||||
|
@Transient private val volRand = ParamRandomiser(0.8f, 0.4f)
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
|
|||||||
@@ -248,10 +248,10 @@ class FixtureJukebox : Electric, PlaysMusic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setJitter(it: TerrarumAudioMixerTrack?, mode: Int, intensity: Float) {
|
fun setJitter(it: TerrarumAudioMixerTrack?, mode: Int, intensity: Float) {
|
||||||
it?.let {
|
// it?.let {
|
||||||
it.processor.jitterMode = mode
|
// it.processor.jitterMode = mode
|
||||||
it.processor.jitterIntensity = intensity
|
// it.processor.jitterIntensity = intensity
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) {
|
fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) {
|
||||||
@@ -263,10 +263,10 @@ class FixtureJukebox : Electric, PlaysMusic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun unsetJitter(actor: Actor, music: MusicContainer?) {
|
fun unsetJitter(actor: Actor, music: MusicContainer?) {
|
||||||
actor.musicTracks[music]?.let {
|
// actor.musicTracks[music]?.let {
|
||||||
it.processor.jitterMode = 0
|
// it.processor.jitterMode = 0
|
||||||
it.processor.jitterIntensity = 0f
|
// it.processor.jitterIntensity = 0f
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,11 +4,11 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.Input
|
import com.badlogic.gdx.Input
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.spriteanimation.SheetSpriteAnimation
|
import net.torvald.spriteanimation.SheetSpriteAnimation
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.audio.MusicContainer
|
import net.torvald.terrarum.audio.MusicContainer
|
||||||
import net.torvald.terrarum.audio.dsp.Gain
|
import net.torvald.terrarum.audio.dsp.Gain
|
||||||
@@ -289,6 +289,9 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation {
|
|||||||
spawnTimer = 0f
|
spawnTimer = 0f
|
||||||
|
|
||||||
|
|
||||||
|
// update sound randomiser
|
||||||
|
volRand.update(delta)
|
||||||
|
|
||||||
|
|
||||||
// manage audio
|
// manage audio
|
||||||
getTrackByAudio(static).let {
|
getTrackByAudio(static).let {
|
||||||
@@ -307,12 +310,13 @@ class FixtureSmelterBasic : FixtureBase, CraftingStation {
|
|||||||
if (it.filters[filterIndex] !is Gain) // just in case...
|
if (it.filters[filterIndex] !is Gain) // just in case...
|
||||||
it.filters[filterIndex] = Gain(0f)
|
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 filterIndex = 0
|
||||||
|
@Transient private val volRand = ParamRandomiser(0.8f, 0.4f)
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
super.dispose()
|
super.dispose()
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user