Getting started
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
- grab Audioware latest release and unzip it in root game folder.
- make sure you have both Codeware 1.11.1+ and TweakXL 1.10.2+ installed too.
๐ 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:
version: 1.0.0
sfx:
my_custom_audio: some.mp3 # accepts most common formats like .wav / .ogg / .mp3 / .flac
โฌโ.ห Use in-game
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.
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.
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.
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:
But let's process to next chapter to see how it can be used, and what it can currently do for you.
vanilla describes everything belonging to the original game, as opposed to further modifications or mods made by the community.
natively in the sense that tool, assets and game itself speaks the exact same language leading to seamless integration.
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:
- define your audios in Manifest(s): see how to further describe your audio assets along optional settings and metadata.
- 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 YAML
1 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 .yml
1 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
orr6\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.
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:
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
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.
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.
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).
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.
Each audio file is briefly preloaded on game startup to make sure they will play just fine during your game session.
Each setting defined alongside audios must be valid.
e.g. specifying a
start_position
further than audio total duration is not!
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.
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!
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 ๐
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.
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.
my_custom_sfx: ./somewhere/sfx.ogg
Default | Editable? | |
---|---|---|
usage | in-memory | โ |
volume settings | SfxVolume | โ |
Onos
onos
(onomatopeia) is used to define audio with 2 files each, one per gender.
my_custom_ono:
fem: ./somewhere/ono.wav
male: ./somewhere/else/ono.wav
Default | Editable? | |
---|---|---|
usage | in-memory | โ |
volume settings | DialogueVolume | โ |
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.
Default | Editable? | |
---|---|---|
usage | on-demand | โ |
volume settings | DialogueVolume | โ |
Simple Voice
my_simple_voice:
en-us: ./some/voice.wav
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
my_simple_voice:
en-us:
file: ./some/voice.wav
subtitle: "hello world"
Defining subtitle will automatically register them with Codeware Localization and play them alongside audio, for the proper gender and locale(s).
Plural Voice
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."
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.
version: 1.0.0
music:
gorillaz_feel_good_inc: ./feel-good-inc.mp3
Default | Editable? | |
---|---|---|
usage | streaming | โ |
volume settings | MusicVolume | โ |
Settings
Any sound will accept the following settings.
๐๏ธ Usage
This allows to specify how audio will be handled in memory.
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
.
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.
on-demand
The audio is loaded all-at-once each time on-demand, and never kept around.
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.
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:
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
๐ Start time
This will play your audio with a delay.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
start_time: 10s # 10 seconds delay
๐ Start position
This will play your audio further from start.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
start_position: 1s # start playing directly at 1s
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.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
region:
starts: 120ms # starts directly from 1.2s
ends: 8s # ends at 8s
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.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
loop: true
โฉ Playback rate
This will play your audio faster, or slower.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
playback_rate: x0.5 # plays twice as slow
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.
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.
my_custom_audio:
file: ./somewhere/audio.wav
settings:
panning: 0.0 # plays fully on left side
my_custom_audio:
file: ./somewhere/audio.wav
settings:
panning: 1.0 # plays fully on right side
โคด๏ธ Fade-in tween
This will play your audio gradually fading-in.
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)
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.
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.
track | volume |
---|---|
sfx | SfxVolume |
onos | DialogueVolume |
voices | DialogueVolume |
music | MusicVolume |
All audio are always affected by MasterVolume
, as expected.
Parameters
Likewise each track will be affected, or not, by preset and reverb mix.
track | preset | reverb |
---|---|---|
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.
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.
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.
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:
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.));
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.
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
Going further
Combined with Codeware, you can e.g. quickly create atmosphere like so:
let weather = GameInstance.GetWeatherSystem(game);
weather.SetWeather(n"24h_weather_rain", 20.0, 9u);
GameInstance.GetAudioSystemExt(game).Play(n"milles_feuilles");
AudioSettingsExt
Earlier we saw that settings can be defined in manifest, but these settings can also be specified in scripts:
// 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
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()
);
Parameters
Audioware exposes the following parameters.
Reverb Mix
Allows to alter reverb like e.g. when in a cavern.
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);
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.
Preset
Allows to alter frequencies like e.g. underwater or on the phone.
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:
let value: Preset; // possible values: None, Underwater, OnThePhone
GameInstance.GetBlackboardSystem(game)
.Get(GetAllBlackboardDefs().Audioware_Settings)
.SetInt(GetAllBlackboardDefs().Audioware_Settings.AudioPreset, value, true);
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.
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.
if !GameInstance.GetAudioSystemExt(game).IsRegisteredEmitter(emitterID) {
GameInstance.GetAudioSystemExt(game).RegisterEmitter(emitterID);
}
Audio emitter have to be positioned so they can only be Entity or classes inheriting from it like GameObject, devices, vehicles, NPCs, etc.
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
/// 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!
Usage
Then, simply use the OnEmitter
variants of the methods:
// โ ๏ธ 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);
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.
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);
}
}
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.
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.
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.