Skip to content

Commit

Permalink
Finished variable slot count
Browse files Browse the repository at this point in the history
Finished Variable slot count, the first major feature unique to Resounding!
This can be thought of as the reverb "resolution", higher slot counts mean smoother reverb and more detail, but at the cost of memory and performance
This setting can be changed with the `reverbResolution` setting in the config
Also:
 - updated config. This will work until i can get around to a full rewrite
 - rewrote `dev.thedocruby.resounding.openal.*`, since i needed to to get the variable slot count working.
 - fixed a critical error with material properties inherited from Sound Physics that forced all materials to use fallback values. Material properties should now be applied correctly
 - fixed a bug from the last commit that prevented the mod from updating properly when the config was changed
 - Improved the reverb quality by no longer hard-coding some things, like reverb diffusion. Most of these are also now configurable
 - a few more minor things
  • Loading branch information
thedocruby committed Feb 2, 2022
1 parent ffb5117 commit 618830a
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 434 deletions.
248 changes: 148 additions & 100 deletions src/main/java/dev/thedocruby/resounding/Resounding.java

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/main/java/dev/thedocruby/resounding/ResoundingLog.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ public class ResoundingLog {

private ResoundingLog() {}

public static void checkErrorLog(final String errorMessage) {
public static boolean checkErrorLog(final String errorMessage) {
final int error = AL10.alGetError();
if (error == AL10.AL_NO_ERROR) {
return;
return false;
}

String errorName;
Expand All @@ -27,6 +27,7 @@ public static void checkErrorLog(final String errorMessage) {
};

Resounding.LOGGER.error(errorMessage + " Caused by: OpenAL \"" + errorName + "\" error.");
return true;
}

}
44 changes: 0 additions & 44 deletions src/main/java/dev/thedocruby/resounding/ResoundingModClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,6 @@ public class ResoundingModClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
Resounding.env = EnvType.CLIENT;
Resounding.blockSoundGroups = Arrays.stream(BlockSoundGroup.class.getDeclaredFields())
.filter((f) -> {
try {
return Modifier.isStatic(f.getModifiers()) && Modifier.isPublic(f.getModifiers())
&& (f.get(null) instanceof BlockSoundGroup group) && !Resounding.redirectMap.containsKey(group);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
})
.collect(Collectors.toMap(
(f) -> {
try {
return (BlockSoundGroup)f.get(null);
} catch (IllegalAccessException | ClassCastException e) {
e.printStackTrace();
}
return null;
},
(f) -> {
try {
return new Pair<>(f.getName(), (f.get(null) instanceof BlockSoundGroup g ? (Resounding.groupMap.containsKey(f.getName()) ? Resounding.groupMap.get(f.getName()) : g.getBreakSound().getId().getPath().split("\\.")[1] ): "not a group"));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return new Pair<>("", "");
}));
Resounding.groupSoundBlocks = Arrays.stream(BlockSoundGroup.class.getDeclaredFields())
.filter((f) -> {
try {
return Modifier.isStatic(f.getModifiers()) && Modifier.isPublic(f.getModifiers())
&& (f.get(null) instanceof BlockSoundGroup group) && !Resounding.redirectMap.containsKey(group);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}).map((f)-> {
BlockSoundGroup b;
try { b = (BlockSoundGroup)f.get(null); }
catch (IllegalAccessException | ClassCastException e) { e.printStackTrace(); b = null;}
return new Pair<>(f.getName(),b);
}).filter((f) -> f.getRight() != null)
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));

ConfigManager.registerAutoConfig();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import dev.thedocruby.resounding.config.PrecomputedConfig;
import dev.thedocruby.resounding.config.ResoundingConfig;
import dev.thedocruby.resounding.config.presets.ConfigPresets;
import dev.thedocruby.resounding.openal.ResoundingEFX;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigHolder;
import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer;
Expand All @@ -23,12 +24,13 @@ private ConfigManager() {}

private static ConfigHolder<ResoundingConfig> holder;

public static String configVersion = "1.0.0-alpha.2";

@Environment(EnvType.CLIENT)
public static final ResoundingConfig DEFAULT = Resounding.env == EnvType.CLIENT ? new ResoundingConfig(){{
Map<String, MaterialData> map =
Resounding.blockSoundGroups.entrySet().stream()
.collect(Collectors.toMap((e)-> e.getValue().getLeft(), (e) -> new MaterialData(e.getValue().getRight(), 0.5, 0.5)));
map.putIfAbsent("DEFAULT", new MaterialData(Resounding.groupMap.get("DEFAULT"), 0.5, 0.5));
Map<String, MaterialData> map = Resounding.nameToGroup.keySet().stream()
.collect(Collectors.toMap(e -> e, e -> new MaterialData(e, 0.5, 0.5)));
map.putIfAbsent("DEFAULT", new MaterialData("DEFAULT", 0.5, 0.5));
Materials.materialProperties = map;
}} : null;

Expand Down Expand Up @@ -73,17 +75,18 @@ public static void handleUnstableConfig( ResoundingConfig c ){
Resounding.LOGGER.error("Error: Config file is not from a compatible version! Resetting the config...");
ConfigPresets.DEFAULT_PERFORMANCE.configChanger.accept(c);
ConfigPresets.RESET_MATERIALS.configChanger.accept(c);
c.version = "1.0.0-alpha.1";
c.version = configVersion;
}

public static ActionResult onSave(ResoundingConfig c) {
if (Resounding.env == EnvType.CLIENT && (c.Materials.materialProperties == null || c.Materials.materialProperties.get("DEFAULT") == null)) handleBrokenMaterials(c);
if (Resounding.env == EnvType.CLIENT && c.preset != ConfigPresets.LOAD_SUCCESS) c.preset.configChanger.accept(c);
if (c.version == null || !Objects.equals(c.version, "1.0.0-alpha.1")) handleUnstableConfig(c);
if (c.version == null || !Objects.equals(c.version, configVersion)) handleUnstableConfig(c);
if (PrecomputedConfig.pC != null) PrecomputedConfig.pC.deactivate();
try {PrecomputedConfig.pC = new PrecomputedConfig(c);} catch (CloneNotSupportedException e) {e.printStackTrace(); return ActionResult.FAIL;}
if (Resounding.env == EnvType.CLIENT) {
Resounding.updateRays();
ResoundingEFX.initEAXReverb();
}
return ActionResult.SUCCESS;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.thedocruby.resounding.config;

import dev.thedocruby.resounding.Resounding;
import dev.thedocruby.resounding.ResoundingLog;
import it.unimi.dsi.fastutil.objects.Reference2DoubleOpenHashMap;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
Expand All @@ -11,6 +10,8 @@
import java.util.*;
import java.util.stream.Collectors;

import static dev.thedocruby.resounding.Resounding.nameToGroup;

/*
Values, which remain constant after the config has changed
Only one instance allowed
Expand All @@ -25,8 +26,13 @@ public class PrecomputedConfig {
public final boolean off;

public final float globalReverbGain;
public final double minEnergy;
public final int resolution;
public final double warpFactor;
public final float globalReverbBrightness;
public final double reverbCondensationFactor;
public final double globalBlockAbsorption;
public final double globalAbsorptionBrightness;
public final double globalBlockReflectance;
public final double globalReflRcp;
public final float airAbsorption;
Expand All @@ -45,6 +51,8 @@ public class PrecomputedConfig {
@Environment(EnvType.CLIENT)
public double rcpTotRays;
@Environment(EnvType.CLIENT)
public double maxDistance;
@Environment(EnvType.CLIENT)
public boolean simplerSharedAirspaceSimulation;

@Environment(EnvType.CLIENT)
Expand Down Expand Up @@ -81,25 +89,22 @@ public class PrecomputedConfig {
public final boolean pLog;
public final boolean dRays;

public final int resolution;
public final double warpFactor;
public final double globalAbsorptionBrightness;
public final double maxDecayTime;
public final int traceRange;
public final double minEnergy;
public final double maxDistance;

private boolean active = true;

public PrecomputedConfig(ResoundingConfig c) throws CloneNotSupportedException {
if (pC != null && pC.active) throw new CloneNotSupportedException("Tried creating second instance of precomputedConfig");
off = !c.enabled;

defaultAttenuationFactor = c.General.attenuationFactor;
globalReverbGain = (float) (1 / c.General.globalReverbGain);
globalReverbGain = (float) c.General.globalReverbGain;
minEnergy = Math.exp(-1 * c.General.globalReverbStrength);
resolution = c.General.reverbResolution;
warpFactor = c.General.reverbWarpFactor;
globalReverbBrightness = (float) c.General.globalReverbBrightness;
reverbCondensationFactor = 1 - c.General.globalReverbSmoothness;
globalBlockAbsorption = c.General.globalBlockAbsorption;
soundDistanceAllowance = c.General.soundDistanceAllowance;
globalAbsorptionBrightness = c.General.globalAbsorptionBrightness;
soundDistanceAllowance = c.General.soundDistanceAllowance; // TODO: Refactor to sound render distance
globalBlockReflectance = c.General.globalBlockReflectance;
globalReflRcp = 1 / globalBlockReflectance;
airAbsorption = (float) c.General.airAbsorption;
Expand All @@ -113,6 +118,7 @@ public PrecomputedConfig(ResoundingConfig c) throws CloneNotSupportedException {
rcpNRays = 1d / nRays;
nRayBounces = c.Performance.environmentEvaluationRayBounces;
rcpTotRays = rcpNRays / nRayBounces;
maxDistance = c.Performance.traceRange * nRayBounces * Math.sqrt(2 * (16*16)) * 2;
simplerSharedAirspaceSimulation = c.Performance.simplerSharedAirspaceSimulation;

blockWhiteSet = new HashSet<>(c.Materials.blockWhiteList);
Expand All @@ -133,13 +139,13 @@ public PrecomputedConfig(ResoundingConfig c) throws CloneNotSupportedException {
absorptionMap = new Reference2DoubleOpenHashMap<>();
final List<String> wrong = new java.util.ArrayList<>();
final List<String> toRemove = new java.util.ArrayList<>();
c.Materials.materialProperties.forEach((k, v) -> {
BlockSoundGroup bsg = Resounding.groupSoundBlocks.get(k);
if (bsg != null) {
c.Materials.materialProperties.forEach((k, v) -> { //TODO Materials need to be reworked.
if (nameToGroup.containsKey(k)) {
BlockSoundGroup bsg = nameToGroup.get(k);
reflectivityMap.put(bsg, v.reflectivity);
absorptionMap.put(bsg, v.absorption * 2);
absorptionMap.put(bsg, v.absorption);
} else {
if (!k.equals("DEFAULT") && !blockWhiteSet.contains(k)) {
if (!blockWhiteSet.contains(k) && !k.equals("DEFAULT")) {
wrong.add(k + " (" + v.example + ")");
toRemove.add(k);
}
Expand All @@ -150,28 +156,20 @@ public PrecomputedConfig(ResoundingConfig c) throws CloneNotSupportedException {
toRemove.forEach(c.Materials.materialProperties::remove);
}

recordsDisable = c.Vlads_Tweaks.recordsDisable;
continuousRefreshRate = c.Vlads_Tweaks.continuousRefreshRate;
maxDirectOcclusionFromBlocks = c.Vlads_Tweaks.maxDirectOcclusionFromBlocks;
_9Ray = c.Vlads_Tweaks._9RayDirectOcclusion;
soundDirectionEvaluation = c.Vlads_Tweaks.soundDirectionEvaluation;
directRaysDirEvalMultiplier = Math.pow(c.Vlads_Tweaks.directRaysDirEvalMultiplier, 10.66);
notOccludedRedirect = !c.Vlads_Tweaks.notOccludedNoRedirect;
recordsDisable = c.Misc.recordsDisable;
continuousRefreshRate = c.Misc.continuousRefreshRate;
maxDirectOcclusionFromBlocks = c.Misc.maxDirectOcclusionFromBlocks;
_9Ray = c.Misc._9RayDirectOcclusion;
soundDirectionEvaluation = c.Misc.soundDirectionEvaluation; // TODO: DirEval
directRaysDirEvalMultiplier = Math.pow(c.Misc.directRaysDirEvalMultiplier, 10.66); // TODO: DirEval
notOccludedRedirect = !c.Misc.notOccludedNoRedirect;
}

dLog = c.Misc.debugLogging;
oLog = c.Misc.occlusionLogging;
eLog = c.Misc.environmentLogging;
pLog = c.Misc.performanceLogging;
dRays = c.Misc.raytraceParticles;

resolution = 4;
warpFactor = 4;
globalAbsorptionBrightness = 1d / 1d;
maxDecayTime = Math.min(20, 4.142);
traceRange = 256;
minEnergy = Math.exp(-1 * c.Misc.minEnergy);
maxDistance = traceRange * nRayBounces;
dLog = c.Debug.debugLogging;
oLog = c.Debug.occlusionLogging;
eLog = c.Debug.environmentLogging;
pLog = c.Debug.performanceLogging;
dRays = c.Debug.raytraceParticles;
}

public void deactivate(){ active = false;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.List;
import java.util.Map;

import static dev.thedocruby.resounding.config.BlueTapePack.ConfigManager.configVersion;

@SuppressWarnings("CanBeFinal")
@Config(name = "resounding")
@Config.Gui.Background("minecraft:textures/block/note_block.png")
Expand All @@ -32,20 +34,30 @@ public class ResoundingConfig implements ConfigData {
public Materials Materials = new Materials();

@ConfigEntry.Gui.CollapsibleObject
public Vlads_Tweaks Vlads_Tweaks = new Vlads_Tweaks();
public ResoundingConfig.Misc Misc = new Misc();

@ConfigEntry.Gui.CollapsibleObject
public Misc Misc = new Misc();
public Debug Debug = new Debug();

public static class General{
@ConfigEntry.Gui.Excluded // TODO: remove this
@Comment("Affects how quiet a sound gets based on distance. Lower values mean distant sounds are louder.\n1.0 is the physically correct value.\n0.2 - 1.0 or just don't set it to 0")
public double attenuationFactor = 1.0;
@ConfigEntry.Gui.Excluded // TODO: remove this
@Comment("The global volume of simulated reverberations.\n0.1 - 2.0")
public double globalReverbGain = 1.0;
@ConfigEntry.BoundedDiscrete(max = 32, min = 4)
public int reverbResolution = 12;
public double globalReverbStrength = 5.0;
public double reverbWarpFactor = 4;
public double globalReverbSmoothness = 0.62;
@Comment("The brightness of reverberation.\nHigher values result in more high frequencies in reverberation.\nLower values give a more muffled sound to the reverb.\n0.1 - 2.0")
public double globalReverbBrightness = 1.0;
@ConfigEntry.Gui.Excluded // TODO: Occlusion
@Comment("The global amount of sound that will be absorbed when traveling through blocks.\n 0.1 - 4.0")
public double globalBlockAbsorption = 1.0;
@ConfigEntry.Gui.Excluded // TODO: Occlusion
public double globalAbsorptionBrightness = 1.0;
@Comment("The global amount of sound reflectance energy of all blocks.\nLower values result in more conservative reverb simulation with shorter reverb tails.\nHigher values result in more generous reverb simulation with higher reverb tails.\n0.1 - 4.0")
public double globalBlockReflectance = 1.0;
@Comment("Minecraft won't allow sounds to play past a certain distance;\nResounding makes that configurable by multiplying this parameter by the default distance.\nValues too high can cause polyphony issues.\n1.0 - 6.0")
Expand All @@ -62,6 +74,7 @@ public static class General{

public static class Performance{
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: Occlusion
@Comment("If true, rain sound sources won't trace for sound occlusion.\nThis can help performance during rain.")
public boolean skipRainOcclusionTracing = true;
@Environment(EnvType.CLIENT)
Expand All @@ -73,6 +86,9 @@ public static class Performance{
@ConfigEntry.BoundedDiscrete(max = 32, min = 2)
public int environmentEvaluationRayBounces = 12;
@Environment(EnvType.CLIENT)
public double traceRange = 6;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: Remove
@Comment("If true, enables a simpler technique for determining when the player and a sound source share airspace.\nMight sometimes miss recognizing shared airspace, but it's faster to calculate.")
public boolean simplerSharedAirspaceSimulation = false;
}
Expand All @@ -87,33 +103,39 @@ public static class Materials {
public List<String> blockWhiteList = new ArrayList<>();
}

public static class Vlads_Tweaks {
public static class Misc {
@Environment(EnvType.CLIENT)
@Comment("Disable occlusion of jukeboxes and note blocks.\nUseful if you have an audio signaling system that you need to hear clearly")
public boolean recordsDisable = false;
@Environment(EnvType.CLIENT)
@Comment("Continuous sources reverb refresh interval (ticks per refresh or 1/(20Hz))")
public int continuousRefreshRate = 4;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: Occlusion
@Comment("The amount at which occlusion is capped. 10 * block_occlusion is the theoretical limit")
public double maxDirectOcclusionFromBlocks = 10;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: Occlusion
@Comment("Calculate direct occlusion as the minimum of 9 rays from vertices of a block")
public boolean _9RayDirectOcclusion = true;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: DirEval
@Comment("Whether to try calculating where the sound should come from based on reflections")
public boolean soundDirectionEvaluation = true;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: DirEval
@Comment("How much the sound direction depends on reflected sounds.\nRequires \"Re-calculate sound direction\" to be enabled.\n0.0 is no reflected sounds, 1.0 is 100% reflected sounds.\n0.5 is approximately physically accurate.")
public double directRaysDirEvalMultiplier = 0.5;
@Environment(EnvType.CLIENT)
@ConfigEntry.Gui.Excluded // TODO: DirEval, Occlusion
@Comment("Skip redirecting non-occluded sounds (the ones you can see directly).\nCan be inaccurate in some situations, especially when \"Re-calculate sound direction\" is enabled.")
public boolean notOccludedNoRedirect = false;
}

public static class Misc {
public static class Debug {
@Comment("General debug logging")
public boolean debugLogging = false;
@ConfigEntry.Gui.Excluded // TODO: Occlusion
@Comment("Occlusion tracing information logging")
public boolean occlusionLogging = false;
@Comment("Environment evaluation information logging")
Expand All @@ -122,14 +144,13 @@ public static class Misc {
public boolean performanceLogging = false;
@Comment("Particles on traced blocks (structure_void is a block)")
public boolean raytraceParticles = false;
public double minEnergy = 5;
}

// TODO: change preset back to "Balanced" when performance permits
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.DROPDOWN)
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
@Comment("Soft presets. Some of these can be applied one after another to stack effects onto a base profile.")
public ConfigPresets preset = ConfigPresets.DEFAULT_PERFORMANCE;

@ConfigEntry.Gui.Excluded
public String version = "1.0.0-alpha.1";
public String version = configVersion;
}
Loading

0 comments on commit 618830a

Please sign in to comment.