footstep sounds

This commit is contained in:
minjaesong
2023-12-02 23:58:18 +09:00
parent 18f8fa881f
commit d145edf11d
9 changed files with 64 additions and 53 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -81,7 +81,7 @@ object AudioMixer: Disposable {
get() = tracks[1]
val guiTrack: TerrarumAudioMixerTrack
get() = tracks[2]
val sfxSumTrack: TerrarumAudioMixerTrack
val sfxSumBus: TerrarumAudioMixerTrack
get() = tracks[3]
val sumBus: TerrarumAudioMixerTrack
@@ -170,7 +170,7 @@ object AudioMixer: Disposable {
init {
// initialise audio paths //
listOf(musicTrack, ambientTrack, sfxSumTrack, guiTrack).forEach {
listOf(musicTrack, ambientTrack, sfxSumBus, guiTrack).forEach {
it.filters[0] = Gain(1f)
}
@@ -181,7 +181,7 @@ object AudioMixer: Disposable {
listOf(sumBus, convolveBusOpen, convolveBusCave).forEach {
it.addSidechainInput(musicTrack, 1.0)
it.addSidechainInput(ambientTrack, 1.0)
it.addSidechainInput(sfxSumTrack, 1.0)
it.addSidechainInput(sfxSumBus, 1.0)
}
convolveBusOpen.filters[1] = Convolv(ModMgr.getFile("basegame", "audio/convolution/EchoThief - PurgatoryChasm.bin"))
@@ -202,18 +202,17 @@ object AudioMixer: Disposable {
dynamicTracks.forEach {
it.filters[0] = BinoPan(0f)
sfxSumTrack.addSidechainInput(it, 1.0)
sfxSumBus.addSidechainInput(it, 1.0)
}
parallelProcessingSchedule = arrayOf(
arrayOf(musicTrack, ambientTrack, guiTrack),
dynamicTracks,
arrayOf(sumBus, convolveBusOpen, convolveBusCave),
arrayOf(sfxSumBus, 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
@@ -291,7 +290,7 @@ object AudioMixer: Disposable {
masterTrack.volume = masterVolume
musicTrack.getFilter<Gain>().gain = musicVolume.toFloat()
ambientTrack.getFilter<Gain>().gain = ambientVolume.toFloat()
sfxSumTrack.getFilter<Gain>().gain = sfxVolume.toFloat()
sfxSumBus.getFilter<Gain>().gain = sfxVolume.toFloat()
guiTrack.getFilter<Gain>().gain = guiVolume.toFloat()

View File

@@ -92,10 +92,6 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
// fetch deviceBufferSize amount of sample from the disk
if (track.trackType != TrackType.MASTER && track.trackType != TrackType.BUS && track.streamPlaying) {
if (track.trackType == TrackType.DYNAMIC_SOURCE) {
printdbg("${track.name} streaming")
}
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
@@ -117,7 +113,7 @@ class MixerTrackProcessor(val bufferSize: Int, val rate: Int, val track: Terraru
samplesL1 = FloatArray(bufferSize / 4)
samplesR1 = FloatArray(bufferSize / 4)
val sidechains = track.sidechainInputs.filterNotNull()
val sidechains = track.sidechainInputs
// add all up
sidechains.forEach { (side, mix) ->
for (i in samplesL1.indices) {

View File

@@ -64,13 +64,13 @@ class TerrarumAudioMixerTrack(val name: String, val trackType: TrackType, var ma
inline fun <reified T> getFilter() = filters.filterIsInstance<T>().first()!!
internal val sidechainInputs = ArrayList<Pair<TerrarumAudioMixerTrack, TrackVolume>?>()
internal fun getSidechains(): List<TerrarumAudioMixerTrack?> = sidechainInputs.map { it?.first }
internal val sidechainInputs = ArrayList<Pair<TerrarumAudioMixerTrack, TrackVolume>>()
internal fun getSidechains(): List<TerrarumAudioMixerTrack?> = sidechainInputs.map { it.first }
fun addSidechainInput(input: TerrarumAudioMixerTrack, inputVolume: TrackVolume) {
if (input.trackType == TrackType.MASTER)
throw IllegalArgumentException("Cannot add master track as a sidechain")
if (sidechainInputs.map { it?.first }.any { it?.hash == input.hash })
if (sidechainInputs.map { it.first }.any { it.hash == input.hash })
throw IllegalArgumentException("The track '${input.hash}' already exists")
if (getSidechains().any { mySidechain ->

View File

@@ -390,8 +390,6 @@ open class ActorWithBody : Actor {
internal var walledTop = false // UNUSED; only for BasicDebugInfoWindow
internal var walledBottom = false // UNUSED; only for BasicDebugInfoWindow
internal var colliding = false
@Transient internal var feetTiles = Array<BlockProp?>(160) { null }
@Transient internal var bodyTiles = Array<BlockProp?>(2400) { null }
var isWalkingH = false
var isWalkingV = false
@@ -587,9 +585,11 @@ open class ActorWithBody : Actor {
}
}
// make dusts
// make some effects
if (collisionStatus != 0)
makeDust(collisionDamage, vecSum)
if (collisionStatus == COLLIDING_BOTTOM)
makeNoise(collisionDamage)
}
else {
stairPenaltyCounter = 999
@@ -631,22 +631,7 @@ open class ActorWithBody : Actor {
walledTop = isWalled(hitbox, COLLIDING_TOP)
walledBottom = isWalled(hitbox, COLLIDING_BOTTOM)
colliding = isColliding(hitbox)
var ptrFeet = 0
var ptrBody = 0
forEachFeetTile {
if (ptrFeet < feetTiles.size) {
feetTiles[ptrFeet] = it
ptrFeet += 1
}
}
forEachOccupyingTile {
if (ptrBody < bodyTiles.size) {
bodyTiles[ptrBody] = it
ptrBody += 1
}
}
feetTiles.fill(null, ptrFeet)
bodyTiles.fill(null, ptrBody)
if (isNoCollideWorld) {
walledLeft = false
walledRight = false
@@ -2014,6 +1999,19 @@ open class ActorWithBody : Actor {
return tileProps.forEach(consumer)
}
fun forEachFeetTileWithPos(consumer: (Point2i, ItemID) -> Unit) {
val y = intTilewiseHitbox.height.toInt() + 1
(0..intTilewiseHitbox.width.toInt()).map { x ->
val px = x + intTilewiseHitbox.startX.toInt()
val py = y + intTilewiseHitbox.startY.toInt()
val point = Point2i(px, py)
val item = world!!.getTileFromTerrain(px, py)
consumer(point, item)
}
}
fun getFeetTiles(): List<Pair<Point2i, ItemID>> {
val y = intTilewiseHitbox.height.toInt() + 1
return (0..intTilewiseHitbox.width.toInt()).map { x ->
@@ -2027,11 +2025,12 @@ open class ActorWithBody : Actor {
val particleCount = (collisionDamage / 24.0).pow(0.75)
val trueParticleCount = particleCount.toInt() + (Math.random() < (particleCount % 1.0)).toInt()
if (collisionDamage > 1.0 / 1024.0) {
// printdbg(this, "Collision damage: $collisionDamage N, count: $particleCount, velocity: $vecSum, mass: ${this.mass}")
val feetTiles = getFeetTiles()
val feetTiles = getFeetTiles()
val feetTileIndices = feetTiles.indices.toList().toIntArray()
if (collisionDamage > 1.0 / 1024.0) {
printdbg(this, "Collision damage: $collisionDamage N, count: $particleCount, velocity: $vecSum, mass: ${this.mass}")
printdbg(this, "feetTileCount = ${feetTiles.size}")
val feetTileIndices = (feetTiles.indices).toList().toIntArray()
for (i in 0 until trueParticleCount) {
if (i % feetTiles.size == 0) feetTileIndices.shuffle()
@@ -2043,17 +2042,22 @@ open class ActorWithBody : Actor {
}
}
if (particleCount >= 1.0) {
val volumeMax = (particleCount.pow(0.75) / 8.0).coerceIn(0.0, 2.0)
val feetTileMats = feetTiles.map { BlockCodex[it.second].material }
val feetTileCnt = feetTileMats.size.toDouble()
val materialStats = feetTileMats.distinct().map { mat -> mat to feetTileMats.count { it == mat } }
materialStats.forEach { (mat, cnt) ->
Terrarum.audioCodex.getRandomFootstep(mat)?.let {
val vol = volumeMax * (cnt / feetTileCnt)
startAudio(it, vol)
printdbg(this, "Playing footstep $mat (vol: $vol, file: ${it.file.name})")
}
}
}
private fun makeNoise(collisionDamage: Double) {
if (collisionDamage > 1.0 / 1024.0) {
val feetTiles = getFeetTiles()
val volumeMax = collisionDamage / 108
val feetTileMats = feetTiles.slice(0 until feetTiles.size).map { BlockCodex[it.second].material }
val feetTileCnt = feetTileMats.size.toDouble()
val materialStats = feetTileMats.distinct().map { mat -> mat to feetTileMats.count { it == mat } }
materialStats.forEach { (mat, cnt) ->
Terrarum.audioCodex.getRandomFootstep(mat)?.let {
val vol = volumeMax * (cnt / feetTileCnt)
startAudio(it, vol)
printdbg(this, "Playing footstep $mat (vol: $vol, file: ${it.file.name}, cd: $collisionDamage)")
}
}
}

View File

@@ -422,7 +422,7 @@ class BasicDebugInfoWindow : UICanvas() {
val x = App.scr.width - 186 - (AudioMixer.tracks.size + 1) * (stripW + stripGap)
val y = App.scr.height - 38 - stripH
val strips = AudioMixer.tracks + AudioMixer.masterTrack
val strips = /*AudioMixer.dynamicTracks.sliceArray(0..7) +*/ AudioMixer.tracks + AudioMixer.masterTrack
// batch.color = COL_MIXER_BACK
// Toolkit.fillArea(batch, x - stripGap, y - stripGap, strips.size * (stripW + stripGap) + stripGap, stripH + 2*stripGap)
@@ -486,8 +486,8 @@ class BasicDebugInfoWindow : UICanvas() {
val faderY = y + stripFilterHeight * numberOfFilters
// receives (opposite of "sends")
if (track != AudioMixer.sfxSumTrack) {
track.sidechainInputs.filterNotNull().reversed().forEachIndexed { i, (side, mix) ->
if (track != AudioMixer.sfxSumBus) {
track.sidechainInputs.reversed().forEachIndexed { i, (side, mix) ->
val mixDb = fullscaleToDecibels(mix)
val perc = ((mixDb + 24.0).coerceAtLeast(0.0) / 24.0).toFloat()
// gauge background
@@ -527,7 +527,7 @@ class BasicDebugInfoWindow : UICanvas() {
// slider text
val dB = track.dBfs
val dBstr = dB.toIntAndFrac(3,1)
val faderKnobDbFs = dB.coerceIn(-dbLow, 0.0).plus(dbLow).div(dbLow + dbOver).toFloat()
val faderKnobDbFs = dB.coerceIn(-dbLow, 6.0).plus(dbLow).div(dbLow + dbOver).toFloat()
batch.color = FILTER_NAME_ACTIVE
App.fontSmallNumbers.draw(batch, dBstr, sliderX - 23f, faderY+1f)