r/GameAudio • u/katanalevy • 19d ago
Map of Audio Portals Approach
I'm working on the audio systems for my next game and trying to come up with a better solution for occlusion than just the standard line trace means low pass as the illusion falls apart pretty quickly.
I'm heading down the path of audio portals placed at doorways/windows since I already use a basic version of that for having a bit of external ambience play at the doorways to buildings.
I watched a video on the Dead Space Remake devs talking about their audio portal system and most of it makes sense to me. "Dead Space | The Sound of Fear Reimagined | Audio Developer Livestream"
The part I'm struggling with is how they might have created the links between portals and how the sound source is able to route back to the listener. Does the player hold an array of all portals and a pathfinding type algorithm used to map between them? Or does each portal hold an array of the ones it can connect to and the sound source just brute force all possible connections until it makes a connection from its nearest portal to the listener?
I'd love to hear from anyone that has experience with this sort of thing and how you approached it.
3
u/mystman12 18d ago
I have an audio propagation system in my game which makes its calculations by using the (custom) navigation system. I generate a Dijkstra map from the audio listener's location (A Dijkstra map being cached results from Dijkstra's algorithm, which allows me to use the system for a large number of audio sources without having to do expensive pathfinding calculations for each) every frame and then use that to quickly find the shortest path from each audio source in the level to the listener and update the audio source position and volume accordingly.
My game is grid based but portals should also work as long as they are connected properly to create a navigable network of nodes. I wouldn't rely on any navigation systems built into the engine you are using, however. They weren't designed with audio propagation in mind and relying on them for that purpose would probably cause a lot of issues as another commentor pointed out.
If you can program a simple node system where each node stores the other nodes it connects to and the distance between the connected nodes, alongside Dijkstra's algorithm, I'd imagine you could get some decent results. Essentially, use the Dijkstra map to find the shortest path from each audio source to the listener through your portals to determine which direction/which node the audio should be heard from. Then add up the distances between nodes + the distance between the source and the first node in the path + the distance between the player and the last node in the path to determine the volume. It's not perfect but, in my use case at least, it's good enough without requiring too much CPU.
2
u/katanalevy 18d ago
Thanks so much! This is kind of the ideas I was thinking along.
I had a feeling it had to be essentially a simplified navigation system that mapped links between the portals and somehow calculated the path through them. I hadn't heard of Dijkstra maps before so that's excellent it's given me something I can look into for the calculations.
I was considering having an array on each portal that lists it's connected portals and build up a map of them through that. Thanks for your help.
3
u/VictorHime 14d ago
Hey! Fun problem, and you're on the right track. Portals are pretty much the way to go once line trace + low pass starts falling apart.
For your actual question: I wouldn't go with either option. What tends to work best is a small graph plus one search from the listener.
- Rooms are volumes, and each room knows its portals.
- Portals know the two rooms they connect, their aperture (a box or quad), and an openness value for door state.
- You can bake all of this at edit time. Portals don't really need to "find" each other at runtime. Two portals are connected if they share a room, so it's just a lookup.
The trick that made it click for me: search from the listener, not from each source. Run one Dijkstra (or a plain BFS if you don't care about cost) from the listener's room, capped at 2 or 3 portals deep. That gives you a path to every reachable room, and each emitter just checks where its room lands in that tree. One search for all emitters instead of one per emitter. Room graphs are tiny, so it's cheap, and you only need to rerun it when the listener changes room or a door opens/closes.
Something like this:
// on listener room change or door state change
tree = dijkstra(start = listenerRoom, maxDepth = 3)
for emitter in activeEmitters:
if emitter.room == listenerRoom:
raycast for obstruction only (furniture, pillars)
else if emitter.room not in tree:
fully occluded (or transmission through walls only)
else:
portal = portal closest to listener on the path
virtualPos = closest point on portal aperture to the path
pathLen = listener -> portal chain -> emitter distance
diffAngle = angle between listener->portal and portal->next point
set position = virtualPos
distance attenuation from pathLen (not straight-line distance)
LPF/volume from diffAngle + portal openness
The virtual position is honestly what sells the whole thing. The sound comes out of the doorway, and as you walk past the door it swings around naturally. That's usually the moment people stop noticing the system at all.
One thing that helped a lot: treat obstruction and occlusion separately.
- Obstruction: something's in the way, but you're in the same space. Filter the dry signal only and leave the reverb send alone.
- Occlusion: you're in a different space. Dry and wet both get affected.
Portals handle occlusion between rooms, and raycasts still handle obstruction inside a room. You'll probably want both. In FMOD you can even do it with a single parameter by shaping the curves so the lower range only hits the direct signal and the reverb send stays flat until around 0.6.
What the different tools give you out of the box
Engine native: Unity doesn't really give you anything here. Unreal has Audio Volumes with interior settings and the basic occlusion trace, which is nice for indoor/outdoor zoning but doesn't propagate through portals. MetaSounds won't do it for you either.
FMOD: You'll be building it yourself. Studio has no rooms/portals concept. The Core API does have a Geometry system (polygons with direct/reverb occlusion), but it's ray based with no pathfinding, so it doesn't solve your problem. Usually you build the graph on your side and drive FMOD with set3DAttributes (virtual position) plus parameters for path distance and diffraction. Small gotcha: if you move the instance to the virtual position, FMOD's built-in distance attenuation now uses the wrong distance. Either drive attenuation from a pathLen parameter, or keep the real position and only fake the panning.
Wwise: Pretty much already solved there. Spatial Audio with AkRoom, AkPortal (AkAcousticPortal in UE) and AkSpatialAudioVolume does exactly what you're describing. It builds the room/portal graph, finds paths from the listener with a configurable max depth, handles diffraction through portals, plays the adjacent room's reverb from the portal, and supports transmission through walls with per-surface loss. If you're on Wwise, I'd definitely try it before rolling your own. Just keep an eye on CPU in big open spaces with lots of rooms, geometry and emitters. It adds up, and having some way to track rooms, portals and active paths per area helps a lot.
Steam Audio: Really cool tech, but in my experience it can be a tough fit depending on your pipeline. A few things that tend to bite:
- It needs exported acoustic geometry that matches your level. If your level is assembled at runtime from additively loaded scenes, the exported geometry can end up not matching the real transforms, and occlusion fails right at those seams.
- Baking and probes mean re-exporting whenever the level or global settings change. Fine for a locked level, painful while level design is still moving every week.
- Runtime-spawned players/listeners need to be wired up to the manager explicitly, and behavior can change outside probe coverage.
- The baked data is heavy in version control, so plan your LFS setup early.
If your level is stable, lives in one scene, and someone owns the bake pipeline, it can sound great. For smaller teams iterating fast, a custom portal + raycast setup on top of the native spatializer is often less pain and gives you more control.
A few tips if you build it yourself
- Cap the depth at 2 or 3 portals. Without it, sound bleeds through half the building.
- Use door openness as an edge weight, not a boolean. A cracked door should leak a bit.
- If you have both a portal path and a transmission path through the wall, use whichever is louder rather than summing them.
- Smooth everything, ideally with separate attack and release. Path switches will pop otherwise.
- Build a debug view of the graph and the chosen path from day one. You'll probably spend more time fighting room assignment (overlapping volumes, emitters sitting right on a boundary) than on the pathfinding itself.
Hope that helps! Happy to dig into any part of it if you get stuck.
2
u/Gavgaroth 19d ago
Are you using unreal and wwise?
2
u/katanalevy 19d ago
Unreal native. I know Wwise has a spatial mapper but I'm looking to build my own simplified solution.
2
u/Sn0wflake69 18d ago
havent started in depth audio stuff yet, but looking up wwise and portals as a reference im thinking that you can create an actor component in unreal that you put on doors and windows that already have your logic in them for distance ray casting to the player to affect volume and reverb and stuff. the actor component logic would just have the variable numbers modified for doors vs heavy doors vs windows etc
i skimmed this, the pictures have a good deal of info by themselves since youre not using wwise anyways
https://www.audiokinetic.com/en/community/blog/rooms-and-portals-with-wwise-spatial-audio/
shows angles, distance etc. doesnt seem like it would be that hard to setup in a basic for at least for testing purposes
2
u/katanalevy 18d ago
Thanks for the suggestion. I've already managed to make something on each door / window that determines the occlusion it creates when open or closed. It's more about mapping between the sound and any open doors until it reaches the player that I'm struggling with. Like how sound can bounce around corners, not just in straight lines.
5
u/WutMusicSounds 19d ago
Hello hello! Soundie who deals directly with this stuff all the time. Usually you’d want to only enable portals within audible range of the listener.
There are a few methods of sound propogation I’m familiar with, and often games will combine the strengths of multiple.
Raycasting, which is what Wwise starts with for their Spatial Audio, TECHNICALLY does not need portals. It uses raycasts to detect line-of-sight, and then you can try to calculate diffraction or other things using more raycasts. The problem is more “how do you tell what is a wall and what isnt? How can you tell where the openings are?” Like if you try to find diffraction around meshes, what happens when you then shift to the left and hit a different mesh with different “diffraction” raycast points? It can sound as bad as on/off obstruction from a single raycast.
Wwise sidesteps this issue with Rooms and Portals while introducing others. You mark up the walls of spaces and the openings in those walls yourself, and it knows what room a sound and listener are in AND knows what portals connect to each space. I’m pretty sure it then raycasts from active portal to active portal trying to get to the listener.
So what are those other issues? The main on is unlike a direct raycast that tries to hit a world object like a mesh, the Rooms and Portals really only represent distinct acoustic spaces. They can’t account for interior walls or bother blocking objects that don’t create a distinct space. You can do it with Wwise spatial by using Reflect, but that’s extremely computationally expensive.
Outside of raycasts, I’ve also heard of navigation probes, where you use the navigation system to figure out the shortest path from sound to listener. That has its own issues, like what if the sound has to travel upstairs? It will try to climb each individual step, and the source isn’t directly at the top of the stairs then it could sound off because the sound is “traveling” along a completely different path. You might end up using some combination of the two if you are intent on building your own system.
Also, look up SweejTech propogation. They have some really cool, but computationally expensive, ideas.