Getting started

Cover image

Welcome to audioware book !

Audioware is a native plugin to play custom audios in Cyberpunk 2077, without REDmod.

It's built with emphasis on getting you going fast, providing sensible defaults and seamless integration with the game while not compromising on performances.

Here's the simplest way to test it out in under 5min.

โฌ‡๏ธ Install

๐Ÿ“„ Define audios

Create a folder e.g. MyMod for your mod, located in either depot:

  • under mods\MyMod
  • or r6\audioware\MyMod but not both !

Create a manifest e.g. audios.yml.

In its simplest form, here's how it looks like:

  YAML
version: 1.0.0
sfx:
  my_custom_audio: some.mp3 # accepts most common formats like .wav / .ogg / .mp3 / .flac

โ™ฌโ‹†.หš Use in-game

  Redscript
GameInstance.GetAudioSystem(game).Play(n"my_custom_audio");

If you want to dive in directly, head over to How to use? for more.

Concept

Out-of-the-box, Cyberpunk 2077's vanilla1 audio engine is built on top of Audiokinetic's WWise which is a professional-grade audio software and tools suite.

Audioware does not make any use of it and it has almost no control over it.

Here's how Cyberpunk 2077 is designed, in an overly simplified way.

Cyberpunk 2077 audio system

Why not directly hook WWise?

When I initially started working on Audioware I also was tempted to hook everything from Audiokinetic to allow adding custom audio to the game. At first.

But the reality is that, when you choose this path on one side you get native2 integration which is great, but on the other you then need to do everything as both WWise and the game does. Not even mentioning that you actually will have to learn how CDPR works with WWise, which is not always standard.

Professional all-in-one softwares like Audiokinetic can be dauting to use when unfamiliar and quickly become an entry-skills barrier3 for newcomers who would simply like to add sounds, play around with them, have fun and come up with an interesting mod.

What about REDmod?

I really enjoyed REDmod in the beginning but always felt frustrated after a while to not be able to alter sounds dynamically.

The audio parameters it exposes are very cool, but as far as I remember you can't seamlessly switch from one to another, and if you want multiple parameters per sound you basically have to duplicate them as many times.

Last but not least, I regularly got players complaining about it becoming overly slow when (too?) many mods use it, and it does not seem particularly appreciated among player base.

Then, how?

What I always wanted right from start is a tool that can get me going in under 15min.

I wanted something to be able to play easily defined sounds with parameters and audio effects.

Something Simple. Easy. yet Customizable and Fast.

And this how Audioware was initially born as a simple proof-of-concept in 4ddicted, another mod of mine. Until other modders started to notice that it worked pretty well and asked me to turn into a fully integrated native plugin.

Audioware actually uses a second alternate audio engine named kira, alongside vanilla one.

It then does integrate seamlessly, creating the illusion that there's only one and unique audio environment.

Here is, once again in an overly simplified way, how it works:

Audioware plugin


But let's process to next chapter to see how it can be used, and what it can currently do for you.

1

vanilla describes everything belonging to the original game, as opposed to further modifications or mods made by the community.

2

natively in the sense that tool, assets and game itself speaks the exact same language leading to seamless integration.

3

reserved to a handful of professional.

How to use?

In Getting started we already saw that adding custom sounds for Cyberpunk 2077 with Audioware literally boils down to 2 steps:

  1. define your audios in Manifest(s): see how to further describe your audio assets along optional settings and metadata.
  2. play them in-game with scripting API: using CET or Redscript to control how / when they get played, stopped, switched, etc.

All audios have some automations built-in, that you can read about in Integration

Manifest

A manifest is a simple YAML1 file to describe your sounds. Audioware then use them to build sounds banks on game startup.

Let's take a closer look at a Manifest's anatomy.

Anatomy

A manifest is a .yml1 file located in a folder named after your mod inside one of 2 depots.

It expects a version and sections like sfx, onos, voices or music.

It must be defined:

  • in a folder named after your mod (e.g. mods\MyMod) itself located inside any valid depot (mods or r6\audioware),
  • alongside audio files: files can be located in sub-folders, at your discretion.

Each section contains one or multiple audio ID(s) which points to an audio file path.

When using a simple audio file, you can write it inline.

  YAML
version: 1.0.0
# โฌ‡๏ธ section
sfx:
# โฌ‡๏ธ audio ID      โฌ‡๏ธ audio file path
  my_custom_audio: some.mp3

But you can also write nested properties for settings:

  YAML
version: 1.0.0
sfx:
  my_custom_audio:
    file: some.mp3 
    settings:
      volume: 4.0 # 4 times louder!

All audio accepts multiple optional settings.

Supported audio formats

Audioware supports the following formats:

  • .wav
  • .ogg
  • .mp3
  • .flac

Tip

Generally speaking, Cyberpunk 2077 vanilla audio uses 48kHz / 16 bit PCM.

analyze with ffprobe
$ just analyze C:\\Development\\modding-cyberpunk\\4ddicted\\archive\\source\\archive\\base\\localization\\common\\vo\\civ_mid_m_85_mex_30_mt_vista_del_rey_f_1ed3f72f92559000.wem

ffprobe -i 'C:\Development\modding-cyberpunk\4ddicted\archive\source\archive\base\localization\common\vo\civ_mid_m_85_mex_30_mt_vista_del_rey_f_1ed3f72f92559000.wem' -show_format

ffprobe version 6.0-essentials_build-www.gyan.dev Copyright (c) 2007-2023 the FFmpeg developers
  built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-zlib --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-sdl2 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libgme --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libtheora --enable-libvo-amrwbenc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-librubberband
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100

[wav @ 0000023cb642ebc0] Estimating duration from bitrate, this may be inaccurate
[wav @ 0000023cb642ebc0] Could not find codec parameters for stream 0 (Audio: none ([255][255][0][0] / 0xFFFF), 48000 Hz, 
1 channels, 103 kb/s): unknown codec
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Input #0, wav, from 'C:\Development\modding-cyberpunk\4ddicted\archive\source\archive\base\localization\common\vo\civ_mid_m_85_mex_30_mt_vista_del_rey_f_1ed3f72f92559000.wem':
  Duration: 00:00:05.94, bitrate: 103 kb/s
  Stream #0:0: Audio: none ([255][255][0][0] / 0xFFFF), 48000 Hz, 1 channels, 103 kb/s
Unsupported codec with id 0 for input stream 0
[FORMAT]
filename=C:\Development\modding-cyberpunk\4ddicted\archive\source\archive\base\localization\common\vo\civ_mid_m_85_mex_30_mt_vista_del_rey_f_1ed3f72f92559000.wem
nb_streams=1
nb_programs=0
format_name=wav
format_long_name=WAV / WAVE (Waveform Audio)
start_time=N/A
duration=5.937938
size=76925
bit_rate=103638
probe_score=99
[/FORMAT]

Validation

What is worth mentioning is that Audioware will actually validate many properties of your audios on game startup, here's a non-exhaustive list.

Validation error(s)

In any case error(s) will never crash your game, Audioware will instead ignore the invalid entries and report them both in the logs at red4ext\logs\audioware-xyz.log and in CET Game Log.

IDs must be uniques

each audio ID (e.g. my_custom_audio) is automatically added to game's CName pool on startup, so make sure they are truly uniques (across all game and all mods).

Files must be located inside depot

Audio files can be defined at your convenience at the root of your mod folder inside its depot, or any sub-folder, but they cannot be located outside.

Files must be valid

Each audio file is briefly preloaded on game startup to make sure they will play just fine during your game session.

Audio settings must be valid

Each setting defined alongside audios must be valid.

e.g. specifying a start_position further than audio total duration is not!

Validation deep-dive

If you would like to know exactly how validation works, consider browsing unit-tests files.

Guarantees

The reason behind these numerous validation checks: it then allows Audioware to make assumptions about your sounds bank.

Guarantees

Upholding these invariants guarantees for example that any audio ID that makes it into Audioware both exists and can be safely loaded without further need for runtime validation, increasing overall in-game performances!

Don't be THAT person!

Of course if you delete audio file(s) while your game is running, Audioware will crash as soon as called with e.g. Play. This is expected.

Let's be pragmatic 1sec: if you do so, you probably deserve your game to crash anyway ๐Ÿ˜‚

NO hot-reloading

Since everything is loaded at-most once on startup, Audioware does not currently provide any way to hot-reload your audio assets in-game.

๐Ÿ’ก To get you going fast during mod development, you can rely on AudioSettingsExt instead to adjust audio effects until you get them to your liking, then write them down in your Manifest.

1

YAML is a file format, see how to write your own.

Sections

Manifest can contain any of the following sections.

Sections provide "good defaults", a way to classify your audio assets, and even more.

SFX

sfx is used to define simple sounds.

  YAML
my_custom_sfx: ./somewhere/sfx.ogg
DefaultEditable?
usagein-memoryโœ…
volume settingsSfxVolumeโ›”

Onos

onos (onomatopeia) is used to define audio with 2 files each, one per gender.

  YAML
my_custom_ono:
    fem: ./somewhere/ono.wav
    male: ./somewhere/else/ono.wav
DefaultEditable?
usagein-memoryโœ…
volume settingsDialogueVolumeโ›”

Info

Useful for audio that do not require any subtitle, but still have a notion of gender.

e.g. goons grunts and other onos.

Voices

voices (sometimes called voiceovers) is used to define audio with multiple files each
and optional subtitles.

DefaultEditable?
usageon-demandโœ…
volume settingsDialogueVolumeโ›”

Simple Voice

  YAML
my_simple_voice:
  en-us: ./some/voice.wav

Info

Useful for audio that have to be translated into multiple languages, but for which the notion of gender does not matter.

e.g. a vending machine promotional speech

Simple Voice with subtitle

  YAML
my_simple_voice:
  en-us:
    file: ./some/voice.wav
    subtitle: "hello world"

Info

Useful to add simple subtitle to be played along your audio.

e.g. NPC dialogues or chatters.

Tip

Defining subtitle will automatically register them with Codeware Localization and play them alongside audio, for the proper gender and locale(s).

Plural Voice

  YAML
version: 1.0.0
voices:
  my_plural_voice:
    en-us:
      fem: ./fem_intro.mp3
      male: ./male_intro.mp3
      subtitle: "Let me introduce myself, I'm V."
  my_other_plural_voice:
    en-us:
      fem:
        file: ./fem_wake_up.mp3
        subtitle: "Looks yourself in the mirror, girl."
      male:
        file: ./male_wake_up.mp3
        subtitle: "Look yourself in the mirror, dude."

Info

Useful for dialogues that are both locale-based and gender-based, with subtitle.

e.g. V's dialogues.

Music

music defines songs and ambience music.

  YAML
version: 1.0.0
music:
  gorillaz_feel_good_inc: ./feel-good-inc.mp3
DefaultEditable?
usagestreamingโœ…
volume settingsMusicVolumeโ›”

Settings

Any sound will accept the following settings.

๐Ÿ—ƒ๏ธ Usage

This allows to specify how audio will be handled in memory.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  usage: on-demand

Each section already has its own default usage when left unspecified, see Sections.

You can choose between possible values: on-demand, in-memory and streaming.

Extra flexibility

This gives you extra flexibility if e.g. you want to play a song which is traditionally defined in music as a ono instead (which by default is loaded in-memory) while still being able to play it with streaming.

in-memory

The audio is loaded all-at-once in-memory on game startup and kept around for the whole duration of the game session.

Best used for

Short sounds that are meant to be played frequently.

on-demand

The audio is loaded all-at-once each time on-demand, and never kept around.

Best used for

Short sounds that you don't want to permanently allocate memory for,
or that are not meant to be played frequently.

streaming

The audio is streamed on-demand.

Best used for

Long-lasting sounds that should not be loaded all-at-once in-memory and only streamed on-demand.

๐Ÿ”‰ Volume

You can set Volume factor as follow:

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    volume: 2.0 # 2 times louder !
my_other_audio:
  file: ./somewhere/else/audio.ogg
  settings:
    volume: 0.5 # 2 times softer

Info

No matter how high Volume is set, it will not play louder than 85dB.

๐Ÿ•Ÿ Start time

This will play your audio with a delay.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    start_time: 10s # 10 seconds delay

๐Ÿ”š Start position

This will play your audio further from start.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    start_position: 1s # start playing directly at 1s

Warning

Note that digits with decimal(s) are not supported, so if you would like to start the audio at e.g. 1.2s, please specify 120ms instead.

๐Ÿ• Region

This will only play the specified region of audio.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    region:
      starts: 120ms # starts directly from 1.2s
      ends: 8s # ends at 8s

Hint

You're not required to specify both starts and ends.

If left unspecified:

  • starts will start at the beginning of the audio.
  • ends will play until the end of the audio.

Also kindly note that entire piece of audio still need to be loaded, in terms of memory, regardless its region.

๐Ÿ” Loop

This will loop audio until explicitly stopped.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    loop: true

โฉ Playback rate

This will play your audio faster, or slower.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    playback_rate: x0.5 # plays twice as slow
  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    playback_rate: x2 # plays twice as fast

You can also specify the value in semitones as follow.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    playback_rate: 2โ™ฏ # adjusts by 2 semitones

โ†”๏ธ Panning

This adjust from where the audio originates from, from left to right.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    panning: 0.0 # plays fully on left side
  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    panning: 1.0 # plays fully on right side

Warning

The value must be between 0.0 and 1.0 (inclusive).

โคด๏ธ Fade-in tween

This will play your audio gradually fading-in.

  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    fade_in_tween:
      start_time: 1s # starts playing directly from 1s
      duration: 3s # fade-in duration
      Linear: # linear fade-in curve (no value needed)
  YAML
my_custom_audio:
  file: ./somewhere/audio.wav
  settings:
    fade_in_tween:
      start_time: 1s # starts playing directly from 1s
      duration: 3s # fade-in duration
      InPowi: 3 # easing-in with power 3

Possible values for easing can be found here.

Hint

Note that fade-out can be specified as a parameter when calling methods like Stop, Switch, etc. see AudioSettingsExt.

Routing

Each section in the manifest will be routed to different tracks internally.

This is important because each track will come with different behavior.

Volume settings

Depending on which section audio is defined, it will be affected by a specific game volume setting.

Cyberpunk volume settings

Cyberpunk volume settings

trackvolume
sfxSfxVolume
onosDialogueVolume
voicesDialogueVolume
musicMusicVolume

All audio are always affected by MasterVolume, as expected.

YouTube demo

Parameters

Likewise each track will be affected, or not, by preset and reverb mix.

trackpresetreverb
sfxโœ…โœ…
onosโœ…โœ…
voicesโœ…โœ…
musicโŒโŒ

Going further

This might sounds restrictive at first, but it's actually a way to provide good defaults while being easily worked-around when needed.

Tip

Imagine you want to play a song affected by underwater preset when V dives underwater.

Even if you'd usually go for music section,
nothing prevents from defining your audio in sfx instead with streaming usage for example.

API

Audioware's API integrates seamlessly with Cyberpunk AudioSystem, but it offers more.

To start using it right away, continue to the Developper Guide.

If you need a deeper understanding on how it's built, Internal docs are available.

Developer guide

The simplest way to get going uses Cyberpunk 2077's native game system called AudioSystem, as you normally would with vanilla1 sounds.

When you start requiring a little bit more control, or want to add-in some audio effects, it's usually time to reach for AudioSystemExt and AudioSettingsExt.

And you can also modify Global Parameters at anytime during the game session.

Last but not least, your sounds can be played on audio emitter(s) thanks to Spatialization.

1

vanilla describes everything originally belonging to the game, as opposed to further modifications or mods made by the community.

AudioSystem

Once defined, each audio ID is automatically registered on startup, making it available for scripting in-game.

If you simply want to play any custom sound, you can use AudioSystem as you normally would for vanilla sounds.

  Redscript
GameInstance.GetAudioSystem(game).Play(n"my_custom_audio");

It also accepts any of the usual parameters that AudioSystem's methods support.

Currently all these methods are supported:

AudioSystemExt

AudioSystemExt is an enhanced system over Cyberpunk's AudioSystem.

This system exposes both the exact same API as its counterpart, but also similar methods with additional parameters.

For example, if you want your audio to fade-in linearly during 5secs:

  Redscript
import Audioware.LinearTween

//                                      โฌ‡๏ธ notice 'Ext' extension here
let system = GameInstance.GetAudioSystemExt(game);
let v = GetPlayer(game).GetEntityID();

// play audio                            โฌ‡๏ธ with 5s linear fade-in
system.Play(n"my_custom_audio", v, n"V", LinearTween.Immediate(5.));

// later on, stop audio                  โฌ‡๏ธ with 2s linear fade-out
system.Stop(n"my_custom_audio", v, n"V", LinearTween.Immediate(2.));

Warning

Note that any of these additional parameters only work with audio defined in Audioware.

e.g. you cannot use a fade-in tween with non-reexported vanilla audio, see below.

Tip

If you want to use vanilla audio with Audioware, you can still convert + export them from WolvenKit as described in their Wiki, then re-define them normally in your manifest.

โš ๏ธ make sure to use a supported audio format

YouTube demo

Going further

Combined with Codeware, you can e.g. quickly create atmosphere like so:

  Redscript
let weather = GameInstance.GetWeatherSystem(game);
weather.SetWeather(n"24h_weather_rain", 20.0, 9u);
GameInstance.GetAudioSystemExt(game).Play(n"milles_feuilles");

YouTube demo

AudioSettingsExt

Earlier we saw that settings can be defined in manifest, but these settings can also be specified in scripts:

  Redscript
// builder is a mutable ref
let builder: ref<AudioSettingsExtBuilder> = AudioSettingsExtBuilder.Create();
// it supports the same settings as definable in manifest, except start_position
builder.SetFadeInTween(ElasticTween.ImmediateIn(5.0, 0.25));
builder.SetPanning(0.3);
builder.SetPlaybackRate(1.1);
builder.SetVolume(0.9);
// once built it returns an immutable ref with different type
let settings: ref<AudioSettingsExt> = builder.Build();

GameInstance
.GetAudioSystemExt(game)
.Play(n"still_dre", GetPlayer(game).GetEntityID(), n"V", scnDialogLineType.Regular, settings);

Alternate builder shorter syntax click to open

The AudioSettingsExtBuilder also accepts a shorter syntax:

GameInstance
    .GetAudioSystemExt(game)
    .Play(
        n"still_dre",
        GetPlayer(game).GetEntityID(),
        n"V",
        scnDialogLineType.Regular, 
        AudioSettingsExtBuilder.Create()
            .WithFadeInTween(ElasticTween.ImmediateIn(5.0, 0.25))
            .WithPanning(0.3)
            .WithPlaybackRate(1.1)
            .WithVolume(0.9)
            .Build()
    );

YouTube demo

Parameters

Audioware exposes the following parameters.

Reverb Mix

Allows to alter reverb like e.g. when in a cavern.

  Redscript
let value: Float; // reverb can be between 0.0 and 1.0 (inclusive)
GameInstance.GetBlackboardSystem(game)
    .Get(GetAllBlackboardDefs().Audioware_Settings)
    .SetFloat(GetAllBlackboardDefs().Audioware_Settings.ReverbMix, value, true);

Routing

This preset only affects audio played on sfx, onos and voices.

Important

Keep it mind that forgetting to reset reverb to normal once finished will annoy players.

For this very reason, reverb is automatically reset on each save load.

YouTube demo

Preset

Allows to alter frequencies like e.g. underwater or on the phone.

Integration

Whenever V dives into water this preset will be automatically set to Preset.Underwater, and switched back to Preset.None whenever V eventually reaches the surface.

You can also set it manually, if needed:

  Redscript
let value: Preset; // possible values: None, Underwater, OnThePhone
GameInstance.GetBlackboardSystem(game)
    .Get(GetAllBlackboardDefs().Audioware_Settings)
    .SetInt(GetAllBlackboardDefs().Audioware_Settings.AudioPreset, value, true);

Routing

This preset only affects audio played on sfx, onos and voices.

Important

Forgetting to reset preset to Preset.None once finished will ruin players immersion.

For this very reason, preset is automatically reset on each save load.

YouTube demo

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).

Docs

The traditional Rust docs can be found here๐Ÿฆ€, but they are still being written and rather incomplete at the moment.

It merely contains implementation details, so if you're more interested in using Audioware right away please head back to the Developer Guide.

Integration

How well engine matches our expectations when it comes to integrate seamlessly with Cyberpunk 2077.

Let's review what you get for free.

๐Ÿ”‰ Game volume settings

We've already seen that custom audio are affected by player's game volume settings.

โฏ๏ธ Dynamic pause/resume when in menus

All audios will be properly paused when entering any menu,
and resumed when back in-game.

Resuming fading-out sounds

Because the resume function in the engine simply resume any non-stopped sound,
sound(s) that were currently stopping with a fading-out will be entirely resumed,
not resuming their fading out as you could expect.

Providing this feature out-of-the-box requires keeping track of more state, so it is not currently implemented.

But you can still do it anyway

Remember that nothing prevents you to use AudioSystem / AudioSystemExt while in menu, so you can work around this limitation and implement your own logic there.

๐ŸŠโ€โ™‚๏ธ Dynamic underwater preset

As previously stated, audio will dynamically have its frequencies adjusted by Underwater preset whenever V enter or exit water, for the tracks where it makes sense.

This is currently not implemented for cars.

๐Ÿงน Clean game sessions

Spatial scene along with its emitters, every track and currently playing sounds will be completely stopped and reset on every save load.

You don't need to worry about memory leaks.