mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 23:27:59 +01:00
Fixes for pegasus flying wind sound effect
This fixes several aspects of the wind sound effect: -Interpolation of FadeOutSoundInstance breaking the effect's volume controls -Attenuation and panning (3D audio) should now work correctly for other clients -New attenuation curve for velocity based attenuation -New pitch controls same as above -Made effect a continuous loop -Added rate limiter so that sudden movements won't cause volume and pitch jolts (storms?)
This commit is contained in:
parent
69c8ceac45
commit
e117fe44ea
6 changed files with 55 additions and 14 deletions
|
@ -10,6 +10,7 @@ public interface USounds {
|
||||||
SoundEvent ENTITY_PLAYER_BATPONY_SCREECH = register("entity.player.batpony.screech");
|
SoundEvent ENTITY_PLAYER_BATPONY_SCREECH = register("entity.player.batpony.screech");
|
||||||
SoundEvent ENTITY_PLAYER_REBOUND = register("entity.player.rebound");
|
SoundEvent ENTITY_PLAYER_REBOUND = register("entity.player.rebound");
|
||||||
SoundEvent ENTITY_PLAYER_PEGASUS_WINGSFLAP = register("entity.player.pegasus.wingsflap");
|
SoundEvent ENTITY_PLAYER_PEGASUS_WINGSFLAP = register("entity.player.pegasus.wingsflap");
|
||||||
|
SoundEvent ENTITY_PLAYER_PEGASUS_FLYING = register("entity.player.pegasus.flying");
|
||||||
SoundEvent ENTITY_PLAYER_PEGASUS_DASH = register("entity.player.pegasus.dash");
|
SoundEvent ENTITY_PLAYER_PEGASUS_DASH = register("entity.player.pegasus.dash");
|
||||||
SoundEvent ENTITY_PLAYER_PEGASUS_MOLT = register("entity.player.pegasus.molt");
|
SoundEvent ENTITY_PLAYER_PEGASUS_MOLT = register("entity.player.pegasus.molt");
|
||||||
SoundEvent ENTITY_PLAYER_CHANGELING_BUZZ = register("entity.player.changeling.buzz");
|
SoundEvent ENTITY_PLAYER_CHANGELING_BUZZ = register("entity.player.changeling.buzz");
|
||||||
|
|
|
@ -75,8 +75,10 @@ public class ClientInteractionManager extends InteractionManager {
|
||||||
PlayerPhysics physics = Pony.of(e).getPhysics();
|
PlayerPhysics physics = Pony.of(e).getPhysics();
|
||||||
return physics.isFlying() && physics.getFlightType() == FlightType.INSECTOID;
|
return physics.isFlying() && physics.getFlightType() == FlightType.INSECTOID;
|
||||||
}, USounds.ENTITY_PLAYER_CHANGELING_BUZZ, 1F, 1F, Random.create(seed)));
|
}, USounds.ENTITY_PLAYER_CHANGELING_BUZZ, 1F, 1F, Random.create(seed)));
|
||||||
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity) {
|
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity && isClientPlayer((PlayerEntity) source)) {
|
||||||
soundManager.play(new MotionBasedSoundInstance(SoundEvents.ITEM_ELYTRA_FLYING, (PlayerEntity)source, Random.create(seed)));
|
soundManager.play(new MotionBasedSoundInstance(SoundEvents.ITEM_ELYTRA_FLYING, (PlayerEntity)source, Random.create(seed)));
|
||||||
|
} else if (type == SOUND_GLIDING && source instanceof PlayerEntity) {
|
||||||
|
soundManager.play(new MotionBasedSoundInstance(USounds.ENTITY_PLAYER_PEGASUS_FLYING, (PlayerEntity)source, Random.create(seed)));
|
||||||
} else if (type == SOUND_MAGIC_BEAM) {
|
} else if (type == SOUND_MAGIC_BEAM) {
|
||||||
soundManager.play(new LoopedEntityTrackingSoundInstance(USounds.SPELL_CAST_SHOOT, 0.3F, 1F, source, seed));
|
soundManager.play(new LoopedEntityTrackingSoundInstance(USounds.SPELL_CAST_SHOOT, 0.3F, 1F, source, seed));
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,12 @@ public abstract class FadeOutSoundInstance extends MovingSoundInstance {
|
||||||
progress = 0;
|
progress = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setVolume(float vol){
|
||||||
|
sourceVolume = vol;
|
||||||
|
targetVolume = vol;
|
||||||
|
progress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private float getLerpedVolume() {
|
private float getLerpedVolume() {
|
||||||
float delta = MinecraftClient.getInstance().getTickDelta();
|
float delta = MinecraftClient.getInstance().getTickDelta();
|
||||||
float interpolate = MathHelper.clamp(MathHelper.lerp(delta, prevProgress, progress) / transitionTicks, 0, 1);
|
float interpolate = MathHelper.clamp(MathHelper.lerp(delta, prevProgress, progress) / transitionTicks, 0, 1);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.client.sound;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.sound.SoundEvent;
|
import net.minecraft.sound.SoundEvent;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
@ -11,18 +12,30 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
|
||||||
|
|
||||||
private final PlayerEntity player;
|
private final PlayerEntity player;
|
||||||
|
|
||||||
|
// Tune these if you want to change the way this sounds!
|
||||||
|
// Currently just hardcoded for flying because nothing else uses this class
|
||||||
|
private static final float MAX_VELOCITY = 1.5f; // Max velocity before we clamp volume (units/tick?)
|
||||||
|
private static final float VOLUME_AT_MAX = 1.0f;
|
||||||
|
private static final float ATTEN_EXPO = 2.0f; // Exponent for velocity based attenuation
|
||||||
|
private static final int FADEIN_TICKS = 20; // Ticks for fade-in
|
||||||
|
private static final float MIN_PITCH = 0.7f; // Pitch at 0-speed
|
||||||
|
private static final float MAX_PITCH = 2.6f; // Pitch at reference speed MAX_VELOCITY
|
||||||
|
private static final float MAX_RATE_TICKS = 20.0f; // How many ticks it takes to go from 0 to max volume (filter!)
|
||||||
|
|
||||||
private int tickCount;
|
private int tickCount;
|
||||||
|
private float currentVal; // Cache last tick's curve value
|
||||||
|
|
||||||
public MotionBasedSoundInstance(SoundEvent sound, PlayerEntity player, Random random) {
|
public MotionBasedSoundInstance(SoundEvent sound, PlayerEntity player, Random random) {
|
||||||
super(sound, player.getSoundCategory(), 0.1F, random);
|
super(sound, player.getSoundCategory(), 0.1F, random);
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
currentVal = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldKeepPlaying() {
|
protected boolean shouldKeepPlaying() {
|
||||||
++tickCount;
|
++tickCount;
|
||||||
|
|
||||||
if (player.isRemoved() || tickCount > 200) {
|
if (player.isRemoved()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,30 +45,41 @@ public class MotionBasedSoundInstance extends FadeOutSoundInstance {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update effect position
|
||||||
x = ((float)player.getX());
|
x = ((float)player.getX());
|
||||||
y = ((float)player.getY());
|
y = ((float)player.getY());
|
||||||
z = ((float)this.player.getZ());
|
z = ((float)player.getZ());
|
||||||
|
|
||||||
|
// Get velocity
|
||||||
float f = (float)player.getVelocity().horizontalLength();
|
float f = (float)player.getVelocity().horizontalLength();
|
||||||
|
|
||||||
|
float lastVal = currentVal;
|
||||||
|
|
||||||
|
// First we normalise the volume to the maximum velocity we're targeting, then we make it a curve.
|
||||||
|
// Drag is not linear, and neither is the woosh it produces, so a curve makes it sound more natural.
|
||||||
|
currentVal = (float) Math.pow(MathHelper.clamp(f / MAX_VELOCITY, 0, 1),ATTEN_EXPO);
|
||||||
|
|
||||||
|
// Primitive lowpass filter/rate limiter thingy to rule out sudden jolts
|
||||||
|
currentVal = lastVal + MathHelper.clamp(currentVal - lastVal, -(1/MAX_RATE_TICKS), 1/MAX_RATE_TICKS);
|
||||||
|
|
||||||
if (f >= 1.0E-7D) {
|
if (f >= 1.0E-7D) {
|
||||||
volume = MathHelper.clamp(f / 4F, 0, 1);
|
// Multiply output volume by reference volume for overall gain control.
|
||||||
|
volume = currentVal * VOLUME_AT_MAX;
|
||||||
} else {
|
} else {
|
||||||
volume = 0.0F;
|
volume = 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tickCount < 20) {
|
// If we only just started playing, fade in!
|
||||||
volume = 0;
|
if (tickCount < FADEIN_TICKS) {
|
||||||
} else if (tickCount < 40) {
|
volume *= ((tickCount) / (float)FADEIN_TICKS);
|
||||||
volume = (float)(volume * ((tickCount - 20) / 20D));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volume > 0.8F) {
|
// Control pitch with velocity
|
||||||
pitch = 1 + (volume - 0.8F);
|
pitch = MathHelper.lerp(currentVal,MIN_PITCH,MAX_PITCH);
|
||||||
} else {
|
|
||||||
pitch = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTargetVolume(volume);
|
// Setting target volume every frame breaks interpolation. We set volume directly,
|
||||||
|
// so that FadeOutSoundInstance only handles stopping the sound with an actual fade out!
|
||||||
|
setVolume(volume);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
"unicopia:woosh/woosh5"
|
"unicopia:woosh/woosh5"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"entity.player.pegasus.flying": {
|
||||||
|
"sounds": [
|
||||||
|
{
|
||||||
|
"name": "unicopia:wind/flying_loop",
|
||||||
|
"volume": 0.6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"item.magic.aura": {
|
"item.magic.aura": {
|
||||||
"category": "player",
|
"category": "player",
|
||||||
"subtitle": "unicopia.subtitle.magic_aura",
|
"subtitle": "unicopia.subtitle.magic_aura",
|
||||||
|
|
BIN
src/main/resources/assets/unicopia/sounds/wind/flying_loop.ogg
Normal file
BIN
src/main/resources/assets/unicopia/sounds/wind/flying_loop.ogg
Normal file
Binary file not shown.
Loading…
Reference in a new issue