Add comparator output, tab-completion, soundlist/soundstopall, and OpenAL low-pass occlusion/underwater filter
This commit is contained in:
@@ -58,6 +58,7 @@ import javazoom.jl.decoder.SampleBuffer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceContext;
|
||||
@@ -65,6 +66,8 @@ import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.ALC10;
|
||||
import org.lwjgl.openal.EXTEfx;
|
||||
import org.lwjgl.stb.STBVorbis;
|
||||
import org.lwjgl.stb.STBVorbisInfo;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
@@ -200,6 +203,14 @@ public final class AudioPlaybackService {
|
||||
return;
|
||||
}
|
||||
SoundDebug.log(SoundDebug.Level.L2, "PLAYBACK", sourceId, "stop source={} buffer={}", src.source, src.buffer);
|
||||
if (src.directFilter > 0) {
|
||||
try {
|
||||
AL10.alSourcei(src.source, EXTEfx.AL_DIRECT_FILTER, EXTEfx.AL_FILTER_NULL);
|
||||
EXTEfx.alDeleteFilters(src.directFilter);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
src.directFilter = 0;
|
||||
}
|
||||
AL10.alSourceStop((int)src.source);
|
||||
AL10.alDeleteSources((int)src.source);
|
||||
if (src.reverbSource > 0) {
|
||||
@@ -209,6 +220,13 @@ public final class AudioPlaybackService {
|
||||
AL10.alDeleteBuffers((int)src.buffer);
|
||||
}
|
||||
|
||||
public synchronized void stopAll() {
|
||||
ArrayList<String> all = new ArrayList<>(this.active.keySet());
|
||||
for (String id : all) {
|
||||
this.stop(id);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isPlaying(String sourceId) {
|
||||
return this.active.containsKey(sourceId);
|
||||
}
|
||||
@@ -223,6 +241,7 @@ public final class AudioPlaybackService {
|
||||
return;
|
||||
}
|
||||
Vector3d playerPos = player.position();
|
||||
boolean underwater = player.isEyeInFluid(FluidTags.WATER);
|
||||
ArrayList<String> remove = new ArrayList<String>();
|
||||
int topPriority = Integer.MIN_VALUE;
|
||||
String dominantCategory = "ambient";
|
||||
@@ -248,9 +267,13 @@ public final class AudioPlaybackService {
|
||||
float gain = this.computeAttenuatedGain(src, playerPos);
|
||||
float occlusionFactor = this.computeOcclusionFactor(src, playerPos);
|
||||
gain *= occlusionFactor;
|
||||
if (underwater) {
|
||||
gain *= 0.72f;
|
||||
}
|
||||
gain = this.applyFades(src, gain);
|
||||
gain = this.applyPriorityDucking(src, gain, topPriority, dominantCategory);
|
||||
AL10.alSourcef((int)src.source, (int)4106, (float)Math.max(0.0f, gain));
|
||||
this.updateDirectFilter(src, occlusionFactor, underwater);
|
||||
float pitch = src.settings.pitch;
|
||||
pitch *= this.computePitchModulation(src);
|
||||
if (src.settings.occlusion && src.settings.use3d && occlusionFactor < 0.999f && !"voice".equals(src.settings.category)) {
|
||||
@@ -276,6 +299,63 @@ public final class AudioPlaybackService {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean efxSupported = false;
|
||||
private static boolean efxChecked = false;
|
||||
|
||||
private static boolean isEfxSupported() {
|
||||
if (!efxChecked) {
|
||||
efxChecked = true;
|
||||
try {
|
||||
long context = ALC10.alcGetCurrentContext();
|
||||
long device = ALC10.alcGetContextsDevice(context);
|
||||
efxSupported = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX");
|
||||
} catch (Throwable t) {
|
||||
efxSupported = false;
|
||||
}
|
||||
}
|
||||
return efxSupported;
|
||||
}
|
||||
|
||||
private void updateDirectFilter(PlayingSource src, float occlusionFactor, boolean underwater) {
|
||||
if (!isEfxSupported()) {
|
||||
return;
|
||||
}
|
||||
boolean needFilter = (src.settings.occlusion && src.settings.use3d && occlusionFactor < 0.999f) || underwater;
|
||||
if (!needFilter) {
|
||||
if (src.directFilter > 0) {
|
||||
try {
|
||||
AL10.alSourcei(src.source, EXTEfx.AL_DIRECT_FILTER, EXTEfx.AL_FILTER_NULL);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (src.directFilter <= 0) {
|
||||
src.directFilter = EXTEfx.alGenFilters();
|
||||
if (src.directFilter > 0) {
|
||||
EXTEfx.alFilteri(src.directFilter, EXTEfx.AL_FILTER_TYPE, EXTEfx.AL_FILTER_LOWPASS);
|
||||
}
|
||||
}
|
||||
if (src.directFilter > 0) {
|
||||
float gainHF = 1.0f;
|
||||
float gainLF = 1.0f;
|
||||
if (src.settings.occlusion && src.settings.use3d && occlusionFactor < 0.999f) {
|
||||
float str = Math.max(0.0f, Math.min(1.0f, src.settings.occlusionStrength));
|
||||
gainHF = Math.max(0.08f, 1.0f - str * 0.82f);
|
||||
}
|
||||
if (underwater) {
|
||||
gainHF *= 0.18f;
|
||||
gainLF *= 0.75f;
|
||||
}
|
||||
EXTEfx.alFilterf(src.directFilter, EXTEfx.AL_LOWPASS_GAIN, gainLF);
|
||||
EXTEfx.alFilterf(src.directFilter, EXTEfx.AL_LOWPASS_GAINHF, gainHF);
|
||||
AL10.alSourcei(src.source, EXTEfx.AL_DIRECT_FILTER, src.directFilter);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private float computePitchModulation(PlayingSource src) {
|
||||
if (src.settings.pitchMode == null || src.settings.pitchMode == PitchModulationMode.STATIC) {
|
||||
return 1.0f;
|
||||
@@ -653,6 +733,7 @@ public final class AudioPlaybackService {
|
||||
int fadeOutTicks;
|
||||
int reverbSource;
|
||||
int elapsedTicks;
|
||||
int directFilter;
|
||||
long lastLiveUpdateTick = Long.MIN_VALUE;
|
||||
|
||||
PlayingSource(String sourceId, int source, int buffer, BlockPos pos, SoundSettings settings, long startedAtTick) {
|
||||
|
||||
Reference in New Issue
Block a user