A [[Voice]] is a 3D position that rays will attempt to discover. To create a voice, invoke the `CreateVoice` function on a [[RaytracingContext]]. It takes one [[IPositionF]] argument, which is used to position the voice: ```cs var position = new StaticPositionF(4, 4, 4); var voice = context.CreateVoice(position); ``` ## Position Interface You can change the position of a `Voice` at any time: ```cs voice.position = new StaticPositionF(10, 10, 10); ``` It's best to implement the [[IPositionF]] interface on your game objects, and then assign your object directly to the voice. For example if you want a voice to follow an enemy in your game, your enemy class would implement [[IPositionF]]: ```cs public class Enemy : IPositionF { public Vector3F position; // Implement the interface public Vector3F GetPosition() => position; } ``` Then pass the enemy directly to the voice: ```cs var enemy = new Enemy(); var voice = context.CreateVoice(enemy); ``` This voice's position will now automatically match the enemy's position. ## The Initial Raytrace When a voice is created, it starts in an `initialising` state where it is waiting to be raytraced. Do not play sounds in your game engine yet, as this voice might be muffled. New voices are raytraced together in batches when `context.Update()` is called. You can customise the batch size via the `context.maxNewVoiceBatchSize` setting. ```cs void Update() { var voice1 = context.CreateVoice(...); var voice2 = context.CreateVoice(...); var voice3 = context.CreateVoice(...); // The above 3 voices are placed into a batch and raytraced together context.Update(); } ``` > `context.Update` must be called regularly. Once per frame is typical, but you can call it as often as you like ## Raytracing Results The first time a voice is raytraced, its `OnRaytracingComplete` callback will fire. The `filter` field on a voice contains the low frequency (LF) and high frequency (HF) gains that should be set on a low pass filter: ```cs var voice = context.CreateVoice(...); voice.OnRaytracingComplete = () => { var gainLF = voice.filter.gainLF; var gainHF = voice.filter.gainHF; // Pseudocode var filter = new Godot.LowPassFilter(gainLF, gainHF); Godot.PlaySound(voice.position, filter); } ```