Links
Tags
Creators
Details
Licensed LGPL-3.0-or-later
Published 5 months ago
Updated 5 months ago
All versions
4.0.0-alpha
Alpha
AudioEnginePlus 4.0-alpha5 months ago 350
Compatibility
Minecraft: Java Edition
1.21.1–1.21.11
Platform
Fabric
Supported environments
Client-side
Changes
v4.0 Alpha — Weather Audio, Occlusion Polish & Stability
✨ New
- Weather-safe streaming —
MemoryAudioStreamloops PCM when the buffer ends instead of returningnull(avoids OpenAL reload overlap) - Continuous ambient bypass —
AsyncStreamer.isContinuousAmbientStream()keeps rain, weather, and cave ambients on vanillaOggAudioStream(no Phase 5 PCM cache for those paths) - Occlusion 2.1 — provisional cache + async refine; player-centric raycasting (
phase4.playerCentricRaycasting, default on); smoothed gain viaOcclusionState/writeSmoothedGain - LOOP_FAR priority — distant ambient/weather loops (>32 blocks) use
SourcePriority.LOOP_FARwith sharedmaxAmbientSourcesbudget - Reload generation guards —
reloadGenerationonSoundPreloader,AsyncStreamer, andSoundReloadListenerso in-flight preloads/decode do not write after resource reload - OcclusionApi —
getOcclusionFromProvider()hook for external occlusion mods/providers - Cloth Config lang —
en_us.jsontooltip for deprecatedasyncWorkerThreads
⚡ Performance
- PCM replay — seamless loop for cached stream segments; fewer redundant OGG decodes on short repeatable streams
- Occlusion tick — invalidates stale pending futures when source/listener block moves; sync fallback before async refine; normalized cache path for player-centric mode
- OcclusionCache — tick-based TTL retained; provisional entries reduce “silent until ray completes” gaps
- Smart pool — deferred eviction queue (
aep$deferredEvictions);getEffectiveCount()/ pending-eviction accounting; position tracking with 0.01-block epsilon - Dedup — greedy centroid clustering retained; weather path exempt so global loops are not merged/delayed
- LOD —
LodPcmGeneratorLanczos resampler (anti-alias) replaces box filter; correct native byte-order onByteBuffer.duplicate()(fixes distant mob LOD crackle) - Preload — direct-memory headroom checks and generation-stamped async work in
SoundPreloader - Phase 3 — async tick work stays sync on render thread (~μs per sound);
asyncWorkerThreadsmarked unused in config
🔧 Changes
- Updated:
gradle.properties/ docs — release line 3.0-alpha → 4.0-alpha - Updated:
SoundEngineMixinPhase4— occlusion apply order; category scaling after occlusion; WEATHER and relative sounds skip occlusion processing - Updated:
SoundDeduplicator—weatheradded to dedup-exempt patterns (with block interaction sounds) - Updated:
SoundReloadListener— coordinated cache clear: PCM, session static, LOD, occlusion state, dedup/pool,AsyncStreamer.reset() - Updated:
SoundPhysicsRemasteredCompat— runtime occlusion disable when SPR is present (unchanged behavior, refined checks) - Unchanged from 3.0:
StreamingBufferQueuestill not wired;SoundInstancePoolstill removed; Caffeine still absent
🐛 Fixes
- Duplicate rain / weather layer — second rain heard while moving or standing (PCM stream end → reload overlap + occlusion gain on listener-bound loops)
- Shared
OggAudioStreamcorruption — per-playMemoryAudioStreamwith independent cursor (carried from 3.0; loop rewind completes the fix for repeatable streams) - LOD crackle on distant sounds — wrong endian on duplicated PCM views in
LodPcmGenerator - Stale occlusion after movement — cancel pending futures and refresh cache when source/listener block changes
- Dedup replay —
MergedSoundInstancenever re-deferred; key counts cleared on flush - Resource reload races — blacklist pattern swap, native buffer ownership, and in-flight preload abandonment
- Smart pool double-register — merged sounds only registered via
play()injection path
⚠️ Known limitations (alpha)
StreamingBufferQueue— implemented but not connected toSoundLoader; true decode-while-playing pipeline is future work- Weather PCM cache — if manually cached via blacklist/config edge cases, prefer vanilla path; continuous ambients are excluded by default
- No automated tests — heavy farms/PvP may need lower
globalRayBudgetPerTick,dedupThreshold, or category limits in Phase 1 - Phase 5 static path —
enableStaticCachingstill limited bystaticCacheThresholdBytes; long streamed ambients should stay on OGG
📦 Upgrade from 3.0-alpha
| If you had… | In 4.0… |
|---|---|
| Rain/weather “ghost” audio | Fixed by default (no config toggle required) |
| Distant mob LOD noise | Improved resampler + byte-order fix |
| Occlusion pumping while walking | Reduced; weather/relative loops excluded |
Same phase5 / phase4 config keys |
Compatible; new: playerCentricRaycasting |
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:NkAfJVb8:9q9mlIWY"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:NkAfJVb8:9q9mlIWY"
}

