mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 16:46:07 +09:00
dynamic track first commit
This commit is contained in:
@@ -951,6 +951,23 @@ fun distBetweenActors(a: ActorWithBody, b: ActorWithBody): Double {
|
|||||||
val dist = min(min(bpos.distanceSquared(apos1), bpos.distanceSquared(apos2)), bpos.distanceSquared(apos3))
|
val dist = min(min(bpos.distanceSquared(apos1), bpos.distanceSquared(apos2)), bpos.distanceSquared(apos3))
|
||||||
return dist.sqrt()
|
return dist.sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return positive if the otherActor is on the right side of the player, negative if on the left
|
||||||
|
*/
|
||||||
|
fun relativeXposition(thisActor: ActorWithBody, otherActor: ActorWithBody): Double {
|
||||||
|
val ww = INGAME.world.width * TILE_SIZED
|
||||||
|
val thisPos = thisActor.centrePosVector
|
||||||
|
val pos1 = otherActor.centrePosVector
|
||||||
|
val pos2 = Vector2(pos1.x + ww, pos1.y)
|
||||||
|
val pos3 = Vector2(pos1.x - ww, pos1.y)
|
||||||
|
val posToUse = listOf(
|
||||||
|
pos1 to thisPos.distanceSquared(pos1),
|
||||||
|
pos2 to thisPos.distanceSquared(pos2),
|
||||||
|
pos3 to thisPos.distanceSquared(pos3),
|
||||||
|
).sortedBy { it.second }.first().first
|
||||||
|
return posToUse.x - thisPos.x
|
||||||
|
}
|
||||||
fun distBetween(a: ActorWithBody, bpos: Vector2): Double {
|
fun distBetween(a: ActorWithBody, bpos: Vector2): Double {
|
||||||
val ww = INGAME.world.width * TILE_SIZED
|
val ww = INGAME.world.width * TILE_SIZED
|
||||||
val apos1 = a.centrePosVector
|
val apos1 = a.centrePosVector
|
||||||
|
|||||||
@@ -95,6 +95,26 @@ object AudioMixer: Disposable {
|
|||||||
|
|
||||||
var processing = true
|
var processing = true
|
||||||
|
|
||||||
|
var actorNowPlaying = Terrarum.ingame?.actorNowPlaying; private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return oldest dynamic track, even if the track is currently playing
|
||||||
|
*/
|
||||||
|
fun getFreeTrackNoMatterWhat(): TerrarumAudioMixerTrack {
|
||||||
|
return dynamicTracks.minBy { it.playStartedTime }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return oldest dynamic track that is not playing
|
||||||
|
*/
|
||||||
|
fun getFreeTrack(): TerrarumAudioMixerTrack? {
|
||||||
|
val oldestTrack = dynamicTracks.minBy { it.playStartedTime }
|
||||||
|
return if (oldestTrack.isPlaying)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
oldestTrack
|
||||||
|
}
|
||||||
|
|
||||||
private val processingExecutor = ThreadExecutor()
|
private val processingExecutor = ThreadExecutor()
|
||||||
// private lateinit var processingSubthreads: List<Thread>
|
// private lateinit var processingSubthreads: List<Thread>
|
||||||
val processingThread = Thread {
|
val processingThread = Thread {
|
||||||
@@ -117,6 +137,8 @@ object AudioMixer: Disposable {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
while (processing) {
|
while (processing) {
|
||||||
|
actorNowPlaying = Terrarum.ingame?.actorNowPlaying
|
||||||
|
|
||||||
for (tracks in parallelProcessingSchedule) {
|
for (tracks in parallelProcessingSchedule) {
|
||||||
if (!processing) break
|
if (!processing) break
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package net.torvald.terrarum.audio
|
|||||||
|
|
||||||
import com.badlogic.gdx.utils.Queue
|
import com.badlogic.gdx.utils.Queue
|
||||||
import net.torvald.reflection.forceInvoke
|
import net.torvald.reflection.forceInvoke
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.audio.dsp.BinoPan
|
||||||
import net.torvald.terrarum.audio.dsp.NullFilter
|
import net.torvald.terrarum.audio.dsp.NullFilter
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
|
import net.torvald.terrarum.relativeXposition
|
||||||
import net.torvald.terrarum.sqr
|
import net.torvald.terrarum.sqr
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.*
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-11-17.
|
* Created by minjaesong on 2023-11-17.
|
||||||
@@ -35,6 +38,8 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
|
|
||||||
private var breakBomb = false
|
private var breakBomb = false
|
||||||
|
|
||||||
|
private val distFalloff = 2048.0
|
||||||
|
|
||||||
private fun printdbg(msg: Any) {
|
private fun printdbg(msg: Any) {
|
||||||
if (true) println("[AudioAdapter ${track.name}] $msg")
|
if (true) println("[AudioAdapter ${track.name}] $msg")
|
||||||
}
|
}
|
||||||
@@ -67,15 +72,30 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
|||||||
if (breakBomb) break*/ // uncomment to multithread
|
if (breakBomb) break*/ // uncomment to multithread
|
||||||
// Your code here
|
// Your code here
|
||||||
|
|
||||||
|
|
||||||
|
// update panning and shits
|
||||||
|
if (track.trackType == TrackType.DYNAMIC_SOURCE && track.isPlaying) {
|
||||||
|
if (AudioMixer.actorNowPlaying != null) {
|
||||||
|
if (track.trackingTarget == null || track.trackingTarget == AudioMixer.actorNowPlaying) {
|
||||||
|
track.volume = track.maxVolume
|
||||||
|
(track.filters[0] as BinoPan).pan = 0f
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val relativeXpos = relativeXposition(AudioMixer.actorNowPlaying!!, track.trackingTarget!!)
|
||||||
|
track.volume = track.maxVolume * (1.0 - relativeXpos.absoluteValue.pow(0.5) / distFalloff)
|
||||||
|
(track.filters[0] as BinoPan).pan = ((2*asin(relativeXpos / distFalloff)) / Math.PI).toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// fetch deviceBufferSize amount of sample from the disk
|
// fetch deviceBufferSize amount of sample from the disk
|
||||||
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying) {
|
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying) {
|
||||||
streamBuf.fetchBytes {
|
streamBuf.fetchBytes {
|
||||||
val bytesRead = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(it))
|
val bytesRead = track.currentTrack?.gdxMusic?.forceInvoke<Int>("read", arrayOf(it))
|
||||||
if (bytesRead == null || bytesRead <= 0) { // some class (namely Mp3) may return 0 instead of negative value
|
if (bytesRead == null || bytesRead <= 0) { // some class (namely Mp3) may return 0 instead of negative value
|
||||||
// printdbg("Finished reading audio stream")
|
// printdbg("Finished reading audio stream")
|
||||||
track.currentTrack?.gdxMusic?.forceInvoke<Int>("reset", arrayOf())
|
track.stop()
|
||||||
track.streamPlaying = false
|
|
||||||
track.fireSongFinishHook()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
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
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.getHashStr
|
import net.torvald.terrarum.getHashStr
|
||||||
import net.torvald.terrarum.hashStrMap
|
import net.torvald.terrarum.hashStrMap
|
||||||
import net.torvald.terrarum.modulebasegame.MusicContainer
|
import net.torvald.terrarum.modulebasegame.MusicContainer
|
||||||
@@ -36,6 +39,8 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, privat
|
|||||||
var currentTrack: MusicContainer? = null
|
var currentTrack: MusicContainer? = null
|
||||||
var nextTrack: MusicContainer? = null
|
var nextTrack: MusicContainer? = null
|
||||||
|
|
||||||
|
var currentSound: Sound? = null // DYNAMIC_SOURCE only
|
||||||
|
|
||||||
var volume: TrackVolume = 1.0
|
var volume: TrackVolume = 1.0
|
||||||
get() = field
|
get() = field
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -46,14 +51,16 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, privat
|
|||||||
val maxVolume: Double
|
val maxVolume: Double
|
||||||
get() = maxVolumeFun()
|
get() = maxVolumeFun()
|
||||||
|
|
||||||
var pan = 0.0
|
|
||||||
|
|
||||||
var dBfs: Double
|
var dBfs: Double
|
||||||
get() = fullscaleToDecibels(volume)
|
get() = fullscaleToDecibels(volume)
|
||||||
set(value) { volume = decibelsToFullscale(value) }
|
set(value) { volume = decibelsToFullscale(value) }
|
||||||
|
|
||||||
val filters: Array<TerrarumAudioFilter> = Array(4) { NullFilter }
|
val filters: Array<TerrarumAudioFilter> = Array(4) { NullFilter }
|
||||||
|
|
||||||
|
var trackingTarget: ActorWithBody? = null
|
||||||
|
|
||||||
|
var playStartedTime = 0L; private set
|
||||||
|
|
||||||
inline fun <reified T> getFilter() = filters.filterIsInstance<T>().first()!!
|
inline fun <reified T> getFilter() = filters.filterIsInstance<T>().first()!!
|
||||||
|
|
||||||
internal val sidechainInputs = ArrayList<Pair<TerrarumAudioMixerTrack, TrackVolume>?>()
|
internal val sidechainInputs = ArrayList<Pair<TerrarumAudioMixerTrack, TrackVolume>?>()
|
||||||
@@ -110,6 +117,7 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, privat
|
|||||||
|
|
||||||
internal var streamPlaying = false
|
internal var streamPlaying = false
|
||||||
fun play() {
|
fun play() {
|
||||||
|
playStartedTime = System.nanoTime()
|
||||||
streamPlaying = true
|
streamPlaying = true
|
||||||
// currentTrack?.gdxMusic?.play()
|
// currentTrack?.gdxMusic?.play()
|
||||||
}
|
}
|
||||||
@@ -129,6 +137,14 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, privat
|
|||||||
|
|
||||||
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
|
override fun equals(other: Any?) = this.hash == (other as TerrarumAudioMixerTrack).hash
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
currentTrack?.gdxMusic?.forceInvoke<Int>("reset", arrayOf())
|
||||||
|
streamPlaying = false
|
||||||
|
playStartedTime = 0L
|
||||||
|
fireSongFinishHook()
|
||||||
|
// fireSoundFinishHook()
|
||||||
|
}
|
||||||
|
|
||||||
fun fireSongFinishHook() {
|
fun fireSongFinishHook() {
|
||||||
currentTrack?.songFinishedHook?.invoke(currentTrack!!.gdxMusic)
|
currentTrack?.songFinishedHook?.invoke(currentTrack!!.gdxMusic)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
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.INGAME
|
import net.torvald.terrarum.INGAME
|
||||||
import net.torvald.terrarum.ReferencingRanges
|
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.modulebasegame.MusicContainer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.savegame.toBigEndian
|
import net.torvald.terrarum.savegame.toBigEndian
|
||||||
@@ -88,6 +93,60 @@ abstract class Actor : Comparable<Actor>, Runnable {
|
|||||||
*/
|
*/
|
||||||
abstract @Event fun onActorValueChange(key: String, value: Any?)
|
abstract @Event fun onActorValueChange(key: String, value: Any?)
|
||||||
|
|
||||||
|
// @Transient val soundTracks = HashMap<Sound, TerrarumAudioMixerTrack>()
|
||||||
|
@Transient val musicTracks = HashMap<MusicContainer, TerrarumAudioMixerTrack>()
|
||||||
|
|
||||||
|
/*open fun startAudio(sound: Sound) {
|
||||||
|
getTrackByAudio(sound)?.let {
|
||||||
|
it.trackingTarget = if (this is ActorWithBody) this else null
|
||||||
|
it.currentSound = sound
|
||||||
|
it.play()
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private fun getTrackByAudio(music: MusicContainer): TerrarumAudioMixerTrack? {
|
||||||
|
// get existing track
|
||||||
|
var track = musicTracks[music]
|
||||||
|
|
||||||
|
// if there is no existing track, try to get one
|
||||||
|
if (track == null) {
|
||||||
|
track = if (this == Terrarum.ingame?.actorNowPlaying)
|
||||||
|
AudioMixer.getFreeTrackNoMatterWhat()
|
||||||
|
else
|
||||||
|
AudioMixer.getFreeTrack()
|
||||||
|
// if the request was successful, put it into the hashmap
|
||||||
|
if (track != null) {
|
||||||
|
musicTracks[music] = track
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return track
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun startAudio(music: MusicContainer) {
|
||||||
|
getTrackByAudio(music)?.let {
|
||||||
|
it.trackingTarget = if (this is ActorWithBody) this else null
|
||||||
|
it.currentTrack = music
|
||||||
|
it.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*open fun stopAudio(sound: Sound) {
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
open fun stopAudio(music: MusicContainer) {
|
||||||
|
musicTracks[music]?.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*open fun onAudioInterrupt(sound: Sound) {
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
open @Event fun onAudioInterrupt(music: MusicContainer) {
|
||||||
|
music.songFinishedHook(music.gdxMusic)
|
||||||
|
}
|
||||||
|
|
||||||
abstract fun dispose()
|
abstract fun dispose()
|
||||||
|
|
||||||
@Transient val localHash = HQRNG().nextInt()
|
@Transient val localHash = HQRNG().nextInt()
|
||||||
|
|||||||
Reference in New Issue
Block a user