mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 12:04:06 +09:00
turntable wow and flutter sim wip
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
package net.torvald.terrarum.audio
|
package net.torvald.terrarum.audio
|
||||||
|
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
||||||
import net.torvald.terrarum.ceilToInt
|
import net.torvald.terrarum.ceilToInt
|
||||||
import net.torvald.terrarum.floorToInt
|
import net.torvald.terrarum.floorToInt
|
||||||
|
import net.torvald.terrarum.printStackTrace
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import org.dyn4j.Epsilon
|
import org.dyn4j.Epsilon
|
||||||
import kotlin.math.PI
|
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) {
|
class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) -> Int?, val onAudioFinished: () -> Unit) {
|
||||||
|
|
||||||
var playbackSpeed = 1f
|
var playbackSpeed = 1f
|
||||||
set(value) {
|
var jitterMode = 0 // 0: none, 1: phono, 2: tape
|
||||||
field = value.coerceIn(0.5f, 2f)
|
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
|
private val internalSamplingRate
|
||||||
get() = inputSamplingRate * playbackSpeed
|
get() = inputSamplingRate * playRate
|
||||||
|
|
||||||
private val doResample
|
private val doResample
|
||||||
get() = !(inputSamplingRate == SAMPLING_RATE && (playbackSpeed - 1f).absoluteValue < (1f / 1024f))
|
get() = !(inputSamplingRate == SAMPLING_RATE && (playRate - 1f).absoluteValue < (1f / 1024f))
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val RPM = 45f
|
||||||
|
|
||||||
private val epsilon: Double = Epsilon.E
|
private val epsilon: Double = Epsilon.E
|
||||||
|
|
||||||
private val TAPS = 4 // 2*a tap lanczos intp. Lower = greater artefacts
|
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 validSamplesInBuf = 0
|
||||||
|
|
||||||
|
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)
|
||||||
private val fmidL = FloatArray((fetchSize / q + 1.0).toInt() * 2)
|
private val fmidL = FloatArray((fetchSize * 2 + 1.0).toInt())
|
||||||
private val fmidR = FloatArray((fetchSize / q + 1.0).toInt() * 2)
|
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 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 foutR = FloatArray(internalBufferSize) // 640 for (44100, 48000), 512 for (48000, 48000) with BUFFER_SIZE = 512 * 4
|
||||||
private val readBuf = ByteArray(fetchSize * 4)
|
private val readBuf = ByteArray(fetchSize * 4)
|
||||||
@@ -179,6 +206,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
|
|||||||
}
|
}
|
||||||
|
|
||||||
validSamplesInBuf += writeCount
|
validSamplesInBuf += writeCount
|
||||||
|
totalSamplesPlayed += writeCount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ 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 jitterIntensity = 0f
|
||||||
|
|
||||||
private var fout1 = listOf(emptyBuf, emptyBuf)
|
private var fout1 = listOf(emptyBuf, emptyBuf)
|
||||||
|
|
||||||
val maxSigLevel = arrayOf(0.0, 0.0)
|
val maxSigLevel = arrayOf(0.0, 0.0)
|
||||||
@@ -84,7 +87,10 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
|
|||||||
}
|
}
|
||||||
|
|
||||||
bytesRead
|
bytesRead
|
||||||
}, { purgeStreamBuf() })
|
}, { purgeStreamBuf() }).also {
|
||||||
|
it.jitterMode = jitterMode
|
||||||
|
it.jitterIntensity = jitterIntensity
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun read0(buffer: ByteArray, bytesRead: Int): Int {
|
private fun read0(buffer: ByteArray, bytesRead: Int): Int {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.gameactors
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.Texture
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
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.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN
|
import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN
|
||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
|
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.NullFilter
|
||||||
import net.torvald.terrarum.audio.dsp.Phono
|
import net.torvald.terrarum.audio.dsp.Phono
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
@@ -93,7 +90,7 @@ class FixtureJukebox : Electric, PlaysMusic {
|
|||||||
|
|
||||||
|
|
||||||
App.audioMixerReloadHooks[this] = {
|
App.audioMixerReloadHooks[this] = {
|
||||||
loadConvolver(musicTracks[musicNowPlaying])
|
loadEffector(musicTracks[musicNowPlaying])
|
||||||
}
|
}
|
||||||
|
|
||||||
despawnHook = {
|
despawnHook = {
|
||||||
@@ -131,7 +128,7 @@ class FixtureJukebox : Electric, PlaysMusic {
|
|||||||
printdbg(this, "Title: $title, artist: $artist")
|
printdbg(this, "Title: $title, artist: $artist")
|
||||||
|
|
||||||
musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) {
|
musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) {
|
||||||
unloadConvolver(musicNowPlaying)
|
unloadEffector(musicNowPlaying)
|
||||||
discCurrentlyPlaying = null
|
discCurrentlyPlaying = null
|
||||||
musicNowPlaying?.gdxMusic?.tryDispose()
|
musicNowPlaying?.gdxMusic?.tryDispose()
|
||||||
musicNowPlaying = null
|
musicNowPlaying = null
|
||||||
@@ -149,7 +146,7 @@ class FixtureJukebox : Electric, PlaysMusic {
|
|||||||
discCurrentlyPlaying = index
|
discCurrentlyPlaying = index
|
||||||
|
|
||||||
App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, DEFAULT_FADEOUT_LEN / 2f) {
|
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() {
|
private fun stopDiscPlayback() {
|
||||||
musicNowPlaying?.let {
|
musicNowPlaying?.let {
|
||||||
stopAudio(it)
|
stopAudio(it)
|
||||||
unloadConvolver(it)
|
unloadEffector(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
backLamp.currentFrame = 0
|
backLamp.currentFrame = 0
|
||||||
playMech.currentFrame = 0
|
playMech.currentFrame = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadConvolver(it: TerrarumAudioMixerTrack?) {
|
private fun loadEffector(it: TerrarumAudioMixerTrack?) {
|
||||||
Companion.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin")
|
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?) {
|
private fun unloadEffector(music: MusicContainer?) {
|
||||||
Companion.unloadConvolver(this, filterIndex, music)
|
unloadConvolver(this, filterIndex, music)
|
||||||
|
unsetJitter(this, music)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reload() {
|
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?) {
|
fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) {
|
||||||
if (music != null) {
|
if (music != null) {
|
||||||
actor.musicTracks[music]?.let {
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic {
|
|||||||
|
|
||||||
|
|
||||||
App.audioMixerReloadHooks[this] = {
|
App.audioMixerReloadHooks[this] = {
|
||||||
loadConvolver(musicTracks[musicNowPlaying])
|
loadEffector(musicTracks[musicNowPlaying])
|
||||||
}
|
}
|
||||||
|
|
||||||
despawnHook = {
|
despawnHook = {
|
||||||
@@ -120,7 +120,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic {
|
|||||||
App.printdbg(this, "Title: $title, artist: $artist")
|
App.printdbg(this, "Title: $title, artist: $artist")
|
||||||
|
|
||||||
musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) {
|
musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) {
|
||||||
unloadConvolver(musicNowPlaying)
|
unloadEffector(musicNowPlaying)
|
||||||
musicNowPlaying?.gdxMusic?.tryDispose()
|
musicNowPlaying?.gdxMusic?.tryDispose()
|
||||||
musicNowPlaying = null
|
musicNowPlaying = null
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ class FixtureMusicalTurntable : Electric, PlaysMusic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 2f) {
|
App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 2f) {
|
||||||
startAudio(musicNowPlaying!!) { loadConvolver(it) }
|
startAudio(musicNowPlaying!!) { loadEffector(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
(sprite as SheetSpriteAnimation).currentRow = 0
|
(sprite as SheetSpriteAnimation).currentRow = 0
|
||||||
@@ -152,18 +152,20 @@ class FixtureMusicalTurntable : Electric, PlaysMusic {
|
|||||||
private fun stopDiscPlayback() {
|
private fun stopDiscPlayback() {
|
||||||
musicNowPlaying?.let {
|
musicNowPlaying?.let {
|
||||||
stopAudio(it)
|
stopAudio(it)
|
||||||
unloadConvolver(it)
|
unloadEffector(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
(sprite as SheetSpriteAnimation).currentRow = 1
|
(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.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.unloadConvolver(this, filterIndex, music)
|
||||||
|
FixtureJukebox.unsetJitter(this, music)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reload() {
|
override fun reload() {
|
||||||
|
|||||||
Reference in New Issue
Block a user