mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
parallelised audio processing
This commit is contained in:
@@ -9,10 +9,12 @@ import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATE
|
||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED
|
||||
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||
import net.torvald.terrarum.modulebasegame.MusicContainer
|
||||
import net.torvald.terrarum.tryDispose
|
||||
import java.lang.Thread.MAX_PRIORITY
|
||||
import java.util.*
|
||||
import java.util.concurrent.Callable
|
||||
import kotlin.math.*
|
||||
|
||||
/**
|
||||
@@ -86,8 +88,9 @@ object AudioMixer: Disposable {
|
||||
|
||||
var processing = true
|
||||
|
||||
private val processingExecutor = ThreadExecutor()
|
||||
val processingThread = Thread {
|
||||
while (processing) {
|
||||
/*while (processing) {
|
||||
// process
|
||||
tracks.forEach {
|
||||
if (!it.processor.paused) {
|
||||
@@ -100,12 +103,32 @@ object AudioMixer: Disposable {
|
||||
Thread.sleep(1)
|
||||
}*/
|
||||
|
||||
while (!masterTrack.pcmQueue.isEmpty) {
|
||||
masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed
|
||||
}
|
||||
}*/
|
||||
|
||||
while (processing) {
|
||||
parallelProcessingSchedule.forEach { tracks ->
|
||||
val callables = tracks.map { Callable {
|
||||
if (!it.processor.paused) {
|
||||
it.processor.run()
|
||||
}
|
||||
} }
|
||||
|
||||
processingExecutor.renew()
|
||||
processingExecutor.submitAll(callables)
|
||||
processingExecutor.join()
|
||||
}
|
||||
|
||||
while (!masterTrack.pcmQueue.isEmpty) {
|
||||
masterTrack.adev!!.writeSamples(masterTrack.pcmQueue.removeFirst()) // it blocks until the queue is consumed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val parallelProcessingSchedule: Array<Array<TerrarumAudioMixerTrack>>
|
||||
|
||||
// val feeder = FeedSamplesToAdev(BUFFER_SIZE, SAMPLING_RATE, masterTrack)
|
||||
// val feedingThread = Thread(feeder)
|
||||
|
||||
@@ -149,6 +172,14 @@ object AudioMixer: Disposable {
|
||||
masterTrack.addSidechainInput(guiTrack, 1.0)
|
||||
|
||||
|
||||
parallelProcessingSchedule = arrayOf(
|
||||
arrayOf(musicTrack, ambientTrack, sfxMixTrack, guiTrack),
|
||||
arrayOf(sumBus, convolveBusOpen, convolveBusCave),
|
||||
arrayOf(fadeBus),
|
||||
arrayOf(masterTrack)
|
||||
)
|
||||
|
||||
|
||||
processingThread.priority = MAX_PRIORITY // higher = more predictable; audio delay is very noticeable so it gets high priority
|
||||
processingThread.start()
|
||||
// feedingThread.priority = MAX_PRIORITY
|
||||
|
||||
@@ -312,7 +312,7 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass:
|
||||
|
||||
class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
||||
|
||||
private val fftLen: Int
|
||||
val fftLen: Int
|
||||
private val convFFT: Array<ComplexArray>
|
||||
// private val convFFTpartd: Array<Array<ComplexArray>> // index: Channel, partition, frequencies
|
||||
private val inbuf: Array<FloatArray>
|
||||
|
||||
@@ -20,7 +20,7 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v
|
||||
const val SAMPLING_RATE = 48000
|
||||
const val SAMPLING_RATEF = 48000f
|
||||
const val SAMPLING_RATED = 48000.0
|
||||
const val BUFFER_SIZE = 512*4 // n ms -> 384 * n
|
||||
const val BUFFER_SIZE = 256*4 // n ms -> 384 * n
|
||||
}
|
||||
|
||||
val hash = getHashStr()
|
||||
|
||||
@@ -398,6 +398,10 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
private val COL_METER_GRAD2 = Color(0x25a0f2_aa)
|
||||
private val COL_SENDS_GRAD = Color(0x50751c_aa)
|
||||
private val COL_SENDS_GRAD2 = Color(0xa0f225_aa.toInt())
|
||||
private val COL_METER_GRAD_YELLOW = Color(0x62471c_aa)
|
||||
private val COL_METER_GRAD2_YELLOW = Color(0xc68f24_aa.toInt())
|
||||
private val COL_METER_GRAD_RED = Color(0x921c34_aa.toInt())
|
||||
private val COL_METER_GRAD2_RED = Color(0xfa687d_aa.toInt())
|
||||
private val COL_METER_BAR = Color(0x4caee5_aa)
|
||||
private val COL_METER_BAR_OVER = Color(0xef8297_aa.toInt())
|
||||
private val COL_METER_COMP_BAR = Color(0xf3d458_aa.toInt())
|
||||
@@ -603,7 +607,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
"Highpass" to 16,
|
||||
"Buffer" to 16,
|
||||
"BinoPan" to 32,
|
||||
"Convolv" to 16,
|
||||
"Convolv" to 32,
|
||||
"Gain" to 16,
|
||||
"Scope" to stripW,
|
||||
)
|
||||
@@ -653,8 +657,26 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
App.fontSmallNumbers.draw(batch, "Bs:${BUFFER_SIZE/4}", x+3f, y+1f)
|
||||
}
|
||||
is Convolv -> {
|
||||
// processing speed bar
|
||||
val w = filter.processingSpeed
|
||||
val perc = w.coerceAtMost(2f) / 2f
|
||||
batch.color = if (w > 1.5f) COL_METER_GRAD2 else if (w > 1f) COL_METER_GRAD2_YELLOW else COL_METER_GRAD2_RED
|
||||
Toolkit.fillArea(batch, x.toFloat(), y.toFloat(), stripW * perc, 14f)
|
||||
batch.color = if (w > 1.5f) COL_METER_GRAD else if (w > 1f) COL_METER_GRAD_YELLOW else COL_METER_GRAD_RED
|
||||
Toolkit.fillArea(batch, x.toFloat(), y+14f, stripW * perc, 2f)
|
||||
|
||||
// filter length bar
|
||||
val g = FastMath.intLog2(BUFFER_SIZE / 4)
|
||||
val perc2 = (FastMath.intLog2(filter.fftLen).minus(g).toFloat() / (16f - g)).coerceIn(0f, 1f)
|
||||
batch.color = COL_METER_GRAD2
|
||||
Toolkit.fillArea(batch, x.toFloat(), y + 16f, stripW * perc2, 14f)
|
||||
batch.color = COL_METER_GRAD
|
||||
Toolkit.fillArea(batch, x.toFloat(), y + 16f+14f, stripW * perc2, 2f)
|
||||
|
||||
// texts
|
||||
batch.color = FILTER_NAME_ACTIVE
|
||||
App.fontSmallNumbers.draw(batch, "P:${filter.processingSpeed.times(100).roundToInt().div(100f)}x", x+3f, y+1f)
|
||||
App.fontSmallNumbers.draw(batch, "L:${filter.fftLen}", x+3f, y+17f)
|
||||
}
|
||||
is Gain -> {
|
||||
batch.color = FILTER_NAME_ACTIVE
|
||||
|
||||
Reference in New Issue
Block a user