Occlusion
Open the live demo · Read the source · View on GitHub
AudioScene must not learn what a wall is; that belongs to the physics.
Instead it takes a callback, occlusion, and asks it how much of a sound
gets through between the source and the listener.
Step 1: A wall as a question, not a shape #
This page's wall is one line: crossing x = 2 halves what gets through.
/// A wall at x = 2: a straight line that crosses it is half heard, and one
/// that does not is heard clearly. The scene never learns what a wall is;
/// it only asks this question.
static double _occlusion(Vector3 from, Vector3 to) {
final crossesWall = (from.x - 2.0).sign != (to.x - 2.0).sign;
return crossesWall ? 0.5 : 1.0;
}
Step 2: A scene that asks it #
final scene = AudioScene(backend: SilentBackend(), occlusion: _occlusion);
const bell = SoundDef(name: 'bell', asset: 'bell.wav', loop: true);
final behindTheWall = scene.play(bell, Vector3(4.0, 0.0, 0.0));
Step 3: Listen from both sides #
final listener = AudioListener(position: Vector3(0.0, 0.0, 0.0));
scene.update(listener);
final gainBehindWall = behindTheWall.audibleGain;
final muffleBehindWall = behindTheWall.muffle;
listener.position.setValues(5.0, 0.0, 0.0);
scene.update(listener);
final gainSameSide = behindTheWall.audibleGain;
With the listener on the near side of the wall, the sound behind it plays at half its usual gain and reports itself half muffled. Move the listener past the wall to the sound's own side, and it plays clearly again.
Step 4: Walk through the wall's shadow #
The listener walks back and forth across the wall, or stands where the slider puts it. On the wall's far side from the bell the gauges answer the callback: the purple bar is the muffle and the yellow one the gain, and the bell itself goes dull while it is muffled. On the bell's own side the muffle is gone. The wall is nothing but a box the eye can see; the audio scene never learns it.
// The same scene and the same question, asked every frame while the
// listener walks: the wall is only ever the callback.
_audio = AudioScene(backend: SilentBackend(), occlusion: _occlusion);
_bell = _audio.play(
const SoundDef(name: 'bell', asset: 'bell.wav', loop: true),
Vector3(4.0, 0.0, 0.0),
);
_listener = AudioListener(position: Vector3.zero());