sound engine is no longer a singleton

This commit is contained in:
minjaesong
2024-01-16 02:50:47 +09:00
parent 350e205028
commit 755ced9ea4
30 changed files with 275 additions and 159 deletions

View File

@@ -335,7 +335,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
} }
else { else {
if (!transitionOngoing) if (!transitionOngoing)
transitionRequest = AudioMixer.musicTrack.isPlaying.toInt() * MODE_MOUSE_UP transitionRequest = App.audioMixer.musicTrack.isPlaying.toInt() * MODE_MOUSE_UP
} }
} }
@@ -343,7 +343,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
// prev song // prev song
if (mode < MODE_SHOW_LIST) { if (mode < MODE_SHOW_LIST) {
getPrevSongFromPlaylist()?.let { ingame.musicGovernor.unshiftPlaylist(it) } getPrevSongFromPlaylist()?.let { ingame.musicGovernor.unshiftPlaylist(it) }
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) {
ingame.musicGovernor.startMusic() // required for "intermittent" mode ingame.musicGovernor.startMusic() // required for "intermittent" mode
} }
} }
@@ -362,10 +362,10 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
2 -> { // stop 2 -> { // stop
if (mode < MODE_SHOW_LIST) { // disable stop button entirely on MODE_SHOW_LIST if (mode < MODE_SHOW_LIST) { // disable stop button entirely on MODE_SHOW_LIST
if (AudioMixer.musicTrack.isPlaying) { if (App.audioMixer.musicTrack.isPlaying) {
val thisMusic = AudioMixer.musicTrack.currentTrack val thisMusic = App.audioMixer.musicTrack.currentTrack
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f)
AudioMixer.musicTrack.nextTrack = null App.audioMixer.musicTrack.nextTrack = null
ingame.musicGovernor.stopMusic() ingame.musicGovernor.stopMusic()
thisMusic?.let { ingame.musicGovernor.queueMusicToPlayNext(it) } thisMusic?.let { ingame.musicGovernor.queueMusicToPlayNext(it) }
} }
@@ -378,7 +378,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
3 -> { // next 3 -> { // next
// next song // next song
if (mode < MODE_SHOW_LIST) { if (mode < MODE_SHOW_LIST) {
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) {
ingame.musicGovernor.startMusic() // required for "intermittent" mode, does seemingly nothing on "continuous" mode ingame.musicGovernor.startMusic() // required for "intermittent" mode, does seemingly nothing on "continuous" mode
} }
} }
@@ -410,7 +410,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
} }
else { else {
if (!transitionOngoing) if (!transitionOngoing)
transitionRequest = AudioMixer.musicTrack.isPlaying.toInt() * MODE_MOUSE_UP transitionRequest = App.audioMixer.musicTrack.isPlaying.toInt() * MODE_MOUSE_UP
} }
} }
} }
@@ -421,12 +421,12 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
val list = songsInGovernor val list = songsInGovernor
if (index < list.size) { if (index < list.size) {
// if selected song != currently playing // if selected song != currently playing
if (AudioMixer.musicTrack.currentTrack == null || list[index] != AudioMixer.musicTrack.currentTrack) { if (App.audioMixer.musicTrack.currentTrack == null || list[index] != App.audioMixer.musicTrack.currentTrack) {
// rebuild playlist // rebuild playlist
ingame.musicGovernor.queueIndexFromPlaylist(index) ingame.musicGovernor.queueIndexFromPlaylist(index)
// fade out // fade out
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) {
ingame.musicGovernor.startMusic() // required for "intermittent" mode ingame.musicGovernor.startMusic() // required for "intermittent" mode
} }
} }
@@ -442,10 +442,10 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
// (navigating into the selected album involves too much complication :p) // (navigating into the selected album involves too much complication :p)
if (ingame.musicGovernor.playlistSource != albumsList[index].canonicalPath) { if (ingame.musicGovernor.playlistSource != albumsList[index].canonicalPath) {
// fade out // fade out
AudioMixer.requestFadeOut(AudioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 3f) {
loadNewAlbum(albumsList[index]) loadNewAlbum(albumsList[index])
ingame.musicGovernor.startMusic() // required for "intermittent" mode ingame.musicGovernor.startMusic() // required for "intermittent" mode
resetPlaylistScroll(AudioMixer.musicTrack.nextTrack) resetPlaylistScroll(App.audioMixer.musicTrack.nextTrack)
} }
} }
} }
@@ -471,7 +471,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
} }
private fun resetPlaylistScroll(song: MusicContainer? = null) { private fun resetPlaylistScroll(song: MusicContainer? = null) {
val currentlyPlaying = songsInGovernor.indexOf(song ?: AudioMixer.musicTrack.currentTrack) val currentlyPlaying = songsInGovernor.indexOf(song ?: App.audioMixer.musicTrack.currentTrack)
if (currentlyPlaying >= 0) { if (currentlyPlaying >= 0) {
playlistScroll = (currentlyPlaying / PLAYLIST_LINES) * PLAYLIST_LINES playlistScroll = (currentlyPlaying / PLAYLIST_LINES) * PLAYLIST_LINES
} }
@@ -482,7 +482,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private fun getPrevSongFromPlaylist(): MusicContainer? { private fun getPrevSongFromPlaylist(): MusicContainer? {
val list = songsInGovernor.slice(songsInGovernor.indices) // make copy of the list val list = songsInGovernor.slice(songsInGovernor.indices) // make copy of the list
val nowPlaying = AudioMixer.musicTrack.currentTrack ?: return null val nowPlaying = App.audioMixer.musicTrack.currentTrack ?: return null
// find current index // find current index
val currentIndex = list.indexOfFirst { it == nowPlaying } val currentIndex = list.indexOfFirst { it == nowPlaying }
@@ -796,7 +796,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
val pnum = i + playlistScroll val pnum = i + playlistScroll
val m1 = songsInGovernor.getOrNull(pnum) val m1 = songsInGovernor.getOrNull(pnum)
val m2 = AudioMixer.musicTrack.currentTrack val m2 = App.audioMixer.musicTrack.currentTrack
val currentlyPlaying = if (m1 == null || m2 == null) false else (m1 == m2) val currentlyPlaying = if (m1 == null || m2 == null) false else (m1 == m2)
// print number // print number
@@ -988,7 +988,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
// stop button // stop button
else if (i == 2) { else if (i == 2) {
// get correct stop/play button // get correct stop/play button
val iconY = if (!AudioMixer.musicTrack.isPlaying) 1 else 0 val iconY = if (!App.audioMixer.musicTrack.isPlaying) 1 else 0
// fade if avaliable // fade if avaliable
batch.color = Color(1f, 1f, 1f, alphaBase * (1f - buttonFadePerc)) batch.color = Color(1f, 1f, 1f, alphaBase * (1f - buttonFadePerc))
batch.draw(controlButtons.get(i, iconY), btnX, btnY) batch.draw(controlButtons.get(i, iconY), btnX, btnY)
@@ -1077,7 +1077,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private val fftBarHeights = FloatArray(5) private val fftBarHeights = FloatArray(5)
private fun updateMeter() { private fun updateMeter() {
val inbuf = AudioMixer.musicTrack.extortField<MixerTrackProcessor>("processor")!!.extortField<List<FloatArray>>("fout1")!! val inbuf = App.audioMixer.musicTrack.extortField<MixerTrackProcessor>("processor")!!.extortField<List<FloatArray>>("fout1")!!
push(inbuf[0], inBuf[0]) push(inbuf[0], inBuf[0])
push(inbuf[1], inBuf[1]) push(inbuf[1], inBuf[1])
for (i in 0 until FFTSIZE) { for (i in 0 until FFTSIZE) {
@@ -1235,7 +1235,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private fun loadNewAlbum(albumDir: File) { private fun loadNewAlbum(albumDir: File) {
val albumProp = albumPropCache[albumDir] val albumProp = albumPropCache[albumDir]
AudioMixer.musicTrack.let { track -> App.audioMixer.musicTrack.let { track ->
track.doGaplessPlayback = (albumProp.diskJockeyingMode == "continuous") track.doGaplessPlayback = (albumProp.diskJockeyingMode == "continuous")
if (track.doGaplessPlayback) { if (track.doGaplessPlayback) {
track.pullNextTrack = { track.pullNextTrack = {

View File

@@ -927,7 +927,7 @@ public class App implements ApplicationListener {
} }
if (audioMixerInitialised) { if (audioMixerInitialised) {
AudioMixer.INSTANCE.dispose(); audioMixer.dispose();
} }
if (currentScreen != null) { if (currentScreen != null) {
@@ -1052,6 +1052,9 @@ public class App implements ApplicationListener {
private static Boolean audioMixerInitialised = false; private static Boolean audioMixerInitialised = false;
public static AudioMixer audioMixer;
public static int audioBufferSize;
/** /**
* Init stuffs which needs GL context * Init stuffs which needs GL context
*/ */
@@ -1203,9 +1206,10 @@ public class App implements ApplicationListener {
} }
AudioMixer.INSTANCE.getMasterVolume(); audioBufferSize = getConfigInt("audio_buffer_size");
audioMixer = new AudioMixer(audioBufferSize);
audioMixerInitialised = true; audioMixerInitialised = true;
audioManagerThread = new Thread(new AudioManagerRunnable(), "TerrarumAudioManager"); audioManagerThread = new Thread(new AudioManagerRunnable(audioMixer), "TerrarumAudioManager");
audioManagerThread.setPriority(MAX_PRIORITY); // higher = more predictable; audio delay is very noticeable so it gets high priority audioManagerThread.setPriority(MAX_PRIORITY); // higher = more predictable; audio delay is very noticeable so it gets high priority
audioManagerThread.start(); audioManagerThread.start();
@@ -1230,6 +1234,17 @@ public class App implements ApplicationListener {
printdbg(this, "PostInit done; took "+tms+" seconds"); printdbg(this, "PostInit done; took "+tms+" seconds");
} }
public static void renewAudioProcessor(int bufferSize) {
audioManagerThread.interrupt();
audioMixer.dispose();
audioBufferSize = bufferSize;
audioMixer = new AudioMixer(audioBufferSize);
audioManagerThread = new Thread(new AudioManagerRunnable(audioMixer), "TerrarumAudioManager");
audioManagerThread.setPriority(MAX_PRIORITY); // higher = more predictable; audio delay is very noticeable so it gets high priority
audioManagerThread.start();
}
private void setCameraPosition(float newX, float newY) { private void setCameraPosition(float newX, float newY) {
camera.position.set((-newX + scr.getWidth() / 2), (-newY + scr.getHeight() / 2), 0f); // deliberate integer division camera.position.set((-newX + scr.getWidth() / 2), (-newY + scr.getHeight() / 2), 0f); // deliberate integer division

View File

@@ -5,7 +5,7 @@ import net.torvald.terrarum.audio.AudioMixer
/** /**
* Created by minjaesong on 2023-11-08. * Created by minjaesong on 2023-11-08.
*/ */
class AudioManagerRunnable : Runnable { class AudioManagerRunnable(val audioMixer: AudioMixer) : Runnable {
var oldT = System.nanoTime() var oldT = System.nanoTime()
var dT = 0f var dT = 0f
@@ -16,7 +16,7 @@ class AudioManagerRunnable : Runnable {
val T = System.nanoTime() val T = System.nanoTime()
dT = (T - oldT) / 1000000000f dT = (T - oldT) / 1000000000f
oldT = T; oldT = T;
AudioMixer.update(dT) audioMixer.update(dT)
// println("AudioManagerRunnable dT = ${dT * 1000f} ms") // println("AudioManagerRunnable dT = ${dT * 1000f} ms")
Thread.sleep(1L) Thread.sleep(1L)
} }

View File

@@ -17,6 +17,7 @@ import net.torvald.terrarum.App.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE 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.AudioCodex import net.torvald.terrarum.audio.AudioCodex
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.FluidCodex import net.torvald.terrarum.blockproperties.FluidCodex
import net.torvald.terrarum.blockproperties.OreCodex import net.torvald.terrarum.blockproperties.OreCodex
@@ -70,7 +71,6 @@ object Terrarum : Disposable {
shapeRender.end() shapeRender.end()
}*/ }*/
var blockCodex = BlockCodex(); internal set var blockCodex = BlockCodex(); internal set
/** The actual contents of the ItemCodex is sum of Player's Codex and the World's Codex */ /** The actual contents of the ItemCodex is sum of Player's Codex and the World's Codex */
var itemCodex = ItemCodex(); internal set var itemCodex = ItemCodex(); internal set

View File

@@ -7,20 +7,15 @@ import com.badlogic.gdx.utils.Disposable
import com.jme3.math.FastMath import com.jme3.math.FastMath
import net.torvald.spriteanimation.AssembledSpriteAnimation import net.torvald.spriteanimation.AssembledSpriteAnimation
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.THREAD_COUNT
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.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED
import net.torvald.terrarum.audio.dsp.* import net.torvald.terrarum.audio.dsp.*
import net.torvald.terrarum.concurrent.ThreadExecutor import net.torvald.terrarum.concurrent.ThreadExecutor
import net.torvald.terrarum.concurrent.sliceEvenly
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.modulebasegame.BuildingMaker import net.torvald.terrarum.modulebasegame.BuildingMaker
import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.MusicContainer
import java.lang.Thread.MAX_PRIORITY import java.lang.Thread.MAX_PRIORITY
import java.util.* import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.atomic.AtomicReference
import kotlin.math.* import kotlin.math.*
/** /**
@@ -28,13 +23,16 @@ import kotlin.math.*
* *
* Created by minjaesong on 2023-11-07. * Created by minjaesong on 2023-11-07.
*/ */
object AudioMixer: Disposable { class AudioMixer(val bufferSize: Int): Disposable {
var SPEED_OF_SOUND = 340f
const val SPEED_OF_SOUND_AIR = 340f companion object {
const val SPEED_OF_SOUND_WATER = 1480f const val SPEED_OF_SOUND_AIR = 340f
const val SPEED_OF_SOUND_WATER = 1480f
const val SPEED_OF_SOUND = 340f
const val DEFAULT_FADEOUT_LEN = 1.8
}
const val DEFAULT_FADEOUT_LEN = 1.8
val masterVolume: Double val masterVolume: Double
get() = App.getConfigDouble("mastervolume") get() = App.getConfigDouble("mastervolume")
@@ -99,7 +97,7 @@ object AudioMixer: Disposable {
val fadeBus: TerrarumAudioMixerTrack val fadeBus: TerrarumAudioMixerTrack
get() = tracks[7] get() = tracks[7]
var processing = true var processing = false
var actorNowPlaying = Terrarum.ingame?.actorNowPlaying; private set var actorNowPlaying = Terrarum.ingame?.actorNowPlaying; private set
@@ -128,8 +126,7 @@ object AudioMixer: Disposable {
return (headSize0 ?: 0f).times(scale).coerceAtLeast(BinoPan.EARDIST_DEFAULT) return (headSize0 ?: 0f).times(scale).coerceAtLeast(BinoPan.EARDIST_DEFAULT)
} }
private val processingExecutor = ThreadExecutor() fun createProcessingThread(): Thread = Thread {
val processingThread = Thread {
// serial precessing // serial precessing
while (processing) { while (processing) {
actorNowPlaying = Terrarum.ingame?.actorNowPlaying actorNowPlaying = Terrarum.ingame?.actorNowPlaying
@@ -184,8 +181,13 @@ object AudioMixer: Disposable {
masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed
} }
}*/ }*/
}.also {
it.priority = MAX_PRIORITY // higher = more predictable; audio delay is very noticeable so it gets high priority
} }
private val processingExecutor = ThreadExecutor()
lateinit var processingThread: Thread
// val parallelProcessingSchedule: Array<Array<TerrarumAudioMixerTrack>> // val parallelProcessingSchedule: Array<Array<TerrarumAudioMixerTrack>>
@@ -246,8 +248,8 @@ object AudioMixer: Disposable {
arrayOf(fadeBus) + arrayOf(fadeBus) +
arrayOf(masterTrack)*/ arrayOf(masterTrack)*/
processingThread = createProcessingThread()
processingThread.priority = MAX_PRIORITY // higher = more predictable; audio delay is very noticeable so it gets high priority processing = true
processingThread.start() processingThread.start()
// feedingThread.priority = MAX_PRIORITY // feedingThread.priority = MAX_PRIORITY
// feedingThread.start() // feedingThread.start()
@@ -306,7 +308,7 @@ object AudioMixer: Disposable {
if (Gdx.input.isKeyPressed(Input.Keys.NUM_3)) if (Gdx.input.isKeyPressed(Input.Keys.NUM_3))
testAudioMixRatio = 1.0 testAudioMixRatio = 1.0
if (!muteLatched && Gdx.input.isKeyPressed(Input.Keys.NUM_4)) { if (!muteLatched && Gdx.input.isKeyPressed(Input.Keys.NUM_4)) {
AudioMixer.sumBus.volume = 1.0 - AudioMixer.sumBus.volume sumBus.volume = 1.0 - sumBus.volume
muteLatched = true muteLatched = true
} }
else if (!Gdx.input.isKeyPressed(Input.Keys.NUM_4)) else if (!Gdx.input.isKeyPressed(Input.Keys.NUM_4))
@@ -316,13 +318,13 @@ object AudioMixer: Disposable {
if (testAudioMixRatio >= 0.0) { if (testAudioMixRatio >= 0.0) {
val ratio1 = testAudioMixRatio.coerceIn(0.0, 1.0) val ratio1 = testAudioMixRatio.coerceIn(0.0, 1.0)
AudioMixer.convolveBusCave.volume = ratio1 convolveBusCave.volume = ratio1
AudioMixer.convolveBusOpen.volume = 1.0 - ratio1 convolveBusOpen.volume = 1.0 - ratio1
} }
else { else {
val ratio1 = (testAudioMixRatio / MaterialCodex["AIIR"].sondrefl).absoluteValue.coerceIn(0.0, 1.0) val ratio1 = (testAudioMixRatio / MaterialCodex["AIIR"].sondrefl).absoluteValue.coerceIn(0.0, 1.0)
AudioMixer.convolveBusOpen.volume = (1.0 - ratio1).pow(0.75) convolveBusOpen.volume = (1.0 - ratio1).pow(0.75)
AudioMixer.convolveBusCave.volume = 0.0 convolveBusCave.volume = 0.0
} }
} }
@@ -496,6 +498,35 @@ object AudioMixer: Disposable {
}, 500L) }, 500L)
} }
fun updateBufferSizeChange() {
processing = false
processingThread.interrupt()
dynamicTracks.forEach { it.stop() }
tracks.filter { it.trackType == TrackType.STATIC_SOURCE }.forEach { it.stop() }
masterTrack.volume = 0.0
dynamicTracks.forEach { it.updateBufferSizeChange() }
tracks.forEach { it.updateBufferSizeChange() }
masterTrack.updateBufferSizeChange()
processingThread = createProcessingThread()
processing = true
processingThread.start()
// give some time for the cave bus to decay before ramping the volume up
Timer().schedule(object : TimerTask() {
override fun run() {
masterTrack.volume = 1.0
}
}, 500L)
}
override fun dispose() { override fun dispose() {
processingExecutor.killAll() processingExecutor.killAll()
// processingSubthreads.forEach { it.interrupt() } // processingSubthreads.forEach { it.interrupt() }

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.audio package net.torvald.terrarum.audio
import com.jme3.math.FastMath import net.torvald.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE 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
@@ -54,7 +54,6 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
} }
} }
private val BS = AUDIO_BUFFER_SIZE
private val MP3_CHUNK_SIZE = 1152 // 1152 for 32k-48k, 576 for 16k-24k, 384 for 8k-12k private val MP3_CHUNK_SIZE = 1152 // 1152 for 32k-48k, 576 for 16k-24k, 384 for 8k-12k
@@ -76,13 +75,13 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
} }
} }
private fun getOptimalBufferSize(rate: Int) = bufLut[BS to rate]!! private fun getOptimalBufferSize(rate: Int) = bufLut[App.audioBufferSize to rate]!!
} }
private val q private val q
get() = internalSamplingRate.toDouble() / SAMPLING_RATE // <= 1.0 get() = internalSamplingRate.toDouble() / SAMPLING_RATE // <= 1.0
private val fetchSize = (BS.toFloat() / MP3_CHUNK_SIZE).ceilToInt() * MP3_CHUNK_SIZE // fetchSize is always multiple of MP3_CHUNK_SIZE, even if the audio is NOT MP3 private val fetchSize = (App.audioBufferSize.toFloat() / MP3_CHUNK_SIZE).ceilToInt() * MP3_CHUNK_SIZE // fetchSize is always multiple of MP3_CHUNK_SIZE, even if the audio is NOT MP3
private val internalBufferSize = getOptimalBufferSize(inputSamplingRate)// fetchSize * 3 private val internalBufferSize = getOptimalBufferSize(inputSamplingRate)// fetchSize * 3
private val PADSIZE = TAPS + 1 private val PADSIZE = TAPS + 1
@@ -120,13 +119,17 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
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)
init {
printdbg(this, "App.audioMixerBufferSize=${App.audioBufferSize}")
}
private fun shift(array: FloatArray, size: Int) { private fun shift(array: FloatArray, size: Int) {
System.arraycopy(array, size, array, 0, array.size - size) System.arraycopy(array, size, array, 0, array.size - size)
for (i in array.size - size until array.size) { array[i] = 0f } for (i in array.size - size until array.size) { array[i] = 0f }
} }
fun fetchBytes() { fun fetchBytes() {
val readCount = if (validSamplesInBuf < BS) fetchSize else 0 val readCount = if (validSamplesInBuf < 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
@@ -187,17 +190,17 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray)
fun getLR(volume: Double): Pair<FloatArray, FloatArray> { fun getLR(volume: Double): Pair<FloatArray, FloatArray> {
// copy into the out // copy into the out
val outL = FloatArray(BS) { (foutL[it] * volume).toFloat() } val outL = FloatArray(App.audioBufferSize) { (foutL[it] * volume).toFloat() }
val outR = FloatArray(BS) { (foutR[it] * volume).toFloat() } val outR = FloatArray(App.audioBufferSize) { (foutR[it] * volume).toFloat() }
// shift bytes in the fout // shift bytes in the fout
System.arraycopy(foutL, BS, foutL, 0, validSamplesInBuf - BS) System.arraycopy(foutL, App.audioBufferSize, foutL, 0, validSamplesInBuf - App.audioBufferSize)
System.arraycopy(foutR, BS, foutR, 0, validSamplesInBuf - BS) System.arraycopy(foutR, App.audioBufferSize, foutR, 0, validSamplesInBuf - App.audioBufferSize)
for (i in validSamplesInBuf until BS) { for (i in validSamplesInBuf until App.audioBufferSize) {
foutL[i] = 0f foutL[i] = 0f
foutR[i] = 0f foutR[i] = 0f
} }
// decrement necessary variables // decrement necessary variables
validSamplesInBuf -= BS validSamplesInBuf -= App.audioBufferSize
return outL to outR return outL to outR
} }

View File

@@ -1,9 +1,7 @@
package net.torvald.terrarum.audio package net.torvald.terrarum.audio
import com.badlogic.gdx.utils.Queue import com.badlogic.gdx.utils.Queue
import com.jme3.math.FastMath
import net.torvald.reflection.forceInvoke import net.torvald.reflection.forceInvoke
import net.torvald.spriteanimation.AssembledSpriteAnimation
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED
@@ -19,7 +17,18 @@ import kotlin.math.*
/** /**
* Created by minjaesong on 2023-11-17. * Created by minjaesong on 2023-11-17.
*/ */
class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: TerrarumAudioMixerTrack): Runnable { class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAudioMixerTrack): Runnable {
private var buffertaille = bufferSize
fun reset(newBufferSize: Int) {
buffertaille = newBufferSize
// printdbg("new buffertaille = $buffertaille")
emptyBuf = FloatArray(buffertaille)
fout1 = listOf(emptyBuf, emptyBuf)
purgeStreamBuf()
}
companion object { companion object {
} }
@@ -29,7 +38,7 @@ class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: Terra
private val pauseLock = java.lang.Object() private val pauseLock = java.lang.Object()
private val emptyBuf = FloatArray(buffertaille) private var emptyBuf = FloatArray(buffertaille)
internal var streamBuf: AudioProcessBuf? = null internal var streamBuf: AudioProcessBuf? = null
@@ -117,18 +126,18 @@ class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: Terra
// update panning and shits // update panning and shits
if (track.trackType == TrackType.DYNAMIC_SOURCE && track.isPlaying) { if (track.trackType == TrackType.DYNAMIC_SOURCE && track.isPlaying) {
(track.filters[0] as BinoPan).earDist = AudioMixer.listenerHeadSize (track.filters[0] as BinoPan).earDist = App.audioMixer.listenerHeadSize
if (AudioMixer.actorNowPlaying != null) { if (App.audioMixer.actorNowPlaying != null) {
if (track.trackingTarget == null || track.trackingTarget == AudioMixer.actorNowPlaying) { if (track.trackingTarget == null || track.trackingTarget == App.audioMixer.actorNowPlaying) {
// "reset" the track // "reset" the track
track.volume = track.maxVolume track.volume = track.maxVolume
(track.filters[0] as BinoPan).pan = 0f (track.filters[0] as BinoPan).pan = 0f
(track.filters[1] as Lowpass).setCutoff(SAMPLING_RATE / 2f) (track.filters[1] as Lowpass).setCutoff(SAMPLING_RATE / 2f)
} }
else if (track.trackingTarget is ActorWithBody) { else if (track.trackingTarget is ActorWithBody) {
val relativeXpos = relativeXposition(AudioMixer.actorNowPlaying!!, track.trackingTarget as ActorWithBody) val relativeXpos = relativeXposition(App.audioMixer.actorNowPlaying!!, track.trackingTarget as ActorWithBody)
val distFromActor = distBetweenActors(AudioMixer.actorNowPlaying!!, track.trackingTarget as ActorWithBody) val distFromActor = distBetweenActors(App.audioMixer.actorNowPlaying!!, track.trackingTarget as ActorWithBody)
val vol = track.maxVolume * getVolFun(distFromActor / distFalloff).coerceAtLeast(0.0) val vol = track.maxVolume * getVolFun(distFromActor / distFalloff).coerceAtLeast(0.0)
track.volume = vol track.volume = vol
(track.filters[0] as BinoPan).pan = (1.3f * relativeXpos / distFalloff).toFloat() (track.filters[0] as BinoPan).pan = (1.3f * relativeXpos / distFalloff).toFloat()
@@ -169,7 +178,13 @@ class MixerTrackProcessor(val buffertaille: Int, val rate: Int, val track: Terra
// add all up // add all up
sidechains.forEach { (side, mix) -> sidechains.forEach { (side, mix) ->
for (i in samplesL1.indices) { for (i in samplesL1.indices) {
samplesL1[i] += side.processor.fout1[0][i] * (mix * track.volume).toFloat() // try {
samplesL1[i] += side.processor.fout1[0][i] * (mix * track.volume).toFloat()
// }
// catch (e: ArrayIndexOutOfBoundsException) {
// printdbg("buffertaille = $buffertaille, samplesL1 size = ${samplesL1.size}, side.processor.fout1[0] size = ${side.processor.fout1[0].size}")
// throw e
// }
samplesR1[i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat() samplesR1[i] += side.processor.fout1[1][i] * (mix * track.volume).toFloat()
} }
} }

View File

@@ -1,11 +1,9 @@
package net.torvald.terrarum.audio package net.torvald.terrarum.audio
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.audio.Sound
import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import com.badlogic.gdx.utils.Queue import com.badlogic.gdx.utils.Queue
import net.torvald.reflection.forceInvoke
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter import net.torvald.terrarum.audio.dsp.TerrarumAudioFilter
@@ -35,7 +33,6 @@ class TerrarumAudioMixerTrack(
const val SAMPLING_RATE = 48000 const val SAMPLING_RATE = 48000
const val SAMPLING_RATEF = 48000f const val SAMPLING_RATEF = 48000f
const val SAMPLING_RATED = 48000.0 const val SAMPLING_RATED = 48000.0
val AUDIO_BUFFER_SIZE = App.getConfigInt("audio_buffer_size") // n ms -> 384 * n
} }
val hash = getHashStr() val hash = getHashStr()
@@ -168,7 +165,7 @@ class TerrarumAudioMixerTrack(
// 1st ring of the hell: the THREADING HELL // // 1st ring of the hell: the THREADING HELL //
internal var processor = MixerTrackProcessor(AUDIO_BUFFER_SIZE, SAMPLING_RATE, this) internal var processor = MixerTrackProcessor(App.audioBufferSize, SAMPLING_RATE, this)
/*private val processorThread = Thread(processor).also { // uncomment to multithread /*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.priority = MAX_PRIORITY // higher = more predictable; audio delay is very noticeable so it gets high priority
it.start() it.start()
@@ -178,8 +175,8 @@ class TerrarumAudioMixerTrack(
private lateinit var queueDispatcherThread: Thread private lateinit var queueDispatcherThread: Thread
init { init {
pcmQueue.addLast(listOf(FloatArray(AUDIO_BUFFER_SIZE), FloatArray(AUDIO_BUFFER_SIZE))) pcmQueue.addLast(listOf(FloatArray(App.audioBufferSize), FloatArray(App.audioBufferSize)))
pcmQueue.addLast(listOf(FloatArray(AUDIO_BUFFER_SIZE), FloatArray(AUDIO_BUFFER_SIZE))) pcmQueue.addLast(listOf(FloatArray(App.audioBufferSize), FloatArray(App.audioBufferSize)))
/*if (isMaster) { // uncomment to multithread /*if (isMaster) { // uncomment to multithread
queueDispatcher = FeedSamplesToAdev(BUFFER_SIZE, SAMPLING_RATE, this) queueDispatcher = FeedSamplesToAdev(BUFFER_SIZE, SAMPLING_RATE, this)
@@ -190,6 +187,16 @@ class TerrarumAudioMixerTrack(
}*/ }*/
} }
fun updateBufferSizeChange() {
// printdbg(this, "new buffer size: $App.audioMixerBufferSize")
pcmQueue.clear()
pcmQueue.addLast(listOf(FloatArray(App.audioBufferSize), FloatArray(App.audioBufferSize)))
pcmQueue.addLast(listOf(FloatArray(App.audioBufferSize), FloatArray(App.audioBufferSize)))
processor.reset(App.audioBufferSize)
filters.forEach { it.reset() }
}
override fun hashCode() = hashCode0 override fun hashCode() = hashCode0
} }

View File

@@ -3,10 +3,7 @@ package net.torvald.terrarum.audio.dsp
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.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.audio.AudioMixer import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF
import net.torvald.terrarum.audio.decibelsToFullscale import net.torvald.terrarum.audio.decibelsToFullscale
import net.torvald.terrarum.ceilToInt import net.torvald.terrarum.ceilToInt
@@ -43,8 +40,8 @@ class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAud
private val delays = arrayOf(0f, 0f) private val delays = arrayOf(0f, 0f)
private val mults = arrayOf(1f, 1f) private val mults = arrayOf(1f, 1f)
private val outLs = Array(2) { FloatArray(AUDIO_BUFFER_SIZE) } private var outLs = Array(2) { FloatArray(App.audioBufferSize) }
private val outRs = Array(2) { FloatArray(AUDIO_BUFFER_SIZE) } private var outRs = Array(2) { FloatArray(App.audioBufferSize) }
companion object { companion object {
@@ -58,6 +55,13 @@ class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAud
private val HALF_PI = (Math.PI / 2.0).toFloat() private val HALF_PI = (Math.PI / 2.0).toFloat()
} }
override fun reset() {
outLs = Array(2) { FloatArray(App.audioBufferSize) }
outRs = Array(2) { FloatArray(App.audioBufferSize) }
delayLineL.fill(0f)
delayLineR.fill(0f)
}
/** /**
* @param intensity -inf to +inf * @param intensity -inf to +inf
*/ */
@@ -104,7 +108,7 @@ class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAud
mults[R] = volMultFsOther mults[R] = volMultFsOther
} }
for (i in 0 until AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
sumbuf[L][i] = mults[L] * getFrom(i - delays[L], delayLine, inbuf) sumbuf[L][i] = mults[L] * getFrom(i - delays[L], delayLine, inbuf)
sumbuf[R][i] = mults[R] * getFrom(i - delays[R], delayLine, inbuf) sumbuf[R][i] = mults[R] * getFrom(i - delays[R], delayLine, inbuf)
} }
@@ -115,7 +119,7 @@ class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAud
thru("L", -50f, inbuf[L], outLs, delayLineL) // 50 will become 59.036 on panningFieldMap thru("L", -50f, inbuf[L], outLs, delayLineL) // 50 will become 59.036 on panningFieldMap
thru("R", +50f, inbuf[R], outRs, delayLineR) thru("R", +50f, inbuf[R], outRs, delayLineR)
for (i in 0 until AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val outL = (outLs[L][i] + outRs[L][i]) / 2f val outL = (outLs[L][i] + outRs[L][i]) / 2f
val outR = (outLs[R][i] + outRs[R][i]) / 2f val outR = (outLs[R][i] + outRs[R][i]) / 2f
outbuf[L][i] = outL outbuf[L][i] = outL

View File

@@ -3,7 +3,6 @@ package net.torvald.terrarum.audio.dsp
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.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.audio.linToLogPerc import net.torvald.terrarum.audio.linToLogPerc
import net.torvald.terrarum.roundToFloat import net.torvald.terrarum.roundToFloat
import net.torvald.terrarum.ui.BasicDebugInfoWindow import net.torvald.terrarum.ui.BasicDebugInfoWindow
@@ -13,7 +12,7 @@ import net.torvald.terrarum.ui.Toolkit
class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() { class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter() {
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) { override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
for (ch in outbuf.indices) { for (ch in outbuf.indices) {
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val inn = ((inbuf[ch][i] * inputGain).coerceIn(-1f, 1f) + 1f) / 2f // 0f..1f val inn = ((inbuf[ch][i] * inputGain).coerceIn(-1f, 1f) + 1f) / 2f // 0f..1f
val stepped = (inn * (steps - 1)).roundToFloat() / (steps - 1) val stepped = (inn * (steps - 1)).roundToFloat() / (steps - 1)
val out = (stepped * 2f) - 1f // -1f..1f val out = (stepped * 2f) - 1f // -1f..1f
@@ -35,5 +34,8 @@ class Bitcrush(var steps: Int, var inputGain: Float = 1f): TerrarumAudioFilter()
App.fontSmallNumbers.draw(batch, "B:$bits", x+3f, y+1f) App.fontSmallNumbers.draw(batch, "B:$bits", x+3f, y+1f)
} }
override fun reset() {
}
override val debugViewHeight = 16 override val debugViewHeight = 16
} }

View File

@@ -2,7 +2,6 @@ package net.torvald.terrarum.audio.dsp
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
object Buffer : TerrarumAudioFilter() { object Buffer : TerrarumAudioFilter() {
@@ -16,7 +15,10 @@ object Buffer : TerrarumAudioFilter() {
override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) {
batch.color = FILTER_NAME_ACTIVE batch.color = FILTER_NAME_ACTIVE
App.fontSmallNumbers.draw(batch, "Bs:${AUDIO_BUFFER_SIZE}", x+3f, y+1f) App.fontSmallNumbers.draw(batch, "Bs:${App.audioBufferSize}", x+3f, y+1f)
}
override fun reset() {
} }
override val debugViewHeight = 16 override val debugViewHeight = 16

View File

@@ -5,8 +5,6 @@ import com.jme3.math.FastMath
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.App.setDebugTime import net.torvald.terrarum.App.setDebugTime
import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.*
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
import net.torvald.terrarum.ui.BasicDebugInfoWindow
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2 import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2_RED import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2_RED
@@ -25,14 +23,13 @@ import kotlin.math.roundToInt
* @param gain output gain. Fullscale (0.0 - 1.0) * @param gain output gain. Fullscale (0.0 - 1.0)
*/ */
class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter() { class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter() {
private val gain: Float = gain / (1f + crossfeed) private val gain: Float = gain / (1f + crossfeed)
val fftLen: Int val fftLen: Int
private val convFFT: Array<ComplexArray> private val convFFT: Array<ComplexArray>
private val sumbuf: Array<ComplexArray> private val sumbuf: Array<ComplexArray>
private val BLOCKSIZE = TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE
var processingSpeed = 1f; private set var processingSpeed = 1f; private set
init { init {
@@ -71,12 +68,18 @@ class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): Terrarum
} }
} }
private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L) private var realtime = (App.audioBufferSize / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
private val fftIn = ComplexArray(FloatArray(fftLen * 2)) private val fftIn = ComplexArray(FloatArray(fftLen * 2))
private val fftMult = ComplexArray(FloatArray(fftLen * 2)) private val fftMult = ComplexArray(FloatArray(fftLen * 2))
private val fftOutL = FloatArray(fftLen) private val fftOutL = FloatArray(fftLen)
private val fftOutR = FloatArray(fftLen) private val fftOutR = FloatArray(fftLen)
override fun reset() {
realtime = (App.audioBufferSize / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
processingSpeed = 1f
sumbuf.forEach { it.reim.fill(0f) }
}
private fun convolve(x: ComplexArray, h: ComplexArray, output: FloatArray) { private fun convolve(x: ComplexArray, h: ComplexArray, output: FloatArray) {
FFT.fftInto(x, fftIn) FFT.fftInto(x, fftIn)
fftIn.mult(h, fftMult) fftIn.mult(h, fftMult)
@@ -96,9 +99,9 @@ class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): Terrarum
convolve(sumbuf[0], convFFT[0], fftOutL) convolve(sumbuf[0], convFFT[0], fftOutL)
convolve(sumbuf[1], convFFT[1], fftOutR) convolve(sumbuf[1], convFFT[1], fftOutR)
for (i in 0 until BLOCKSIZE) { for (i in 0 until App.audioBufferSize) {
outbuf[0][i] = fftOutL[fftLen - BLOCKSIZE + i] outbuf[0][i] = fftOutL[fftLen - App.audioBufferSize + i]
outbuf[1][i] = fftOutR[fftLen - BLOCKSIZE + i] outbuf[1][i] = fftOutR[fftLen - App.audioBufferSize + i]
} }
@@ -144,7 +147,7 @@ class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): Terrarum
Toolkit.fillArea(batch, x.toFloat(), y+14f, STRIP_W * perc, 2f) Toolkit.fillArea(batch, x.toFloat(), y+14f, STRIP_W * perc, 2f)
// filter length bar // filter length bar
val g = FastMath.intLog2(AUDIO_BUFFER_SIZE) val g = FastMath.intLog2(App.audioBufferSize)
val perc2 = (FastMath.intLog2(fftLen).minus(g).toFloat() / (16f - g)).coerceIn(0f, 1f) val perc2 = (FastMath.intLog2(fftLen).minus(g).toFloat() / (16f - g)).coerceIn(0f, 1f)
batch.color = COL_METER_GRAD2 batch.color = COL_METER_GRAD2
Toolkit.fillArea(batch, x.toFloat(), y + 16f, STRIP_W * perc2, 14f) Toolkit.fillArea(batch, x.toFloat(), y + 16f, STRIP_W * perc2, 14f)

View File

@@ -2,14 +2,13 @@ package net.torvald.terrarum.audio.dsp
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.audio.fullscaleToDecibels import net.torvald.terrarum.audio.fullscaleToDecibels
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
import kotlin.math.roundToInt import kotlin.math.roundToInt
class Gain(var gain: Float): TerrarumAudioFilter() { class Gain(var gain: Float): TerrarumAudioFilter() {
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) { override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
outbuf[0][i] = inbuf[0][i] * gain outbuf[0][i] = inbuf[0][i] * gain
outbuf[1][i] = inbuf[1][i] * gain outbuf[1][i] = inbuf[1][i] * gain
} }
@@ -20,5 +19,9 @@ class Gain(var gain: Float): TerrarumAudioFilter() {
App.fontSmallNumbers.draw(batch, "G:${fullscaleToDecibels(gain.toDouble()).times(100).roundToInt().div(100f)}", x+3f, y+1f) App.fontSmallNumbers.draw(batch, "G:${fullscaleToDecibels(gain.toDouble()).times(100).roundToInt().div(100f)}", x+3f, y+1f)
} }
override fun reset() {
}
override val debugViewHeight = 16 override val debugViewHeight = 16
} }

View File

@@ -68,4 +68,8 @@ class Highpass(cutoff0: Float): TerrarumAudioFilter() {
override val debugViewHeight = 16 override val debugViewHeight = 16
override fun reset() {
in0.fill(0f)
out0.fill(0f)
}
} }

View File

@@ -67,4 +67,9 @@ class Lowpass(cutoff0: Float): TerrarumAudioFilter() {
} }
override val debugViewHeight = 16 override val debugViewHeight = 16
override fun reset() {
in0.fill(0f)
out0.fill(0f)
}
} }

View File

@@ -13,4 +13,7 @@ object NullFilter : TerrarumAudioFilter() {
} }
override val debugViewHeight = 0 override val debugViewHeight = 0
override fun reset() {
}
} }

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.audio.dsp
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.terrarum.App
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -31,7 +32,7 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass:
val alphaHi = RCHi / (RCHi + dt) val alphaHi = RCHi / (RCHi + dt)
for (ch in outbuf.indices) { for (ch in outbuf.indices) {
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val inn = inbuf[ch][i] val inn = inbuf[ch][i]
// reverb // reverb
@@ -52,4 +53,8 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass:
} }
override val debugViewHeight = 0 override val debugViewHeight = 0
override fun reset() {
buf.forEach { it.fill(0f) }
}
} }

View File

@@ -56,4 +56,7 @@ object SoftClp : TerrarumAudioFilter() {
} }
override val debugViewHeight = 0 override val debugViewHeight = 0
override fun reset() {
}
} }

View File

@@ -3,8 +3,8 @@ package net.torvald.terrarum.audio.dsp
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 com.jme3.math.FastMath
import net.torvald.terrarum.App
import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.*
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED
import net.torvald.terrarum.ui.BasicDebugInfoWindow import net.torvald.terrarum.ui.BasicDebugInfoWindow
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W
@@ -91,15 +91,18 @@ class Spectro(val gain: Float = 1f) : TerrarumAudioFilter() {
} }
override val debugViewHeight = STRIP_W override val debugViewHeight = STRIP_W
override fun reset() {
}
} }
class Vecto(val gain: Float = 1f) : TerrarumAudioFilter() { class Vecto(val gain: Float = 1f) : TerrarumAudioFilter() {
val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) { var backbufL = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE) FloatArray(App.audioBufferSize)
} }
val backbufR = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) { var backbufR = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE) FloatArray(App.audioBufferSize)
} }
private val sqrt2p = 0.7071067811865475 private val sqrt2p = 0.7071067811865475
@@ -110,11 +113,11 @@ class Vecto(val gain: Float = 1f) : TerrarumAudioFilter() {
backbufL[i] = backbufL[i - 1] backbufL[i] = backbufL[i - 1]
backbufR[i] = backbufR[i - 1] backbufR[i] = backbufR[i - 1]
} }
backbufL[0] = FloatArray(TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) backbufL[0] = FloatArray(App.audioBufferSize)
backbufR[0] = FloatArray(TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) backbufR[0] = FloatArray(App.audioBufferSize)
// plot dots // plot dots
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val y0 = +inbuf[0][i] * gain val y0 = +inbuf[0][i] * gain
val x0 = -inbuf[1][i] * gain// rotate the domain by -90 deg val x0 = -inbuf[1][i] * gain// rotate the domain by -90 deg
@@ -154,4 +157,13 @@ class Vecto(val gain: Float = 1f) : TerrarumAudioFilter() {
} }
override val debugViewHeight = STRIP_W override val debugViewHeight = STRIP_W
override fun reset() {
backbufL = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
FloatArray(App.audioBufferSize)
}
backbufR = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
FloatArray(App.audioBufferSize)
}
}
} }

View File

@@ -13,6 +13,7 @@ abstract class TerrarumAudioFilter {
} }
else thru(inbuf, outbuf) else thru(inbuf, outbuf)
} }
abstract fun reset()
abstract fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) abstract fun drawDebugView(batch: SpriteBatch, x: Int, y: Int)
abstract val debugViewHeight: Int abstract val debugViewHeight: Int
} }

View File

@@ -1,11 +1,11 @@
package net.torvald.terrarum.audio.dsp package net.torvald.terrarum.audio.dsp
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.App
object XYtoMS: TerrarumAudioFilter() { object XYtoMS: TerrarumAudioFilter() {
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) { override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val X = inbuf[0][i] val X = inbuf[0][i]
val Y = inbuf[1][i] val Y = inbuf[1][i]
val M = (X + Y) / 2f val M = (X + Y) / 2f
@@ -19,11 +19,14 @@ object XYtoMS: TerrarumAudioFilter() {
} }
override val debugViewHeight = 0 override val debugViewHeight = 0
override fun reset() {
}
} }
object MStoXY: TerrarumAudioFilter() { object MStoXY: TerrarumAudioFilter() {
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) { override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until App.audioBufferSize) {
val M = inbuf[0][i] val M = inbuf[0][i]
val S = inbuf[1][i] val S = inbuf[1][i]
val X = M + S val X = M + S
@@ -37,4 +40,7 @@ object MStoXY: TerrarumAudioFilter() {
} }
override val debugViewHeight = 0 override val debugViewHeight = 0
override fun reset() {
}
} }

View File

@@ -1,13 +1,9 @@
package net.torvald.terrarum.gameactors package net.torvald.terrarum.gameactors
import com.badlogic.gdx.audio.Music
import com.badlogic.gdx.audio.Sound
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App
import net.torvald.terrarum.INGAME import net.torvald.terrarum.INGAME
import net.torvald.terrarum.ReferencingRanges
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.audio.TrackVolume import net.torvald.terrarum.audio.TrackVolume
import net.torvald.terrarum.modulebasegame.MusicContainer import net.torvald.terrarum.modulebasegame.MusicContainer
@@ -113,9 +109,9 @@ abstract class Actor : Comparable<Actor>, Runnable {
// if there is no existing track, try to get one // if there is no existing track, try to get one
if (track == null) { if (track == null) {
track = if (this == Terrarum.ingame?.actorNowPlaying) track = if (this == Terrarum.ingame?.actorNowPlaying)
AudioMixer.getFreeTrackNoMatterWhat() App.audioMixer.getFreeTrackNoMatterWhat()
else else
AudioMixer.getFreeTrack() App.audioMixer.getFreeTrack()
// if the request was successful, put it into the hashmap // if the request was successful, put it into the hashmap
if (track != null) { if (track != null) {
musicTracks[music] = track musicTracks[music] = track

View File

@@ -7,9 +7,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.dsp.Lowpass
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockPropUtil import net.torvald.terrarum.blockproperties.BlockPropUtil
import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameactors.*
@@ -300,7 +297,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
override fun show() { override fun show() {
Gdx.input.inputProcessor = BuildingMakerController(this) Gdx.input.inputProcessor = BuildingMakerController(this)
AudioMixer.reset() App.audioMixer.reset()
super.show() super.show()
} }

View File

@@ -8,14 +8,10 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShapeRenderer import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.* import net.torvald.terrarum.App.*
import net.torvald.terrarum.Terrarum.audioCodex
import net.torvald.terrarum.Terrarum.getPlayerSaveFiledesc import net.torvald.terrarum.Terrarum.getPlayerSaveFiledesc
import net.torvald.terrarum.Terrarum.getWorldSaveFiledesc import net.torvald.terrarum.Terrarum.getWorldSaveFiledesc
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE 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
import net.torvald.terrarum.audio.dsp.Lowpass
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF
import net.torvald.terrarum.blockproperties.BlockPropUtil import net.torvald.terrarum.blockproperties.BlockPropUtil
import net.torvald.terrarum.blockstats.MinimapComposer import net.torvald.terrarum.blockstats.MinimapComposer
import net.torvald.terrarum.blockstats.TileSurvey import net.torvald.terrarum.blockstats.TileSurvey
@@ -298,7 +294,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
IngameRenderer.setRenderedWorld(world) IngameRenderer.setRenderedWorld(world)
blockMarkingActor.isVisible = true blockMarkingActor.isVisible = true
AudioMixer.reset() App.audioMixer.reset()
super.show() // this function sets gameInitialised = true super.show() // this function sets gameInitialised = true
@@ -893,13 +889,13 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
val ratio = (TileSurvey.getRatio("basegame.Ingame.audioReflection") ?: 0.0) val ratio = (TileSurvey.getRatio("basegame.Ingame.audioReflection") ?: 0.0)
if (ratio >= 0.0) { if (ratio >= 0.0) {
val ratio1 = ratio.coerceIn(0.0, 1.0) val ratio1 = ratio.coerceIn(0.0, 1.0)
AudioMixer.convolveBusCave.volume = ratio1 App.audioMixer.convolveBusCave.volume = ratio1
AudioMixer.convolveBusOpen.volume = 1.0 - ratio1 App.audioMixer.convolveBusOpen.volume = 1.0 - ratio1
} }
else { else {
val ratio1 = (ratio / MaterialCodex["AIIR"].sondrefl).absoluteValue.coerceIn(0.0, 1.0) val ratio1 = (ratio / MaterialCodex["AIIR"].sondrefl).absoluteValue.coerceIn(0.0, 1.0)
AudioMixer.convolveBusOpen.volume = (1.0 - ratio1).pow(0.75) App.audioMixer.convolveBusOpen.volume = (1.0 - ratio1).pow(0.75)
AudioMixer.convolveBusCave.volume = 0.0 App.audioMixer.convolveBusCave.volume = 0.0
} }

View File

@@ -16,7 +16,6 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.audio.AudioMixer import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
import net.torvald.terrarum.gameworld.fmod
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import javax.sound.sampled.AudioSystem import javax.sound.sampled.AudioSystem
@@ -203,8 +202,8 @@ class TerrarumMusicGovernor : MusicGovernor() {
*/ */
fun queueDirectory(musicDir: String, shuffled: Boolean, diskJockeyingMode: String, fileToName: ((String) -> String)? = null) { fun queueDirectory(musicDir: String, shuffled: Boolean, diskJockeyingMode: String, fileToName: ((String) -> String)? = null) {
if (musicState != STATE_INIT && musicState != STATE_INTERMISSION) { if (musicState != STATE_INIT && musicState != STATE_INTERMISSION) {
AudioMixer.requestFadeOut(AudioMixer.fadeBus, AudioMixer.DEFAULT_FADEOUT_LEN) // explicit call for fade-out when the game instance quits App.audioMixer.requestFadeOut(App.audioMixer.fadeBus, AudioMixer.DEFAULT_FADEOUT_LEN) // explicit call for fade-out when the game instance quits
stopMusic(AudioMixer.musicTrack.currentTrack) stopMusic(App.audioMixer.musicTrack.currentTrack)
} }
songs.forEach { it.gdxMusic.tryDispose() } songs.forEach { it.gdxMusic.tryDispose() }
@@ -337,7 +336,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
} }
fun stopMusic(callStopMusicHook: Boolean = true, pauseLen: Float = Float.POSITIVE_INFINITY) { fun stopMusic(callStopMusicHook: Boolean = true, pauseLen: Float = Float.POSITIVE_INFINITY) {
stopMusic(AudioMixer.musicTrack.currentTrack, callStopMusicHook) stopMusic(App.audioMixer.musicTrack.currentTrack, callStopMusicHook)
intermissionLength = pauseLen intermissionLength = pauseLen
// printdbg(this, "StopMusic Intermission2: $intermissionLength seconds") // printdbg(this, "StopMusic Intermission2: $intermissionLength seconds")
} }
@@ -347,7 +346,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
} }
private fun startMusic(song: MusicContainer) { private fun startMusic(song: MusicContainer) {
AudioMixer.startMusic(song) App.audioMixer.startMusic(song)
printdbg(this, "startMusic Now playing: ${song.name}") printdbg(this, "startMusic Now playing: ${song.name}")
// INGAME.sendNotification("Now Playing $EMDASH ${song.name}") // INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
if (musicStartHooks.isNotEmpty()) musicStartHooks.forEach { it(song) } if (musicStartHooks.isNotEmpty()) musicStartHooks.forEach { it(song) }
@@ -386,7 +385,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
} }
private fun startAmbient(song: MusicContainer) { private fun startAmbient(song: MusicContainer) {
AudioMixer.startAmb(song) App.audioMixer.startAmb(song)
printdbg(this, "startAmbient Now playing: $song") printdbg(this, "startAmbient Now playing: $song")
// INGAME.sendNotification("Now Playing $EMDASH ${song.name}") // INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
ambState = STATE_PLAYING ambState = STATE_PLAYING
@@ -438,8 +437,8 @@ class TerrarumMusicGovernor : MusicGovernor() {
} }
override fun dispose() { override fun dispose() {
AudioMixer.requestFadeOut(AudioMixer.fadeBus, AudioMixer.DEFAULT_FADEOUT_LEN) // explicit call for fade-out when the game instance quits App.audioMixer.requestFadeOut(App.audioMixer.fadeBus, AudioMixer.DEFAULT_FADEOUT_LEN) // explicit call for fade-out when the game instance quits
stopMusic(AudioMixer.musicTrack.currentTrack) stopMusic(App.audioMixer.musicTrack.currentTrack)
stopAmbient() stopAmbient()
} }
} }

View File

@@ -17,9 +17,6 @@ import net.torvald.terrarum.App.printdbgerr
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE 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.TerrarumAppConfiguration.TILE_SIZEF import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.dsp.Lowpass
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack
import net.torvald.terrarum.clut.Skybox import net.torvald.terrarum.clut.Skybox
import net.torvald.terrarum.console.CommandDict import net.torvald.terrarum.console.CommandDict
import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameactors.*
@@ -269,7 +266,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
App.bogoflops = maxOf(App.bogoflops, bogoflops) App.bogoflops = maxOf(App.bogoflops, bogoflops)
AudioMixer.reset() App.audioMixer.reset()
} }

View File

@@ -9,8 +9,7 @@ import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.audio.AudioMixer import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN
import net.torvald.terrarum.audio.AudioMixer.DEFAULT_FADEOUT_LEN
import net.torvald.terrarum.audio.dsp.Convolv import net.torvald.terrarum.audio.dsp.Convolv
import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
@@ -110,7 +109,7 @@ class FixtureJukebox : Electric {
discCurrentlyPlaying = index discCurrentlyPlaying = index
AudioMixer.requestFadeOut(AudioMixer.musicTrack, DEFAULT_FADEOUT_LEN / 2f) { App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, DEFAULT_FADEOUT_LEN / 2f) {
startAudio(musicNowPlaying!!) { startAudio(musicNowPlaying!!) {
it.filters[2] = Convolv( it.filters[2] = Convolv(
ModMgr.getFile( ModMgr.getFile(

View File

@@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.jme3.math.FastMath import com.jme3.math.FastMath
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.* import net.torvald.terrarum.App.*
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.audio.decibelsToFullscale import net.torvald.terrarum.audio.decibelsToFullscale
import net.torvald.terrarum.gameitems.GameItem import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
@@ -388,8 +387,8 @@ class UIInventoryFull(
INGAME.pause() INGAME.pause()
INGAME.setTooltipMessage(null) INGAME.setTooltipMessage(null)
AudioMixer.requestLowpassIn(0.25) App.audioMixer.requestLowpassIn(0.25)
AudioMixer.requestFadeOut(AudioMixer.fadeBus, 0.25, decibelsToFullscale(-3.0)) App.audioMixer.requestFadeOut(App.audioMixer.fadeBus, 0.25, decibelsToFullscale(-3.0))
} }
override fun doClosing(delta: Float) { override fun doClosing(delta: Float) {
@@ -398,8 +397,8 @@ class UIInventoryFull(
INGAME.resume() INGAME.resume()
INGAME.setTooltipMessage(null) INGAME.setTooltipMessage(null)
AudioMixer.requestLowpassOut(0.25) App.audioMixer.requestLowpassOut(0.25)
AudioMixer.requestFadeIn(AudioMixer.fadeBus, 0.25, 1.0) App.audioMixer.requestFadeIn(App.audioMixer.fadeBus, 0.25, 1.0)
} }
override fun endOpening(delta: Float) { override fun endOpening(delta: Float) {

View File

@@ -1,8 +1,9 @@
package net.torvald.terrarum.modulebasegame.ui package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.audio.AudioMixer
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
@@ -28,10 +29,10 @@ class UISoundControlPanel(remoCon: UIRemoCon?) : UICanvas() {
arrayOf("", { "" }, "pp"), arrayOf("", { "" }, "pp"),
arrayOf("guivolume", { Lang["MENU_LABEL_INTERFACE"] }, "sliderd,0,1"), arrayOf("guivolume", { Lang["MENU_LABEL_INTERFACE"] }, "sliderd,0,1"),
arrayOf("", { "" }, "pp"), arrayOf("", { "" }, "pp"),
arrayOf("audio_speaker_setup", { Lang["MENU_OPTIONS_SPEAKER_SETUP"] }, "textsel,headphone=MENU_OPTIONS_SPEAKER_HEADPHONE,stereo=MENU_OPTIONS_SPEAKER_STEREO"),
arrayOf("", { Lang["MENU_LABEL_AUDIO_ENGINE"] }, "h1"), arrayOf("", { Lang["MENU_LABEL_AUDIO_ENGINE"] }, "h1"),
arrayOf("audio_buffer_size", { Lang["MENU_OPTIONS_AUDIO_BUFFER_SIZE"] }, "spinnersel,128,256,512,1024,2048"), arrayOf("audio_speaker_setup", { Lang["MENU_OPTIONS_SPEAKER_SETUP"] }, "textsel,headphone=MENU_OPTIONS_SPEAKER_HEADPHONE,stereo=MENU_OPTIONS_SPEAKER_STEREO"),
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"), arrayOf("audio_buffer_size", { Lang["MENU_OPTIONS_App.audioMixerBufferSize"] }, "spinnersel,128,256,512,1024,2048"),
// arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
arrayOf("", { "${Lang["MENU_LABEL_AUDIO_BUFFER_INSTRUCTION"]}" }, "p"), arrayOf("", { "${Lang["MENU_LABEL_AUDIO_BUFFER_INSTRUCTION"]}" }, "p"),
)) ))
@@ -39,8 +40,18 @@ class UISoundControlPanel(remoCon: UIRemoCon?) : UICanvas() {
override var height = ControlPanelCommon.getMenuHeight("basegame.soundcontrolpanel") override var height = ControlPanelCommon.getMenuHeight("basegame.soundcontrolpanel")
private var oldBufferSize = App.getConfigInt("audio_buffer_size")
override fun updateUI(delta: Float) { override fun updateUI(delta: Float) {
uiItems.forEach { it.update(delta) } uiItems.forEach { it.update(delta) }
App.getConfigInt("audio_buffer_size").let {
if (it != oldBufferSize) {
oldBufferSize = it
App.renewAudioProcessor(it)
}
}
} }
override fun renderUI(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) { override fun renderUI(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {

View File

@@ -13,8 +13,6 @@ import net.torvald.terrarum.Terrarum.mouseTileX
import net.torvald.terrarum.Terrarum.mouseTileY import net.torvald.terrarum.Terrarum.mouseTileY
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.*
import net.torvald.terrarum.audio.AudioMixer.dynamicSourceCount
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
import net.torvald.terrarum.audio.dsp.* import net.torvald.terrarum.audio.dsp.*
import net.torvald.terrarum.controller.TerrarumController import net.torvald.terrarum.controller.TerrarumController
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
@@ -136,7 +134,7 @@ class BasicDebugInfoWindow : UICanvas() {
showWeatherInfo = showWeatherInfo xor (Gdx.input.isKeyJustPressed(KEY_WEATHERS) && Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)) showWeatherInfo = showWeatherInfo xor (Gdx.input.isKeyJustPressed(KEY_WEATHERS) && Gdx.input.isKeyPressed(Keys.CONTROL_LEFT))
showAudioMixer = showAudioMixer xor (Gdx.input.isKeyJustPressed(KEY_AUDIOMIXER) && Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)) showAudioMixer = showAudioMixer xor (Gdx.input.isKeyJustPressed(KEY_AUDIOMIXER) && Gdx.input.isKeyPressed(Keys.CONTROL_LEFT))
AudioMixer.masterTrack.filters[2].bypass = !showAudioMixer App.audioMixer.masterTrack.filters[2].bypass = !showAudioMixer
drawMain(batch) drawMain(batch)
if (showTimers) drawTimers(batch) if (showTimers) drawTimers(batch)
@@ -438,10 +436,10 @@ class BasicDebugInfoWindow : UICanvas() {
private fun drawAudioMixer(batch: SpriteBatch) { private fun drawAudioMixer(batch: SpriteBatch) {
val x = App.scr.width - 186 - (AudioMixer.tracks.size + 1) * (STRIP_W + stripGap) val x = App.scr.width - 186 - (App.audioMixer.tracks.size + 1) * (STRIP_W + stripGap)
val y = App.scr.height - 38 - stripH val y = App.scr.height - 38 - stripH
val strips = AudioMixer.tracks + AudioMixer.masterTrack val strips = App.audioMixer.tracks + App.audioMixer.masterTrack
// batch.color = COL_MIXER_BACK // batch.color = COL_MIXER_BACK
// Toolkit.fillArea(batch, x - stripGap, y - stripGap, strips.size * (stripW + stripGap) + stripGap, stripH + 2*stripGap) // Toolkit.fillArea(batch, x - stripGap, y - stripGap, strips.size * (stripW + stripGap) + stripGap, stripH + 2*stripGap)
@@ -457,7 +455,7 @@ class BasicDebugInfoWindow : UICanvas() {
} }
val dss = AudioMixer.dynamicTracks val dss = App.audioMixer.dynamicTracks
dss.forEachIndexed { index, track -> dss.forEachIndexed { index, track ->
val px = x - (miniW + 5) * (1 + (index / 13)) val px = x - (miniW + 5) * (1 + (index / 13))
val py = y + (miniH + stripGap) * (index % 13) val py = y + (miniH + stripGap) * (index % 13)
@@ -588,7 +586,7 @@ class BasicDebugInfoWindow : UICanvas() {
App.fontSmallNumbers.draw(batch, s, x + 3f, faderY - (i + 1) * 16f + 1f) App.fontSmallNumbers.draw(batch, s, x + 3f, faderY - (i + 1) * 16f + 1f)
} }
} }
else if (track != AudioMixer.sfxSumBus) { else if (track != App.audioMixer.sfxSumBus) {
track.sidechainInputs.reversed().forEachIndexed { i, (side, mix) -> track.sidechainInputs.reversed().forEachIndexed { i, (side, mix) ->
val mixDb = fullscaleToDecibels(mix) val mixDb = fullscaleToDecibels(mix)
val perc = ((mixDb + 24.0).coerceAtLeast(0.0) / 24.0).toFloat() val perc = ((mixDb + 24.0).coerceAtLeast(0.0) / 24.0).toFloat()
@@ -620,7 +618,7 @@ class BasicDebugInfoWindow : UICanvas() {
// label // label
batch.color = FILTER_NAME_ACTIVE batch.color = FILTER_NAME_ACTIVE
App.fontSmallNumbers.draw(batch, "\u00C0", x.toFloat(), faderY - (i + 1) * 16f + 1f) App.fontSmallNumbers.draw(batch, "\u00C0", x.toFloat(), faderY - (i + 1) * 16f + 1f)
App.fontSmallNumbers.draw(batch, "DS($dynamicSourceCount)", x + 10f, faderY - (i + 1) * 16f + 1f) App.fontSmallNumbers.draw(batch, "DS(${net.torvald.terrarum.App.audioMixer.dynamicSourceCount})", x + 10f, faderY - (i + 1) * 16f + 1f)
} }
// fader // fader
@@ -1001,7 +999,7 @@ class BasicDebugInfoWindow : UICanvas() {
} }
override fun endClosing(delta: Float) { override fun endClosing(delta: Float) {
AudioMixer.masterTrack.filters[2].bypass = true App.audioMixer.masterTrack.filters[2].bypass = true
} }
override fun dispose() { override fun dispose() {