mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
footstep sounds
This commit is contained in:
BIN
assets/mods/basegame/audio/effects/steps/DIRT_1.ogg
LFS
Normal file
BIN
assets/mods/basegame/audio/effects/steps/DIRT_1.ogg
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/audio/effects/steps/DIRT_2.ogg
LFS
Normal file
BIN
assets/mods/basegame/audio/effects/steps/DIRT_2.ogg
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/audio/effects/steps/DIRT_3.ogg
LFS
Normal file
BIN
assets/mods/basegame/audio/effects/steps/DIRT_3.ogg
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/audio/effects/steps/DIRT_4.ogg
LFS
Normal file
BIN
assets/mods/basegame/audio/effects/steps/DIRT_4.ogg
LFS
Normal file
Binary file not shown.
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user