mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-14 12:34:05 +09:00
mixer: room for dynamic sources
This commit is contained in:
@@ -45,17 +45,19 @@ object AudioMixer: Disposable {
|
||||
val guiVolume: Double
|
||||
get() = App.getConfigDouble("guivolume")
|
||||
|
||||
val dynamicSourceCount: Int
|
||||
get() = App.getConfigInt("audio_dynamic_source_max")
|
||||
|
||||
val tracks = Array(8) { TerrarumAudioMixerTrack(
|
||||
if (it == 0) "Music"
|
||||
else if (it == 1) "Ambient"
|
||||
else if (it == 2) "Player"
|
||||
else if (it == 3) "GUI"
|
||||
else if (it == 2) "GUI"
|
||||
else if (it == 3) "\u00E4SFX"
|
||||
else if (it == 4) "\u00F0 \u00E4 \u00F0" // summation
|
||||
else if (it == 5) "\u00D9Open\u00D9" // convolution1
|
||||
else if (it == 6) "\u00D9Cave\u00D9" // convolution2
|
||||
else if (it == 7) "\u00F0 \u00DA \u00F0" // fade
|
||||
else "Trk${it+1}", isBus = (it >= 4), maxVolumeFun = {
|
||||
else "Trk${it+1}", trackType = if (it >= 3) TrackType.BUS else TrackType.STATIC_SOURCE, maxVolumeFun = {
|
||||
when (it) {
|
||||
0 -> { musicVolume }
|
||||
1 -> { ambientVolume }
|
||||
@@ -66,15 +68,20 @@ object AudioMixer: Disposable {
|
||||
}
|
||||
) }
|
||||
|
||||
val masterTrack = TerrarumAudioMixerTrack("\u00DBMASTER", true) { masterVolume }
|
||||
val dynamicTracks = Array(dynamicSourceCount) { TerrarumAudioMixerTrack(
|
||||
"DS${(it + 1).toString().padStart(3, '0')}",
|
||||
TrackType.DYNAMIC_SOURCE
|
||||
) }
|
||||
|
||||
val masterTrack = TerrarumAudioMixerTrack("\u00DBMASTER", TrackType.MASTER) { masterVolume }
|
||||
|
||||
val musicTrack: TerrarumAudioMixerTrack
|
||||
get() = tracks[0]
|
||||
val ambientTrack: TerrarumAudioMixerTrack
|
||||
get() = tracks[1]
|
||||
val sfxMixTrack: TerrarumAudioMixerTrack
|
||||
get() = tracks[2]
|
||||
val guiTrack: TerrarumAudioMixerTrack
|
||||
get() = tracks[2]
|
||||
val sfxSumTrack: TerrarumAudioMixerTrack
|
||||
get() = tracks[3]
|
||||
|
||||
val sumBus: TerrarumAudioMixerTrack
|
||||
@@ -145,10 +152,7 @@ object AudioMixer: Disposable {
|
||||
init {
|
||||
// initialise audio paths //
|
||||
|
||||
// musicTrack.filters[1] = BinoPan(0f)
|
||||
// musicTrack.filters[2] = Reverb(36f, 0.92f, 1200f)
|
||||
|
||||
listOf(musicTrack, ambientTrack, sfxMixTrack, guiTrack).forEach {
|
||||
listOf(musicTrack, ambientTrack, sfxSumTrack, guiTrack).forEach {
|
||||
it.filters[0] = Gain(1f)
|
||||
}
|
||||
|
||||
@@ -159,7 +163,7 @@ object AudioMixer: Disposable {
|
||||
listOf(sumBus, convolveBusOpen, convolveBusCave).forEach {
|
||||
it.addSidechainInput(musicTrack, 1.0)
|
||||
it.addSidechainInput(ambientTrack, 1.0)
|
||||
it.addSidechainInput(sfxMixTrack, 1.0)
|
||||
it.addSidechainInput(sfxSumTrack, 1.0)
|
||||
}
|
||||
|
||||
convolveBusOpen.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - PurgatoryChasm.bin"))
|
||||
@@ -178,9 +182,14 @@ object AudioMixer: Disposable {
|
||||
masterTrack.addSidechainInput(fadeBus, 1.0)
|
||||
masterTrack.addSidechainInput(guiTrack, 1.0)
|
||||
|
||||
dynamicTracks.forEach {
|
||||
it.filters[0] = BinoPan(0f)
|
||||
sfxSumTrack.addSidechainInput(it, 1.0)
|
||||
}
|
||||
|
||||
parallelProcessingSchedule = arrayOf(
|
||||
arrayOf(musicTrack, ambientTrack, sfxMixTrack, guiTrack),
|
||||
arrayOf(musicTrack, ambientTrack, guiTrack),
|
||||
dynamicTracks,
|
||||
arrayOf(sumBus, convolveBusOpen, convolveBusCave),
|
||||
arrayOf(fadeBus),
|
||||
arrayOf(masterTrack)
|
||||
@@ -204,7 +213,7 @@ object AudioMixer: Disposable {
|
||||
)
|
||||
|
||||
private val fadeReqs = HashMap<TerrarumAudioMixerTrack, FadeRequest>().also { map ->
|
||||
listOf(musicTrack, ambientTrack, sfxMixTrack, guiTrack, fadeBus).forEach {
|
||||
listOf(musicTrack, ambientTrack, guiTrack, fadeBus).forEach {
|
||||
map[it] = FadeRequest()
|
||||
}
|
||||
}
|
||||
@@ -264,7 +273,7 @@ object AudioMixer: Disposable {
|
||||
masterTrack.volume = masterVolume
|
||||
musicTrack.getFilter<Gain>().gain = musicVolume.toFloat()
|
||||
ambientTrack.getFilter<Gain>().gain = ambientVolume.toFloat()
|
||||
sfxMixTrack.getFilter<Gain>().gain = sfxVolume.toFloat()
|
||||
sfxSumTrack.getFilter<Gain>().gain = sfxVolume.toFloat()
|
||||
guiTrack.getFilter<Gain>().gain = guiVolume.toFloat()
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
||||
// Your code here
|
||||
|
||||
// fetch deviceBufferSize amount of sample from the disk
|
||||
if (!track.isMaster && !track.isBus && track.streamPlaying) {
|
||||
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying) {
|
||||
streamBuf.fetchBytes {
|
||||
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
|
||||
@@ -87,7 +87,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
||||
var bufEmpty = false
|
||||
|
||||
// get samples and apply the fader
|
||||
if (track.isMaster || track.isBus) {
|
||||
if (track.trackType == TrackType.MASTER || track.trackType == TrackType.BUS) {
|
||||
// combine all the inputs
|
||||
samplesL1 = FloatArray(bufferSize / 4)
|
||||
samplesR1 = FloatArray(bufferSize / 4)
|
||||
@@ -164,7 +164,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
|
||||
|
||||
|
||||
// by this time, the output buffer is filled with processed results, pause the execution
|
||||
if (!track.isMaster) {
|
||||
if (track.trackType != TrackType.MASTER) {
|
||||
this.pause()
|
||||
}
|
||||
else {
|
||||
@@ -246,7 +246,7 @@ private fun <T> Queue<T>.removeFirstOrElse(function: () -> T): T {
|
||||
|
||||
class FeedSamplesToAdev(val bufferSize: Int, val rate: Int, val track: TerrarumAudioMixerTrack) : Runnable {
|
||||
init {
|
||||
if (!track.isMaster) throw IllegalArgumentException("Track is not master")
|
||||
if (track.trackType != TrackType.MASTER) throw IllegalArgumentException("Track is not master")
|
||||
}
|
||||
|
||||
val sleepTime = (1000000000.0 * ((bufferSize / 4.0) / TerrarumAudioMixerTrack.SAMPLING_RATED)).toLong()
|
||||
|
||||
@@ -15,13 +15,17 @@ import kotlin.math.pow
|
||||
|
||||
typealias TrackVolume = Double
|
||||
|
||||
class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, val isBus: Boolean = false, private val maxVolumeFun: () -> Double): Disposable {
|
||||
enum class TrackType {
|
||||
STATIC_SOURCE, DYNAMIC_SOURCE, BUS, MASTER
|
||||
}
|
||||
|
||||
class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, private val maxVolumeFun: () -> Double = {1.0}): Disposable {
|
||||
|
||||
companion object {
|
||||
const val SAMPLING_RATE = 48000
|
||||
const val SAMPLING_RATEF = 48000f
|
||||
const val SAMPLING_RATED = 48000.0
|
||||
val BUFFER_SIZE = 4 * App.getConfigInt("audiobuffersize") // n ms -> 384 * n
|
||||
val BUFFER_SIZE = 4 * App.getConfigInt("audio_buffer_size") // n ms -> 384 * n
|
||||
}
|
||||
|
||||
val hash = getHashStr()
|
||||
@@ -52,10 +56,10 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v
|
||||
|
||||
inline fun <reified T> getFilter() = filters.filterIsInstance<T>().first()!!
|
||||
|
||||
internal val sidechainInputs = Array<Pair<TerrarumAudioMixerTrack, TrackVolume>?>(16) { null }
|
||||
internal val sidechainInputs = ArrayList<Pair<TerrarumAudioMixerTrack, TrackVolume>?>()
|
||||
internal fun getSidechains(): List<TerrarumAudioMixerTrack?> = sidechainInputs.map { it?.first }
|
||||
fun addSidechainInput(input: TerrarumAudioMixerTrack, inputVolume: TrackVolume) {
|
||||
if (input.isMaster)
|
||||
if (input.trackType == TrackType.MASTER)
|
||||
throw IllegalArgumentException("Cannot add master track as a sidechain")
|
||||
|
||||
if (sidechainInputs.map { it?.first }.any { it?.hash == input.hash })
|
||||
@@ -67,13 +71,8 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v
|
||||
})
|
||||
throw IllegalArgumentException("The track '${input.hash}' contains current track (${this.hash}) as its sidechain")
|
||||
|
||||
val emptySpot = sidechainInputs.indexOf(null)
|
||||
if (emptySpot != -1) {
|
||||
sidechainInputs[emptySpot] = (input to inputVolume)
|
||||
}
|
||||
else {
|
||||
throw IllegalStateException("Sidechain is full (${sidechainInputs.size})!")
|
||||
}
|
||||
|
||||
sidechainInputs.add(input to inputVolume)
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +86,7 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v
|
||||
it.get(Gdx.audio) as Int
|
||||
}
|
||||
internal val adev: OpenALBufferedAudioDevice? =
|
||||
if (isMaster) {
|
||||
if (trackType == TrackType.MASTER) {
|
||||
OpenALBufferedAudioDevice(
|
||||
Gdx.audio as OpenALLwjgl3Audio,
|
||||
SAMPLING_RATE,
|
||||
|
||||
Reference in New Issue
Block a user