Spatialization

Thanks to kira Audioware supports audio spatialization, which means audio that moves along its emitter, getting louder when closer and softer when further, along with left-right panning.

Registration

Audio emitter(s) must be registered before you can emit audio from them, but they are automatically cleaned up whenever emitter despawns or dies.

  Redscript
if !GameInstance.GetAudioSystemExt(game).IsRegisteredEmitter(emitterID) {
    GameInstance.GetAudioSystemExt(game).RegisterEmitter(emitterID);
}

Types

Audio emitter have to be positioned so they can only be Entity or classes inheriting from it like GameObject, devices, vehicles, NPCs, etc.

Cleanup

You don't need to manually unregister your audio emitter(s), even if you can do so:
Audioware does it automatically whenever emitter despawns or dies. Dying emitter still emit.

How to easily e.g. fade a sound out whenever an Entity is dying click to open
  Redscript
/// for Humans
@wrapMethod(NPCDeathListener)
protected cb func OnStatPoolCustomLimitReached(value: Float) -> Bool {
    let wasAlive = !this.npc.m_wasJustKilledOrDefeated;
    let out = wrappedMethod(value);
    if wasAlive && this.npc.m_wasJustKilledOrDefeated {
        let id = this.npc.GetEntityID();
        let name = this.npc.GetDisplayName(); // or whatever you named it
        // fades for 2sec, with intensity 0.2
        let fadeOut = LinearTween.ImmediateOut(2.0, 0.2);

        GameInstance
            .GetAudioSystemExt(this.npc.GetGame())
            .Stop(n"my_custom_audio", id, name, fadeOut);
    }
    return out;
}
/// for Robots
@wrapMethod(NPCDeathListener)
protected cb func OnStatPoolMinValueReached(value: Float) -> Bool { ... }

A courtesy of Demon9ne, thanks for the snippet!

Hint

V cannot be an audio emitter because (s)he is the listener.

Usage

Then, simply use the OnEmitter variants of the methods:

  Redscript
// ⚠️ emitterID and emitterCName must be both valid and non-default
GameInstance.GetAudioSystemExt(game).PlayOnEmitter(n"my_custom_audio", emitterID, emitterCName);

// if should stop at some point...
GameInstance.GetAudioSystemExt(game).StopOnEmitter(n"my_custom_audio", emitterID, emitterCName);

YouTube demo

Auto-registration

Whenever you want to turn all particular entities of a kind into audio emitters automatically, you can reach out for Codeware game events.

Here's a dummy example on how to use F1 to register any audio emitter in crosshair.

  Redscript
import Audioware.*

public class AutoEmittersSystem extends ScriptableSystem {
    private func OnAttach() {
        GameInstance.GetCallbackSystem().RegisterCallback(n"Input/Key", this, n"OnKeyInput")
        // listen to F1 being pressed or released
        .AddTarget(InputTarget.Key(EInputKey.IK_F1));
    }
    private cb func OnKeyInput(evt: ref<KeyInputEvent>) {
        // when F1 is released
        if NotEquals(evt.GetAction(), EInputAction.IACT_Release) { return; }
        // some songs defined in manifest
        let sounds = [ 
            n"my_custom_song_01",
            n"my_custom_song_02", 
            n"my_custom_song_03",
            n"my_custom_song_04", 
            n"my_custom_song_05"
        ];
        // get a random sound above
        let eventName = sounds[RandRange(0, ArraySize(sounds) -1)];
        // prepare some settings
        let tween = new LinearTween();
        tween.startTime = RandRangeF(1.0, 3.0);
        tween.duration = RandRangeF(3.0, 4.5);
        let emitterID: EntityID;
        let emitterCName: CName = n"DummyTest";

        let game = this.GetGameInstance();
        // get entity V currently looks at (crosshair)
        let target = GameInstance.GetTargetingSystem(game).GetLookAtObject(GetPlayer(game));
        if !IsDefined(target) { return; }
        emitterID = target.GetEntityID();
        if !GameInstance.GetAudioSystemExt(game).IsRegisteredEmitter(emitterID) {
            GameInstance.GetAudioSystemExt(game).RegisterEmitter(emitterID);
        }
        GameInstance.GetAudioSystemExt(game).PlayOnEmitter(eventName, emitterID, emitterCName);
    }
}

YouTube demo

This particular showcase is a smoke test: applying most CPU-intensive sounds (music streaming) to multiple entities in the vicinity and triggering auto-unregistration.

It aims at demonstrating that both performances stay correct (even on my low-end laptop!),
and unregistration happens seamlessly (including during simultaneous kills).