From 90681432394f0e706c42b110d8f7fb19198565b3 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Thu, 8 Feb 2024 15:04:34 +0900 Subject: [PATCH] turntable wow and flutter sim wip --- .../torvald/terrarum/audio/AudioProcessBuf.kt | 42 +++++++++++++++---- .../terrarum/audio/MixerTrackProcessor.kt | 8 +++- .../gameactors/FixtureJukebox.kt | 35 +++++++++++----- .../gameactors/FixtureMusicalTurntable.kt | 14 ++++--- 4 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt index eb053d708..5a5b90b8e 100644 --- a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt +++ b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt @@ -1,10 +1,12 @@ package net.torvald.terrarum.audio +import com.jme3.math.FastMath import net.torvald.terrarum.App import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.floorToInt +import net.torvald.terrarum.printStackTrace import net.torvald.terrarum.serialise.toUint import org.dyn4j.Epsilon import kotlin.math.PI @@ -27,17 +29,40 @@ private data class Frac(var nom: Int, val denom: Int) { class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) -> Int?, val onAudioFinished: () -> Unit) { var playbackSpeed = 1f - set(value) { - field = value.coerceIn(0.5f, 2f) - } + var jitterMode = 0 // 0: none, 1: phono, 2: tape + var jitterIntensity = 0f + + + private fun _jitterPhonoEccentricity(t: Float): Float { + val a = FastMath.TWO_PI * t * RPM + val b = 60f * SAMPLING_RATE + return sin(a / b).toRate() + } + + private fun jitterMode1(t: Float): Float { + return _jitterPhonoEccentricity(t) + } + + private fun Float.toRate(): Float { + return if (this >= 0f) 1f + this + 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 + 1 -> jitterMode1(totalSamplesPlayed.toFloat()) + else -> 0f + } * jitterIntensity).coerceIn(0.5f, 2f)*/ private val internalSamplingRate - get() = inputSamplingRate * playbackSpeed + get() = inputSamplingRate * playRate private val doResample - get() = !(inputSamplingRate == SAMPLING_RATE && (playbackSpeed - 1f).absoluteValue < (1f / 1024f)) + get() = !(inputSamplingRate == SAMPLING_RATE && (playRate - 1f).absoluteValue < (1f / 1024f)) companion object { + private val RPM = 45f + private val epsilon: Double = Epsilon.E private val TAPS = 4 // 2*a tap lanczos intp. Lower = greater artefacts @@ -111,10 +136,12 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) var validSamplesInBuf = 0 + var totalSamplesPlayed = 0L + private val finL = FloatArray(fetchSize + 2 * PADSIZE) private val finR = FloatArray(fetchSize + 2 * PADSIZE) - private val fmidL = FloatArray((fetchSize / q + 1.0).toInt() * 2) - private val fmidR = FloatArray((fetchSize / q + 1.0).toInt() * 2) + private val fmidL = FloatArray((fetchSize * 2 + 1.0).toInt()) + private val fmidR = FloatArray((fetchSize * 2 + 1.0).toInt()) private val foutL = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 private val foutR = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4 private val readBuf = ByteArray(fetchSize * 4) @@ -179,6 +206,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) } validSamplesInBuf += writeCount + totalSamplesPlayed += writeCount } } else { diff --git a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt index 362ae1845..7b5f27038 100644 --- a/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt +++ b/src/net/torvald/terrarum/audio/MixerTrackProcessor.kt @@ -36,6 +36,9 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud internal var streamBuf: AudioProcessBuf? = null + internal var jitterMode = 0 + internal var jitterIntensity = 0f + private var fout1 = listOf(emptyBuf, emptyBuf) val maxSigLevel = arrayOf(0.0, 0.0) @@ -84,7 +87,10 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud } bytesRead - }, { purgeStreamBuf() }) + }, { purgeStreamBuf() }).also { + it.jitterMode = jitterMode + it.jitterIntensity = jitterIntensity + } } private fun read0(buffer: ByteArray, bytesRead: Int): Int { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt index 6f559822b..fabd18a90 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt @@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.gameactors import com.badlogic.gdx.Gdx import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.jme3.math.FastMath import net.torvald.gdx.graphics.Cvec @@ -13,8 +12,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN import net.torvald.terrarum.audio.TerrarumAudioMixerTrack -import net.torvald.terrarum.audio.dsp.Convolv -import net.torvald.terrarum.audio.dsp.LoFi import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.Phono import net.torvald.terrarum.gameactors.AVKey @@ -93,7 +90,7 @@ class FixtureJukebox : Electric, PlaysMusic { App.audioMixerReloadHooks[this] = { - loadConvolver(musicTracks[musicNowPlaying]) + loadEffector(musicTracks[musicNowPlaying]) } despawnHook = { @@ -131,7 +128,7 @@ class FixtureJukebox : Electric, PlaysMusic { printdbg(this, "Title: $title, artist: $artist") musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) { - unloadConvolver(musicNowPlaying) + unloadEffector(musicNowPlaying) discCurrentlyPlaying = null musicNowPlaying?.gdxMusic?.tryDispose() musicNowPlaying = null @@ -149,7 +146,7 @@ class FixtureJukebox : Electric, PlaysMusic { discCurrentlyPlaying = index App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, DEFAULT_FADEOUT_LEN / 2f) { - startAudio(musicNowPlaying!!) { loadConvolver(it) } + startAudio(musicNowPlaying!!) { loadEffector(it) } } @@ -210,19 +207,21 @@ class FixtureJukebox : Electric, PlaysMusic { private fun stopDiscPlayback() { musicNowPlaying?.let { stopAudio(it) - unloadConvolver(it) + unloadEffector(it) } backLamp.currentFrame = 0 playMech.currentFrame = 0 } - private fun loadConvolver(it: TerrarumAudioMixerTrack?) { - Companion.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin") + private fun loadEffector(it: TerrarumAudioMixerTrack?) { + loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin") + setJitter(it, 1, 0.005f) } - private fun unloadConvolver(music: MusicContainer?) { - Companion.unloadConvolver(this, filterIndex, music) + private fun unloadEffector(music: MusicContainer?) { + unloadConvolver(this, filterIndex, music) + unsetJitter(this, music) } override fun reload() { @@ -248,6 +247,13 @@ class FixtureJukebox : Electric, PlaysMusic { )) } + fun setJitter(it: TerrarumAudioMixerTrack?, mode: Int, intensity: Float) { + it?.let { + it.processor.jitterMode = mode + it.processor.jitterIntensity = intensity + } + } + fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) { if (music != null) { actor.musicTracks[music]?.let { @@ -255,5 +261,12 @@ class FixtureJukebox : Electric, PlaysMusic { } } } + + fun unsetJitter(actor: Actor, music: MusicContainer?) { + 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/FixtureMusicalTurntable.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt index cbe4dee6c..111e4231b 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt @@ -55,7 +55,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic { App.audioMixerReloadHooks[this] = { - loadConvolver(musicTracks[musicNowPlaying]) + loadEffector(musicTracks[musicNowPlaying]) } despawnHook = { @@ -120,7 +120,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic { App.printdbg(this, "Title: $title, artist: $artist") musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) { - unloadConvolver(musicNowPlaying) + unloadEffector(musicNowPlaying) musicNowPlaying?.gdxMusic?.tryDispose() musicNowPlaying = null @@ -132,7 +132,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic { } App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 2f) { - startAudio(musicNowPlaying!!) { loadConvolver(it) } + startAudio(musicNowPlaying!!) { loadEffector(it) } } (sprite as SheetSpriteAnimation).currentRow = 0 @@ -152,18 +152,20 @@ class FixtureMusicalTurntable : Electric, PlaysMusic { private fun stopDiscPlayback() { musicNowPlaying?.let { stopAudio(it) - unloadConvolver(it) + unloadEffector(it) } (sprite as SheetSpriteAnimation).currentRow = 1 } - private fun loadConvolver(it: TerrarumAudioMixerTrack?) { + private fun loadEffector(it: TerrarumAudioMixerTrack?) { FixtureJukebox.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - small_speaker_Gallien Krueger GK 250ML B5 Left A 230 200 320.bin", 3.5f / 16f, 0.8f) + FixtureJukebox.setJitter(it, 1, 0.01f) } - private fun unloadConvolver(music: MusicContainer?) { + private fun unloadEffector(music: MusicContainer?) { FixtureJukebox.unloadConvolver(this, filterIndex, music) + FixtureJukebox.unsetJitter(this, music) } override fun reload() {