mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 18:44:05 +09:00
date marks for DSPs
This commit is contained in:
@@ -144,7 +144,8 @@ class MixerTrackProcessor(bufferSize: Int, val rate: Int, val track: TerrarumAud
|
|||||||
)
|
)
|
||||||
val isApproaching = if (distFromActorNext <= distFromActor) 1.0 else -1.0
|
val isApproaching = if (distFromActorNext <= distFromActor) 1.0 else -1.0
|
||||||
val relativeSpeed = (sourceVec - listenerVec).magnitude * GAME_TO_SI_VELO * isApproaching
|
val relativeSpeed = (sourceVec - listenerVec).magnitude * GAME_TO_SI_VELO * isApproaching
|
||||||
val dopplerFactor = (SPEED_OF_SOUND_AIR + relativeSpeed) / SPEED_OF_SOUND_AIR // >1: speedup, <1: speeddown
|
val soundSpeed = SPEED_OF_SOUND_AIR * 4f // using an arbitrary value for "gamification"
|
||||||
|
val dopplerFactor = (soundSpeed + relativeSpeed) / soundSpeed // >1: speedup, <1: speeddown
|
||||||
|
|
||||||
track.processor.streamBuf?.playbackSpeed = dopplerFactor.toFloat()
|
track.processor.streamBuf?.playbackSpeed = dopplerFactor.toFloat()
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import kotlin.math.tanh
|
|||||||
* @param pan -1 for far-left, 0 for centre, 1 for far-right
|
* @param pan -1 for far-left, 0 for centre, 1 for far-right
|
||||||
* @param soundSpeed speed of the sound in meters per seconds
|
* @param soundSpeed speed of the sound in meters per seconds
|
||||||
* @param earDist distance between ears in meters. Maximum: 16.0
|
* @param earDist distance between ears in meters. Maximum: 16.0
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2023-11-23.
|
||||||
*/
|
*/
|
||||||
class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAudioFilter() {
|
class BinoPan(var pan: Float, var earDist: Float = EARDIST_DEFAULT): TerrarumAudioFilter() {
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow
|
|||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.toIntAndFrac
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.toIntAndFrac
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-23.
|
||||||
|
*/
|
||||||
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) {
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-18.
|
||||||
|
*/
|
||||||
object Buffer : TerrarumAudioFilter() {
|
object Buffer : TerrarumAudioFilter() {
|
||||||
init {
|
init {
|
||||||
bypass = true
|
bypass = true
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import kotlin.math.roundToInt
|
|||||||
* @param ir Binary file containing MONO IR (containing only two channels)
|
* @param ir Binary file containing MONO IR (containing only two channels)
|
||||||
* @param crossfeed The amount of channel crossfeeding to simulate the true stereo IR. Fullscale (0.0 - 1.0)
|
* @param crossfeed The amount of channel crossfeeding to simulate the true stereo IR. Fullscale (0.0 - 1.0)
|
||||||
* @param gain output gain. Fullscale (0.0 - 1.0)
|
* @param gain output gain. Fullscale (0.0 - 1.0)
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2023-11-25.
|
||||||
*/
|
*/
|
||||||
class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
class Convolv(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-25.
|
||||||
|
*/
|
||||||
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 App.audioBufferSize) {
|
for (i in 0 until App.audioBufferSize) {
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2
|
|||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-19.
|
||||||
|
*/
|
||||||
class Highpass(cutoff0: Float): TerrarumAudioFilter() {
|
class Highpass(cutoff0: Float): TerrarumAudioFilter() {
|
||||||
|
|
||||||
var cutoff = cutoff0.toDouble(); private set
|
var cutoff = cutoff0.toDouble(); private set
|
||||||
|
|||||||
53
src/net/torvald/terrarum/audio/dsp/LoFi.kt
Normal file
53
src/net/torvald/terrarum/audio/dsp/LoFi.kt
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package net.torvald.terrarum.audio.dsp
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.tanh
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convolver with tanh saturator
|
||||||
|
*
|
||||||
|
* @param ir Binary file containing MONO IR (containing only two channels)
|
||||||
|
* @param crossfeed The amount of channel crossfeeding to simulate the true stereo IR. Fullscale (0.0 - 1.0)
|
||||||
|
* @param gain output gain. Fullscale (0.0 - 1.0)
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2024-01-21.
|
||||||
|
*/
|
||||||
|
class LoFi(ir: File, val crossfeed: Float, gain: Float = 1f / 256f): TerrarumAudioFilter(), DspCompressor {
|
||||||
|
override val downForce = arrayOf(1.0f, 1.0f)
|
||||||
|
|
||||||
|
internal val convolver = Convolv(ir, crossfeed, gain)
|
||||||
|
|
||||||
|
private val imm = listOf(FloatArray(App.audioBufferSize), FloatArray(App.audioBufferSize))
|
||||||
|
|
||||||
|
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
||||||
|
convolver.thru(inbuf, imm)
|
||||||
|
|
||||||
|
for (ch in imm.indices) {
|
||||||
|
val inn = imm[ch]
|
||||||
|
val out = outbuf[ch]
|
||||||
|
|
||||||
|
for (i in inn.indices) {
|
||||||
|
val u = inn[i]
|
||||||
|
val v = tanh(u)
|
||||||
|
val diff = (v.absoluteValue / u.absoluteValue)
|
||||||
|
out[i] = v
|
||||||
|
|
||||||
|
if (!diff.isNaN()) {
|
||||||
|
downForce[ch] = minOf(downForce[ch], diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override val debugViewHeight = 0
|
||||||
|
|
||||||
|
override fun copyParamsFrom(other: TerrarumAudioFilter) {
|
||||||
|
this.convolver.copyParamsFrom((other as LoFi).convolver)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,9 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.COL_METER_GRAD2
|
|||||||
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.FILTER_NAME_ACTIVE
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-17.
|
||||||
|
*/
|
||||||
class Lowpass(cutoff0: Float): TerrarumAudioFilter() {
|
class Lowpass(cutoff0: Float): TerrarumAudioFilter() {
|
||||||
|
|
||||||
var cutoff = cutoff0.toDouble(); private set
|
var cutoff = cutoff0.toDouble(); private set
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package net.torvald.terrarum.audio.dsp
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-17.
|
||||||
|
*/
|
||||||
object NullFilter : TerrarumAudioFilter() {
|
object NullFilter : TerrarumAudioFilter() {
|
||||||
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
||||||
outbuf.forEachIndexed { index, outTrack ->
|
outbuf.forEachIndexed { index, outTrack ->
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-23.
|
||||||
|
*/
|
||||||
class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: Float = 1200f): TerrarumAudioFilter() {
|
class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: Float = 1200f): TerrarumAudioFilter() {
|
||||||
|
|
||||||
private val highpass = 80f
|
private val highpass = 80f
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ import kotlin.math.absoluteValue
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
object SoftClp : TerrarumAudioFilter() {
|
/**
|
||||||
val downForce = arrayOf(1.0f, 1.0f)
|
* Created by minjaesong on 2023-11-20.
|
||||||
|
*/
|
||||||
|
object SoftClp : TerrarumAudioFilter(), DspCompressor {
|
||||||
|
override val downForce = arrayOf(1.0f, 1.0f)
|
||||||
|
|
||||||
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
||||||
downForce.fill(1.0f)
|
downForce.fill(1.0f)
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W
|
|||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-12-21.
|
||||||
|
*/
|
||||||
class Spectro(var gain: Float = 1f) : TerrarumAudioFilter() {
|
class Spectro(var gain: Float = 1f) : TerrarumAudioFilter() {
|
||||||
private val FFTSIZE = 1024
|
private val FFTSIZE = 1024
|
||||||
private val inBuf = Array(2) { FloatArray(FFTSIZE) }
|
private val inBuf = Array(2) { FloatArray(FFTSIZE) }
|
||||||
@@ -99,7 +102,9 @@ class Spectro(var gain: Float = 1f) : TerrarumAudioFilter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-20.
|
||||||
|
*/
|
||||||
class Vecto(var gain: Float = 1f) : TerrarumAudioFilter() {
|
class Vecto(var gain: Float = 1f) : TerrarumAudioFilter() {
|
||||||
var backbufL = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
|
var backbufL = Array((6144f / App.audioBufferSize).roundToInt().coerceAtLeast(1)) {
|
||||||
FloatArray(App.audioBufferSize)
|
FloatArray(App.audioBufferSize)
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package net.torvald.terrarum.audio.dsp
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-17.
|
||||||
|
*/
|
||||||
abstract class TerrarumAudioFilter {
|
abstract class TerrarumAudioFilter {
|
||||||
var bypass = false
|
var bypass = false
|
||||||
protected abstract fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>)
|
abstract fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>)
|
||||||
operator fun invoke(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
operator fun invoke(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
||||||
if (bypass) {
|
if (bypass) {
|
||||||
outbuf.forEachIndexed { index, outTrack ->
|
outbuf.forEachIndexed { index, outTrack ->
|
||||||
@@ -18,6 +21,13 @@ abstract class TerrarumAudioFilter {
|
|||||||
abstract fun copyParamsFrom(other: TerrarumAudioFilter)
|
abstract fun copyParamsFrom(other: TerrarumAudioFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2024-01-21.
|
||||||
|
*/
|
||||||
|
interface DspCompressor {
|
||||||
|
val downForce: Array<Float>
|
||||||
|
}
|
||||||
|
|
||||||
fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray()
|
fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray()
|
||||||
fun push(samples: FloatArray, buf: FloatArray) {
|
fun push(samples: FloatArray, buf: FloatArray) {
|
||||||
if (samples.size >= buf.size) {
|
if (samples.size >= buf.size) {
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-24.
|
||||||
|
*/
|
||||||
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 App.audioBufferSize) {
|
for (i in 0 until App.audioBufferSize) {
|
||||||
@@ -24,6 +27,9 @@ object XYtoMS: TerrarumAudioFilter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-11-24.
|
||||||
|
*/
|
||||||
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 App.audioBufferSize) {
|
for (i in 0 until App.audioBufferSize) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ 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.Companion.DEFAULT_FADEOUT_LEN
|
import net.torvald.terrarum.audio.AudioMixer.Companion.DEFAULT_FADEOUT_LEN
|
||||||
import net.torvald.terrarum.audio.dsp.Convolv
|
import net.torvald.terrarum.audio.dsp.Convolv
|
||||||
|
import net.torvald.terrarum.audio.dsp.LoFi
|
||||||
import net.torvald.terrarum.audio.dsp.NullFilter
|
import net.torvald.terrarum.audio.dsp.NullFilter
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
@@ -40,6 +41,8 @@ class FixtureJukebox : Electric {
|
|||||||
|
|
||||||
@Transient private val backLamp: SheetSpriteAnimation
|
@Transient private val backLamp: SheetSpriteAnimation
|
||||||
|
|
||||||
|
@Transient private val filterIndex = 2
|
||||||
|
|
||||||
internal val discInventory = ArrayList<ItemID>()
|
internal val discInventory = ArrayList<ItemID>()
|
||||||
|
|
||||||
val musicIsPlaying: Boolean
|
val musicIsPlaying: Boolean
|
||||||
@@ -114,7 +117,7 @@ class FixtureJukebox : Electric {
|
|||||||
|
|
||||||
App.audioMixer.requestFadeOut(App.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[filterIndex] = LoFi(
|
||||||
ModMgr.getFile(
|
ModMgr.getFile(
|
||||||
"basegame",
|
"basegame",
|
||||||
"audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin"
|
"audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin"
|
||||||
@@ -162,7 +165,7 @@ class FixtureJukebox : Electric {
|
|||||||
private fun unloadConvolver(music: MusicContainer?) {
|
private fun unloadConvolver(music: MusicContainer?) {
|
||||||
if (music != null) {
|
if (music != null) {
|
||||||
musicTracks[music]?.let {
|
musicTracks[music]?.let {
|
||||||
it.filters[2] = NullFilter
|
it.filters[filterIndex] = NullFilter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -721,7 +721,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// comp marker
|
// comp marker
|
||||||
track.filters.filterIsInstance<SoftClp>().firstOrNull()?.let {
|
track.filters.filterIsInstance<DspCompressor>().firstOrNull()?.let {
|
||||||
for (ch in 0..1) {
|
for (ch in 0..1) {
|
||||||
val downForceNow = it.downForce[ch] * 1.0
|
val downForceNow = it.downForce[ch] * 1.0
|
||||||
if (downForceNow != 0.0) {
|
if (downForceNow != 0.0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user