GregOrigin - Sonant: Native Contextual Audio Middleware

Watch the promo video.

Read the GitBook docs.

STOP EDITING PROJECT SETTINGS.

Standard Unreal Engine audio implementation is a workflow bottleneck. To get basic footsteps, you have to define dozens of Physical Materials, assign them to every Material Instance, and build complex "Switch on Enum" graphs. To handle ambiance, you have to build elaborate Blueprint logic to detect when a player enters a Cave inside a Forest without breaking the mix.

MEET SONANT.

Sonant is a high-performance Gameplay Audio Manager that treats audio as Logic, not just Content. It runs entirely as a native Game Instance Subsystem.

CORE FEATURES:

1. INTELLIGENT SURFACE DETECTION (The "Zero-Config" Engine)
Sonant "reads" your specific context. Instead of relying solely on Physical Materials, Sonant scans the distinct name of the Material Interface (e.g., M_Temple_Stone_Wet) and matches it against a keyword registry you define.

  • The Workflow: Map the keyword "Stone" to your Stone Sound Pack once. Now, every material in your project with "Stone" in the name works instantly.

  • The Performance: Surface resolution is cached at runtime. The string search runs only once per material asset. Every subsequent footstep is a generic

    O(1) pointer lookup.

2. PRIORITY-BASED ATMOSPHERES (The "Wwise-Lite" Mixer)
Solved: The "Cave inside a Forest" problem.
Sonant replaces standard Sound Mix Modifiers with a Weighted Priority Stack.

  • Tag your volumes (e.g., Indoor, Underwater, Combat).

  • Assign a Priority Integer to each tag in the Config.

  • Sonant automatically calculates the highest-priority active tag and blends the correct Audio Modulation Control Bus instantly. No visual scripting required.

3. NATIVE C++ PERFORMANCE
Your game thread is precious. Sonant adds zero components to your Character. It contains no ticking actors. All logic is event-driven via the C++ Subsystem.

4. METASOUND READY
Fully compatible with UE 5.7+ MetaSounds. Drive procedural footsteps (walk vs. run) by plugging a MetaSoundSource directly into the Sonant registry.

Sonant Changelog

2026-03-11

🚀 Major Architectural Upgrades

  • Massive Performance Overhaul: Refactored the core USonantSubsystem to completely eliminate Game Thread synchronous loading hitches. The TSoftObjectPtr configuration is now loaded exactly once during Initialize() and cached as a hard TObjectPtr, dropping per-frame/per-hit lookup times down to pure O(1) memory access.
  • Amortized Raycasting (Auto-Reverb): Completely rewrote the UpdateReverb logic. Instead of firing 6 expensive, synchronous physical line traces in a single tick to calculate room volume, Sonant now amortizes the traces by performing exactly 1 trace per interval, drastically reducing CPU spikes while maintaining fluid, real-time spatial awareness.
  • Multiplayer & Networking Component: Introduced USonantNetworkComponent. Developers can now drop this replication helper onto their Pawns or Weapons to instantly gain standard Server and NetMulticast RPC wrappers for both Footsteps and Impacts, fully resolving the prior local-only subsystem limitation.
  • True BSP Volume Support: Introduced ASonantBSPVolume. Level Designers are no longer restricted to using primitive UBoxComponent shapes for ambient zones. They can now use standard Unreal Engine BSP brush tools to map complex, non-rectangular acoustic atmospheres (e.g., winding caves, angled corridors).

✨ New Features & API Enhancements

  • Generic Impact Intensity API: Added PlayImpactByIntensity(Location, Intensity). This allows developers who don't use standard Unreal Physics (e.g., custom kinematic controllers or line-trace weapons) to trigger dynamic impact audio simply by passing a normalized float (0.0 to 1.0), decoupling the audio engine from rigid physics mass requirements.
  • Configurable Gameplay Tags: Removed all hardcoded internal C++ strings. The base routing tags for events (e.g., Sonant.Event.Footstep, Sonant.Event.Impact.Heavy) are now fully exposed in the Project Settings via USonantSettings, allowing developers complete control over their tag hierarchies without touching source code.
  • Spectator / Free-Cam Reverb: Upgraded Auto-Reverb tracing to intelligently query GetViewTarget() before falling back to GetPawn(). Cinematic cameras, unpossessed vehicles, and free-cam spectators will now calculate correct spatial audio.

đź›  Demo & Onboarding Improvements

  • "Acoustics Laboratory" Showcase: Completely scrapped and rewrote SonantFeatureDemo. It is now an interactive 4-wing lab that perfectly spaces out and visually explains:
    • North Wing: Material Walkway (Footstep testing).
    • East Wing: Dynamic Reverb Chambers (Closet, Hall, Cavern volumes).
    • South Wing: Physics Impact Arena (Live simulation pit).
    • West Wing: Atmosphere Tag Volumes (Overlapping nested state visualization).

⚙️ Build & Compliance

  • Unreal Engine 5.6 Compatibility: Fixed a backwards-compatibility bug regarding EPhysicalSurface missing from ChaosEngineInterface.h in older engine builds.

:speaker_high_volume: Sonant Changelog

[0.2.0] - 2026-05-17

:sparkles: New Features

  • Setup Wizard (FTUE) :rocket:
    • Introduced a new Editor-only module (SonantEditor).
    • Added a native Slate window accessible via Window > Sonant > Sonant Setup & Scanner.
    • 1-Click Initialization: Automatically creates the default USonantConfig DataAsset, populates it with 8 industry-standard starter keywords (Wood, Metal, Stone, etc.), and assigns it directly to your Project Settings.
  • Smart Material Scanner :magnifying_glass_tilted_left:
    • Integrated into the Setup Wizard.
    • Automatically scans the /Game directory for UMaterialInterface assets.
    • Matches material naming conventions against common archetypes and auto-registers missing keywords into your active Sonant Config, eliminating manual data entry.
  • Visual Debugger :bug:
    • Added a new Cheat Console Variable: Sonant.Debug 1.
    • Reverb Trace Visualization: Draws real-time green debugging lines showing the 6-way amortized raycast used for Auto-Reverb estimation, alongside an on-screen readout of the calculated Room Radius and active Mix.
    • Acoustic Occlusion & Impact Data: Draws a sphere at sound impact sites (Cyan for clear, Red for occluded) and prints an on-screen log detailing the exact GameplayTag triggered, occlusion status, Volume, and Pitch.

:artist_palette: UI / UX Improvements

  • Stylized Editor Interface :milky_way:
    • Overhauled the Sonant Setup window with a premium “Audio Orchestrator” aesthetic.
    • Features a dark space-blue palette (#050D1E), glowing Cyan (#00CCFF) typography, and a custom drop-shadow.
    • Implemented structured, numbered blocks (“01”, “02”) for a clean, modern user onboarding flow.

:hammer_and_wrench: Architecture

  • Module Split: Separated Editor-only UI tools into the new SonantEditor module to ensure they are cleanly stripped from packaged runtime builds.

0.3.0 update, 2026-06-05 :headphone:

:wrench: Runtime Source Changes

  • :label: Added native built-in Sonant gameplay tags:
    • Plugins/Sonant/Source/Sonant/Public/SonantNativeTags.h
    • Plugins/Sonant/Source/Sonant/Private/SonantNativeTags.cpp
  • :puzzle_piece: Updated USonantSettings defaults to use native tag objects instead of FGameplayTag::RequestGameplayTag(...).
  • :hiking_boot: Updated footstep and impact fallback logic to use native tags when settings are missing or invalid.
  • :ocean: Updated demo atmosphere zones to use native atmosphere tags directly.
  • :brick: Removed hard-coded sample-project asset dependency from SonantDemoGameMode.
    • The plugin now defaults to ASonantDemoCharacter::StaticClass().
    • It no longer hard-loads /Game/ThirdPerson/... assets.
  • :hammer_and_wrench: Added missing Engine/Engine.h include in SonantSubsystem.cpp for clean plugin packaging.

:label: Gameplay Tag Config Changes

  • :white_check_mark: Added plugin-distributed tag config:
    • Plugins/Sonant/Config/Tags/SonantTags.ini
  • :white_check_mark: Added project gameplay tag entries:
    • Config/DefaultGameplayTags.ini
  • :compass: Tags covered:
    • Sonant
    • Sonant.Event.Footstep
    • Sonant.Event.Impact
    • Sonant.Event.Impact.Light
    • Sonant.Event.Impact.Heavy
    • Sonant.Atmosphere
    • Sonant.Atmosphere.Outdoor
    • Sonant.Atmosphere.Cave
    • Sonant.Atmosphere.Underwater

0.3.0a update, 2026-06-10

:building_construction: Architecture

  • Dedicated Demo Module :puzzle_piece:
    • Moved all demo/showcase classes (SonantDemoCharacter, SonantDemoGameMode, SonantDemoGenerator, SonantFeatureDemo, SonantAutoShowcase, SonantSpectacle, SonantGodRayShowcase) out of the core Sonant runtime module into a new dedicated SonantDemo runtime module.
    • The core middleware module is now lean (only the shippable runtime). The demo still ships and can be disabled per-project.
    • Added CoreRedirects in Config/DefaultEngine.ini so existing level/Blueprint references to the relocated classes resolve to /Script/SonantDemo.*.

:bug: Fixes & Hardening

  • Surface Cache :card_index_dividers:
    • Re-keyed the material → surface cache by FObjectKey to eliminate dangling/recycled material-pointer false hits, and it now invalidates when the active config changes.
  • Multiplayer :globe_with_meridians:
    • Fixed footsteps/impacts playing twice on the initiating client (USonantNetworkComponent). The client predicts locally once and the NetMulticast now skips the autonomous proxy.
  • GC Safety :recycling_symbol:
    • Converted stray raw pointers in the showcase actors to UPROPERTY/TObjectPtr (and FHitFlash/FPulsingWall to USTRUCT), preventing use-after-free when spawned actors/materials are recycled.
  • Subsystem :shield:
    • Null-guarded GetLocalPlayer() in UpdateReverb and PlaySoundAtLocation.

:video_game: Demo

  • Self-Contained Input :keyboard:
    • SonantDemoCharacter now binds WASD / mouse-look / action keys directly, so the demo runs with no project input mappings (no Enhanced Input or DefaultInput.ini setup required).
  • Cleanup :broom:
    • Removed a hard-coded /Game/M_Sonant_Demo material reference; the demo relies only on engine content.
    • Moved demo logging from LogTemp to a dedicated LogSonantDemo category.

0.3.1 update, 2026-06-11 :musical_score:

:hammer_and_wrench: Core Bug Fixes

  • Editor Crash Resolution: Fixed a critical Editor crash during garbage collection by refactoring the SmartCache in USonantSubsystem to use FObjectKey and FString values instead of raw pointers.
  • Atmosphere Stack Leak: Patched a stack leak in USonantVolume by validating that overlapping components match the Pawn’s Root Component, preventing duplicate atmosphere pushes from overlapping child colliders (like weapon meshes).
  • Material Lookup Bandwidth Bug: Decoupled RPCs in SonantNetworkComponent from sending the full FHitResult to the server. The client now passes lightweight data (FVector and Intensity) to PlayImpactByIntensity, drastically saving bandwidth and preventing mismatched server-side physical material lookups.
  • Multi-Listener Spline Audio Fix: Fixed a logic flaw in USonantSplineAudioComponent that clamped distances to the server’s local camera. It now accurately computes distance dynamically based on the local player’s view target, enabling multiplayer support.
  • Performance Optimization: Changed TSoftObjectPtr in the PhysicsMap back to TObjectPtr<UPhysicalMaterial> after identifying that async loading inside synchronous trace loops was causing micro-stutters.
  • Atmosphere State Corruption Fix: Prevented state corruption where leaving a volume sometimes failed to revert the audio mix. The system now accurately caches and restores the CurrentAppliedMixAsset.

:rocket: Setup Wizard & Workflow Enhancements

  • Memory-Safe Config Loading: The Setup Wizard now safely uses LoadObject instead of FindObject, ensuring that previously created Config assets on disk aren’t accidentally overwritten or broken if they aren’t resident in memory.
  • Automated Physics Mapping: The Smart Scanner now automatically searches the Asset Registry for UPhysicalMaterial assets across the /Game/ directory and pre-populates the PhysicsMap seamlessly.
  • Dynamic Keyword Discovery: Implemented a string-parsing fallback in the Smart Scanner. If a material doesn’t match a core keyword, it automatically extracts the suffix (e.g., “Mud” from “M_Ground_Mud”) and creates a custom KeywordMap entry.
  • Automated Saving: Setup Wizard actions now immediately serialize the generated Configuration Data Assets to disk using UEditorLoadingAndSavingUtils::SavePackages, protecting progress from Editor crashes.
  • Interactive UI Polish: Added dynamic Slate UI highlighting (GetDependentButtonColor) and an FScopedSlowTask progress bar dialogue during heavy Asset Registry scans to improve user experience.
  • Automated Collision Injection: Added a “Step 4: Inject AudioTrace Channel” button to the Setup Wizard. This safely parses DefaultEngine.ini and automatically claims an available ECC_GameTraceChannel for dedicated Sonant traces.

:gear: Performance & Architecture

  • Runtime Async Pre-Caching: Added PrecacheMaterials() to USonantSubsystem::Initialize. The subsystem now proactively sweeps all loaded UMaterialInterface assets and populates the SmartCache during the loading screen, eliminating trace stuttering on the first footstep.
  • Data Validation & Error Checking: USonantConfig now intercepts PostEditChangeProperty to automatically trim whitespace typos from KeywordMap string keys.
  • Blueprint Volume Validation: USonantVolume now utilizes Unreal’s CheckForErrors framework to throw clickable Map Check warnings and Property Editor alerts if a level designer forgets to assign a required AtmosphereTag.
  • :cool_button: Python Content Pipeline: Engineered a complete pipeline (GenerateWavFiles.py and GenerateSonantContent.py) to procedurally synthesize royalty-free demo content natively within the Unreal Engine environment.

Current Python demo content generators are also shared here:

GenerateSonantContent.py (4 KB)
GenerateWavFiles.py (2.4 KB)

0.4.0 update, 2026-07-18 :headphone:

Runtime

  • :world_map: Replaced synchronous config/event loading and global loaded-material scans with soft references, asynchronous loading, explicit readiness, scoped event preloading, and release APIs.
  • :scientist: Added canonical physical-surface routing, exact soft overrides, deterministic keyword priority/longest-match fallback, and automatic migration of legacy hard physical-material mappings.
  • :microphone: Rebuilt automatic reverb around the actual audio listener, enclosure confidence, opposing-wall and ceiling evidence, open-space-aware radius estimation, smoothing, hysteresis, dwell time, authored-state precedence, and opt-in defaults.
  • :ear: Unified atmosphere/reverb mix ownership and added complete world-travel/deinitialization cleanup.
  • Added configurable Medium impact routing and data-driven impact tiers.
  • Added event, VFX, and decal distance/scalability gates; made custom per-event occlusion opt-in and removed pitch shifting from occlusion.
  • Hardened the optional network component with server surface traces, proximity validation, rate limiting, quantized payloads, clamped intensity, and no replicated asset references. Client requests default to disabled.
  • Fixed spline source lifetime and true listener-to-spline selection, projectile swept closest approach, and foley lifecycle/external intensity control.

Editor, tests, and distribution

  • Replaced initial setup/scanning/collision injection with an explicit config creation confirmation and a
    read-only Asset Registry/config audit.
  • Added automation coverage for acoustic classification, keyword resolution, impact tier selection, network boundaries, and configured-asset migration.
  • Moved the demo module to UncookedOnly, removed runtime platform allowlists, aligned metadata with UE 5.7, and excluded raw development samples from production package filters.

I’ll create 1+ videos soon to actually explain what this plugin offers.

[0.4.5] update, 2026-08-29 :studio_microphone:

(A purely technical bugfix update, no new features at this time)

Streaming: transient loads were never retired

FStreamableHandle::IsActive() is !bCanceled && !bReleased. A handle that has
finished loading is still active, so the prune predicate never matched one.

   RequestAsyncLoad()
        |
        v
   +----------+  load finishes  +-----------+  last ref drops  +----------+
   | loading  | --------------> | completed | ---------------> | released |
   +----------+                 +-----------+                  +----------+

                           loading    completed    released
    IsLoadingInProgress()    true       false        false
    IsActive()               true       true (*)     false

    (*) still active once the load finishes - which is why a prune written
        as !IsActive() never retired a completed request
  • Fixed: the prune now tests IsLoadingInProgress(). Previously every sound,
    attenuation, concurrency, VFX and decal streamed for a transient event stayed
    resident for the life of the world, and IsTickable() never returned false again
    once any event had streamed - a permanent per-frame cost with automatic reverb off.
  before   handles: 1  2  3  4  5  6 ...   grows for the life of the world
  after    handles: 1  2  1  0  1  0 ...   settles back to zero
  • Warmed visual assets moved to a bounded 32-entry retention window. Pruning alone
    would have made the warm-up pointless (the assets would be collected before reuse),
    so a small recent window keeps repeated events fast without unbounded retention.
    PreloadEvent remains the guarantee for first-use VFX.

Networking: server-originated events fix

The autonomous-proxy early-out that stops a client double-hearing its own predicted
event was also swallowing events the server raised on that client’s pawn, because
both paths funnelled into the same multicast.

  Who hears a footstep raised on Player A pawn?

                                | Player A   | Player B    | listen
                                | (owner,    | (sees a     | server
                                |  autonom.) |  sim proxy) |
  ------------------------------+------------+-------------+--------
  A predicts locally, server    |  muted     |   hears     |  hears
  echoes it back                |  (correct) |             |
  ------------------------------+------------+-------------+--------
  Server raises it directly
      before  (0.3.0)           |  SILENT !  |   hears     |  hears
      after   (0.4.0)           |  hears     |   hears     |  hears
  • Fixed: the multicast RPCs carry bOwnerAlreadyPlayed. Only a client’s own echo
    is suppressed. Authority-originated audio now reaches the pawn’s owner.
  • The rule moved into the pure decision model as ShouldPlayReplicatedEvent, so it is
    covered by an automation test rather than only reachable through a live session.

Surfaces: exact overrides were unreachable

  before (0.3.0)                     after (0.4.0)
  --------------------------         ----------------------------
  1. SurfaceTypeMap        <-+       1. PhysicalMaterialOverrides
  2. PhysicalMaterialOver.   |       2. MaterialOverrides
  3. MaterialOverrides    ---+       3. SurfaceTypeMap
  4. keyword match             swap  4. keyword match
  5. DefaultSurface                  5. DefaultSurface
  • Fixed: exact soft overrides are consulted before the canonical map. The setup
    wizard seeds SurfaceTypeMap[SurfaceType_Default], so any physical material left on
    the default surface was captured at step 1 and its own override at step 2 could
    never run. Documented in README.md.
  • The material-decision cache (SmartCache) is now capped at 512 entries and drops
    entries whose FObjectKey no longer resolves. Content that mints materials at
    runtime - the plugin’s own endless-runner showcases do exactly this - grew it
    without limit.

Automatic reverb: clearing a requirement made it stricter

Confidence was scored against a fixed ceiling-inclusive maximum, so removing the
ceiling requirement lowered the achievable score without lowering the threshold.

  Sample: 3 walls including an opposing pair, no ceiling. Threshold 0.75.

  evidence   ceiling 0.25  |  horizontal 3 x 0.125  |  opposing 0.25
  scored     ---- 0.000 ---|-------- 0.375 ---------|---- 0.250 ----  = 0.625

  bRequireCeiling = true     0.625 / 1.00 = 0.62   fails (correct - no ceiling)

  bRequireCeiling = false
     before                  0.625 / 1.00 = 0.62   fails  <-- stricter!
     after                   0.625 / 0.75 = 0.83   passes <-- attainable evidence
  • Fixed: confidence is normalized against the evidence the current configuration
    can actually gather. Clearing bRequireCeiling now relaxes detection instead of
    silently demanding all four walls. A ceiling found while not required still counts
    and simply saturates the score.

Atmosphere volumes

  • USonantVolume binds its overlap delegates in BeginPlay, which runs after
    overlaps are generated at registration. A pawn standing inside a level-streamed
    volume - or spawned inside a placed one - was never seen. It now sweeps existing
    overlaps on begin play. (ASonantBSPVolume was unaffected: it overrides the
    always-live NotifyActorBeginOverlap virtual.)
  • The atmosphere refcount saturates instead of overflowing; Count + 1 was signed
    overflow at the limit, before FMath::Min could clamp it.

Spatial components

  • USonantFoleyComponent and USonantSplineAudioComponent name their audio component
    uniquely. A fixed NewObject name collided when one actor carried two of them.
  • Both honour UpdateInterval changes made after BeginPlay; the property is
    BlueprintReadWrite but was only read once.
  • USonantSplineAudioComponent warns when its owner has no spline, instead of
    silently doing nothing forever.
  • USonantProjectileTracker disables its tick once it has fired, until ResetWhizby.

Editor

  • The setup wizard writes Config/DefaultGame.ini via TryUpdateDefaultConfigFile().
    SaveConfig() targets the per-user Saved/Config/<Platform>/Game.ini, so the
    assignment the confirmation dialog promised was neither source-controlled nor
    carried into a packaged build.
  • No widget binds to the module instance any more - the status getters and button
    handlers are statics. A nomad tab outlives ShutdownModule (and a Live Coding
    reload), and the previous CreateRaw(this, ...) bindings dangled.
  • ExtendMenu result is null-checked.

Demo and showcases

  ASonantGodRayShowcase, per generation step:

    spawned   floor 1  +  pillars 2  +  meteor 0.25 (every 4th)   =  3.25
    retired   -------------- one per call ----------------------  =  1.00
                                                           net    = +2.25

    before   actors  _.-~=#@   climbs forever (physics bodies and
                              shadow-casting 50k-intensity lights)
    after    actors  ======    flat at the cap
  • Fixed unbounded actor growth in ASonantGodRayShowcase, ASonantAutoShowcase
    and ASonantDemoGenerator. Each retired exactly one actor per spawn call while
    adding more than one. Cleanup now drains to the cap.
  • ASonantSpectacle checked TileMesh after SpawnActor, leaving three untracked,
    never-destroyed actors behind on every row when it was unset. The check moved ahead
    of the spawn, and the actor now ships engine-content defaults like its siblings.
  • Fixed a null-material dereference in ASonantGodRayShowcase
    (UMaterialInstanceDynamic::Create returns null for a null parent).
  • The showcases re-acquire the player pawn instead of latching a single null in
    BeginPlay. Actor begin-play can precede the game mode spawning the pawn, which
    left them permanently inert.
  • ASonantGodRayShowcase no longer overrides world exposure, bloom and volumetric fog
    by default. It is opt-in via bOverrideWorldPostProcess, and auto-exposure is a
    range again rather than a locked min == max == 1.0 that blinded any host level.
  • The 1-5 keys now route by EPhysicalSurface through the previously unused
    TestSurfaces array. They built a FHitResult with no component and no physical
    material, so all five resolved to DefaultSurface and sounded identical.
  • ImpactTestForce drives the impact tests instead of being ignored.
  • The spline, whiz-by and occlusion exhibits take assignable sounds and say so on
    their signs when unset. They were silent by construction, and the occlusion wing had
    no audio source at all - its own source comment admitted it.
  • The demo projectile assigns its mesh before enabling physics (there was no body to
    simulate or receive the impulse), and its destroy timer holds a TWeakObjectPtr
    rather than a raw actor pointer.
  • PrintCurrentSurfaceInfo traces with bReturnPhysicalMaterial and reports it.

Build correctness

  • Added includes that only -StrictIncludes (non-unity, IWYU) exposes:
    Engine/World.h in SonantFeatureDemo.cpp, and Materials/MaterialInterface.h
    plus PhysicalMaterials/PhysicalMaterial.h in SonantDemoCharacter.cpp. These were
    pre-existing latent failures - an ordinary editor build does not catch them.

Tests

Now 11 automation tests, all passing.

  Sonant.Decision.Acoustics.OpenTerrain
  Sonant.Decision.Acoustics.EnclosedRoom
  Sonant.Decision.Acoustics.Overhang
  Sonant.Decision.Acoustics.CeilingNotRequired      (new)
  Sonant.Decision.Impacts.TierSelection
  Sonant.Decision.Impacts.TierEdgeCases             (new)
  Sonant.Decision.Surfaces.DeterministicKeyword
  Sonant.Decision.Surfaces.KeywordEdgeCases         (new)
  Sonant.Decision.Network.Boundaries
  Sonant.Decision.Network.EchoSuppression           (new)
  Sonant.Integration.ConfigAssetLoads

Run them with:

Automation RunTests Sonant
  • Extracted the replication echo rule into the pure decision model so the
    “server-originated events reach the owner” fix has a regression guard.
  • Added coverage for enclosure confidence when no ceiling is required, keyword edge
    cases and determinism, impact-tier boundaries and fallback, and rate-limit
    burst/idle behaviour.

I unified previous shipped “demo guides” into a single updated one. It also supersedes the ones currently bundled with the Fab edition:

DemoGuide.md (13.2 KB)

0.4.6 update, 2026-09-22 :control_knobs:

Added :ladder:

  • Added a complete Sonant demo-audio setup under Content/SonantDemo/Audio:
    surface footstep cues for concrete, dirt, metal, water, and wood; generic and
    heavy impact cues; forest, cave, and underwater atmosphere cues; an attenuation
    asset; environment volume/LPF buses; and outdoor, cave, underwater, and three
    room-size modulation mixes.
  • Added and populated Content/DA_Sonant_Demo.uasset with:
    • a default surface plus five mapped surface types;
    • footstep and light/medium/heavy impact events for each surface;
    • keyword fallback mappings for concrete, metal, wood, water, dirt, grass,
      stone, and glass;
    • three impact tiers with minimum-strength thresholds and volume/pitch ranges;
    • outdoor, cave, and underwater atmosphere mappings;
    • small, medium, and large room reverb radius settings.

Changed :coral:

  • Updated L_Sonant_Demo to use the configured forest atmosphere, generic impact,
    and cave occlusion audio assets, then saved the map and demo configuration.
  • Hardened the live multiplayer PIE path so server-originated and owner-predicted
    footsteps route across the listen-server and both clients without an owner echo.
    The server performs the collision validation and the owning client suppresses
    the echoed multicast when it has already predicted the event.
  • Added direct Engine/HitResult.h coverage to the network session test after a
    strict UE 5.5 build exposed an include-order dependency.
  • Updated editor/game target and editor-module build configuration used by the
    validation builds.

Fixed :screwdriver:

  • Resolved the first UE 5.5 strict-build failure caused by an indirect
    FHitResult include. The corrected source now passes the same strict build
    matrix as the other supported engines.
  • Corrected the initial cooked-launch harness setup so the isolated host project
    includes an Editor target and can verify a real game world plus loaded Sonant
    module before exiting.

Validated :100:

  • Live multiplayer PIE: 20 Sonant tests passed, 0 failed. The live network
    test used one listen server and two client PIE worlds with real loopback
    connections and a replicated actor.
  • Strict cross-version Shipping builds: UE 5.5.4, 5.6.1, 5.7.4, and 5.8.2
    all passed UnrealEditor Development, UnrealGame Development, and UnrealGame
    Shipping BuildPlugin validation with exit code 0.
  • Cooked game launch: all four supported engines passed Shipping build,
    cook/package, game-world launch, Sonant-module load, clean exit, and a 30-second
    sustained-run check.
  • Runtime demo audio: the Sonant demo map entered PIE successfully; all five
    surface indices were exercised, and the Sonant log query returned no warnings,
    errors, failed, invalid, or missing entries. The map and data asset were saved
    clean with PIE stopped afterward.
  • Automatic reverb presets are configured and ready, but the global automatic
    reverb switch remains opt-in (bEnableAutomaticReverb was restored to false).

To do

  • The UE 5.8 editor still reports the known non-fatal deprecated
    r.Mobile.VirtualTextures startup ensure.

[0.5.0] update, 2026-09-29 :loudspeaker: :musical_notes:

A major modernization release. The runtime gains drop-in footsteps, an event stream that
reports what Sonant decided, runtime config swapping, data validation and live
diagnostics. The old showcase actors are replaced by Resonance, a complete demo
game with its own CC0 audio.

What ships :vertical_traffic_light:

    +--------------+--------------+--------------------------------+
    | Module       | Type         | Present in a cooked build?     |
    +--------------+--------------+--------------------------------+
    | Sonant       | Runtime      | yes - this is the product      |
    | SonantDemo   | UncookedOnly | no  - editor / uncooked only   |
    | SonantEditor | Editor       | no  - setup tab + audit        |
    | SonantDemo-  | Editor       | no  - demo content commandlet  |
    |   Editor     |              |                                |
    +--------------+--------------+--------------------------------+

Because SonantDemo is UncookedOnly, demo actors exist in the editor and in
uncooked play, but not in a packaged game. That is deliberate - see
DISTRIBUTION.md - but it does mean a level built out of demo
actors cannot be shipped as-is.


Added - runtime :plus: :plus:

  • USonantFootstepComponent: footsteps for any character without animation
    setup. Footfalls are spaced by distance travelled (cadence follows speed exactly),
    alternate between foot bones, and trace the surface under each foot. Walking is
    quieter than running. Landings play Sonant impacts scaled by fall speed. The
    OnFootstep delegate reports every footfall; bUseAnimNotifies hands timing to
    animation instead.
  • Sonant Footstep anim notify (UAnimNotify_SonantFootstep) for animation-placed
    footfalls. It routes through the character’s footstep component when one exists.
  • Event records: OnEventPlayed (Blueprint) and OnEventPlayedNative() (C++)
    broadcast an FSonantEventRecord for every event that plays: tag, resolved
    surface and how it was chosen (ESonantSurfaceSource), physical material, sound,
    final volume and pitch after clamping and occlusion, impact intensity, and whether
    it was occluded. HUDs, gameplay and tools can react to what was heard instead of
    re-deriving it.
  • SetConfigOverride swaps the active config at runtime (per level, mode or
    biome); passing null returns to the project MainConfig. Atmospheres stay pushed and
    are re-resolved against the new config. HasConfigOverride reports the state.
  • USonantSubsystem::Get(WorldContext) (“Get Sonant” in Blueprint) returns the
    first local player’s service, or null where none exists.
  • Diagnostics getters: GetActiveAtmosphere, GetActiveReverbMix and
    GetEstimatedRoomRadius.
  • Config validation: USonantConfig::IsDataValid flags events that play nothing,
    events and tiers without tags, overrides without keys, atmospheres and reverb
    presets without mixes, duplicate tier thresholds or room radii, keyword priorities
    with no keyword entry, and impact ranges that start above zero.
  • Native tag Sonant.Event.Clap.
  • Sonant.Debug 1 now labels every played event in the world with its tag, surface,
    volume and pitch.
  • Unreal Insights CPU scopes on the event path (Sonant_PlaySoundByData,
    Sonant_PlayImpact, Sonant_ExecuteEvent).

Added - Resonance demo :guitar:

  • SonantDemo is rebuilt around ASonantResonanceIsland: drop it into an empty
    level and press Play. It builds a floating island of five sound zones (Timber
    Docks, Whisper Garden, Foundry, Echo Chamber, Glass Grotto), its sky, light and
    fog, and runs the game: wake each zone’s shard by making the sound it listens
    for, return the shards to the beacon, and the island resets. Left idle it plays
    itself (attract mode).
  • Every Sonant event sends a ripple of light across the island in the colour of the
    surface it resolved, sized by how loud it was, driven by the new event records.
  • The HUD shows the live stream of Sonant decisions, the surface underfoot, the
    active atmosphere and the automatic reverb preset with its estimated room size.
  • Exercises footsteps on seven surfaces, impact tiers (a heavy landing on an anvil,
    falling crates on wood and steel), atmospheres (cave, underwater), automatic
    reverb (tunnel to great hall), whiz-by projectiles, spline audio (a river) and
    occluded emitters.
  • ASonantDemoAttractGameMode runs attract mode with no banner, for capture.
  • Movie Render Queue capture: on a non-realtime audio device (-deterministicaudio)
    the island plays its sources unpanned for the session and restores the attenuation
    assets on EndPlay. UE 5.8’s non-realtime mixer reports two output channels but
    carries an eight-channel output map, and spatialized sources come out silent
    otherwise.
  • SonantDemoEditor module and SonantDemoBuild commandlet regenerate the demo
    content (Content/Demo) from the sources in Resources/DemoAudio, so each engine
    version can produce assets in its own format.
  • 153 CC0 sounds (Kenney and Freesound contributors), credited in
    Resources/DemoAudio/CREDITS.md.

Changed :currency_exchange:

  • The legacy showcase actors (SonantFeatureDemo, SonantAutoShowcase,
    SonantSpectacle, SonantGodRayShowcase, SonantDemoGenerator) are removed, with
    their CoreRedirects. Levels that placed them need the Resonance island instead.
  • ASonantDemoCharacter uses Enhanced Input built in code (no input assets) and the
    footstep component. Controls: WASD / left stick, mouse / right stick, Space / A to
    jump, E / left click / X to clap, R to restart.
  • The plugin now depends on EnhancedInput.
  • With no MainConfig assigned the subsystem logs at Log level rather than Warning,
    because a config override is a valid way to run.
  • Module rules no longer force non-unity builds or restate C++20; both are engine
    defaults.

Fixed

  • Events whose sound was still streaming in were dropped when the load took longer than
    MaxDeferredEventDelay of wall-clock time. The delay is now measured on the world’s
    clock (undilated). Real-time play behaves as before. Offline renders (Movie Render
    Queue, fixed-timestep capture) no longer lose first-use sounds when a frame takes
    longer to render than the delay allows.
  • GetActiveReverbMix is defined out of line, so SonantSubsystem.h compiles without
    the full USoundControlBusMix type under strict includes.

Verification

  • Sonant.Decision.Footsteps.StrideCadence and
    Sonant.Decision.Footsteps.LandingIntensity cover the new stride and landing math.
  • Strict BuildPlugin -Rocket -TargetPlatforms=Win64 -StrictIncludes (no unity, no PCH)
    passes on UE 5.5.4, 5.6.1, 5.7.4 and 5.8.2: Editor Development, Game Development and
    Game Shipping, AutomationTool exit code 0 on each.
  • UE 5.8.2: 22 of 22 Sonant automation tests pass (-nullrhi, exit code 0), including
    the live listen-server + two-client PIE network test.
  • Resonance ran start to finish unattended, in -game and under Movie Render Queue.
    All five shards woke from their own objectives, and the finale and reset followed.
    The 2560x1440 walkthrough render (3,840 frames with deterministic audio) is the
    evidence.

Sonant 0.5.0 demo video:

A fairly comprehensive tutorial video is now available:

[0.5.1] update, 2026-09-30 :screwdriver: :headphone:

A fix release. Making the Sonant tutorial exercised Sonant the way a cinematic or
scripted production does, and it hit some weaknesses. This release fixes them in the plugin.
Existing projects keep their 0.5.0 behaviour unless they opt in to the new settings.

Added - runtime :running_shoe:

  • Listener-triggered volumes. USonantVolume and ASonantBSPVolume have a new
    TriggeredBy setting (ESonantVolumeTrigger).
    • LocalPawn, the default, is the 0.5.0 behaviour: the pawn a local player possesses.
    • Listener follows each local player’s audio listener instead: the camera, or the
      override set with SetAudioListenerOverride. It is checked every frame, after the
      cameras move.
    • Until now a volume only answered to a locally controlled, player-possessed pawn. An
      AI- or script-driven pawn, a spectator or cinematic camera, or an offline render
      never switched an atmosphere on. The tutorial had to possess its walker to hear its
      interiors.
  • FSonantSurfaceDef::DisplayName. Event records and debug labels report the surface
    under this name. When it is empty they report what matched, as in 0.5.0.
    • Before, the same surface came out as PM_Resonance_Gravel when a physical-material
      override matched, and as Gravel when a surface type or keyword did.
  • FSonantEventRecord::bNoSurfaceHit. This is set when PlayFootstep,
    PlaySoundAtLocation or PlayImpact/PlayImpactByIntensity receive a hit result that
    hit nothing: no blocking hit, physical material or component.
    • Such an event can only play the Default surface, and until now it did so without
      any sign. In the tutorial, a gong strike whose trace missed played as a gravel thud.
    • With Sonant.Debug 1 the event’s label reads NO SURFACE HIT, and a warning is logged
      at most every two seconds.
    • The event still plays as before.
  • IsAtmosphereActive(Tag) reports whether an atmosphere tag is pushed, whatever its
    priority.

Changed - Resonance demo :placard:

  • Offline renders keep panned spatial sound. In UE 5.5–5.8 the engine’s non-realtime
    audio device (used by Movie Render Queue and -deterministicaudio) reports two output
    channels but an eight-entry channel array, so every spatialized source renders silent.
    • 0.5.0 got around this by editing the demo’s attenuation assets at runtime to play
      unpanned. That also left the shared assets modified if the editor crashed during a
      render.
    • The island now repairs the device once it goes non-realtime: it trims the channel
      array to front left and right and rebuilds the panner’s speaker table as a stereo
      device has it. Assets are left alone. It already moved the listener every tick.
    • The code, in ASonantResonanceIsland::SyncAudioListener, is a working reference for
      projects that render their own game.
  • The demo config gives every surface a DisplayName, in the SonantDemoBuild
    commandlet and in Content/Demo/DA_Resonance. Its event records read “Gravel”, not
    PM_Resonance_Gravel.

Fixed - tests

  • Sonant.Network.PIE failed on UE 5.5 and 5.6. CQTest in those engines never fills the
    server’s ClientConnections: its connect loop starts at the array’s size, which is
    already the client count. Epic fixed this in 5.7. The test now finds the owning client’s
    connection by the client’s port, as 5.7’s CQTest does. 0.5.0 had run the automation
    tests on UE 5.8 only; the new matrix run caught it.

Documentation

  • README, Manual and DemoGuide: listener volumes, surface display names, empty hits, and
    a section on offline renders with Movie Render Queue (the engine problems and what a
    project must do).

Verification

  • New tests:
    • Sonant.Decision.Surfaces.DisplayName, Sonant.Decision.Surfaces.EmptyHit and
      Sonant.Decision.Volumes.InsideBox (pure).
    • Sonant.Listener.PIE (live, on a listen server). A Listener volume around a distant
      camera switches its atmosphere on while the possessed pawn is elsewhere; a LocalPawn
      volume in the same place stays off; moving the volume off the camera pops it. Event
      records report “Granite” for a physical-material override with that display name,
      “Default” with bNoSurfaceHit for an empty hit, and the Default surface’s own
      display name once one is set.
  • UE 5.8.3, in the development project: 27 of 27 Sonant automation tests pass
    (-NullRHI, exit code 0), including both live PIE suites.
  • Test matrix: a fresh copy of the plugin in a
    content-free host project, built and tested on UE 5.5.4, 5.6.1, 5.7.4 and 5.8.3.
    • All four module DLLs built on each engine.
    • 27 of 27 Sonant automation tests passed on each (-NullRHI, exit code 0), including
      both live PIE suites.
  • Resonance under Movie Render Queue (UE 5.8.3, 30 s), with the host project’s own
    device fix switched off, so only the demo’s repair was active:
    • The island logged the repair: “8 channels → 2”.
    • Left/right level difference on the loudest frames: median 1.3 dB, 90th percentile
      7.3 dB. The 0.5.0 walkthrough render (unpanned) measures 0.1 and 0.6 dB.
    • Raw mix about -31 LUFS, against about -33 LUFS in 0.5.0: the level is unchanged.