diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 7557d9499db..fbd1d76ba3e 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -39,7 +39,7 @@ END TEMPLATE--> ### New features -*None yet* +* Audio ticks-per-second is now capped at 30 by default and controlled via `audio.tick_rate` cvar. ### Bugfixes diff --git a/Robust.Client/Audio/AudioSystem.cs b/Robust.Client/Audio/AudioSystem.cs index e790c8ddd65..2eabb9fbb24 100644 --- a/Robust.Client/Audio/AudioSystem.cs +++ b/Robust.Client/Audio/AudioSystem.cs @@ -37,7 +37,6 @@ public sealed partial class AudioSystem : SharedAudioSystem [Dependency] private readonly IReplayRecordingManager _replayRecording = default!; [Dependency] private readonly IEyeManager _eyeManager = default!; [Dependency] private readonly IResourceCache _resourceCache = default!; - [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IParallelManager _parMan = default!; [Dependency] private readonly IRuntimeLog _runtimeLog = default!; [Dependency] private readonly IAudioInternal _audio = default!; @@ -49,9 +48,10 @@ public sealed partial class AudioSystem : SharedAudioSystem /// Per-tick cache of relevant streams. /// private readonly List<(EntityUid Entity, AudioComponent Component, TransformComponent Xform)> _streams = new(); - private EntityUid? _listenerGrid; private UpdateAudioJob _updateAudioJob; + private float _audioFrameTime; + private float _audioFrameTimeRemaining; private EntityQuery _physicsQuery; @@ -110,9 +110,16 @@ public override void Initialize() Subs.CVar(CfgManager, CVars.AudioAttenuation, OnAudioAttenuation, true); Subs.CVar(CfgManager, CVars.AudioRaycastLength, OnRaycastLengthChanged, true); + Subs.CVar(CfgManager, CVars.AudioTickRate, OnAudioTickRate, true); InitializeLimit(); } + private void OnAudioTickRate(int obj) + { + _audioFrameTime = 1f / obj; + _audioFrameTimeRemaining = MathF.Min(_audioFrameTimeRemaining, _audioFrameTime); + } + private void OnAudioState(EntityUid uid, AudioComponent component, ref AfterAutoHandleStateEvent args) { ApplyAudioParams(component.Params, component); @@ -254,6 +261,13 @@ private void OnRaycastLengthChanged(float value) public override void FrameUpdate(float frameTime) { + _audioFrameTimeRemaining -= frameTime; + + if (_audioFrameTimeRemaining > 0f) + return; + + // Clamp to 0 in case we have a really long frame. + _audioFrameTimeRemaining = MathF.Max(0f, _audioFrameTime + _audioFrameTimeRemaining); var eye = _eyeManager.CurrentEye; var localEntity = _playerManager.LocalEntity; Vector2 listenerVelocity; @@ -277,9 +291,6 @@ public override void FrameUpdate(float frameTime) _streams.Add((uid, comp, xform)); } - _mapManager.TryFindGridAt(ourPos, out var gridUid, out _); - _listenerGrid = gridUid == EntityUid.Invalid ? null : gridUid; - try { _updateAudioJob.OurPosition = ourPos; @@ -332,7 +343,6 @@ private void ProcessStream(EntityUid entity, AudioComponent component, Transform Vector2 worldPos; component.Volume = component.Params.Volume; - Vector2 delta; // Handle grid audio differently by using grid position. if ((component.Flags & AudioFlags.GridAudio) != 0x0) @@ -346,7 +356,7 @@ private void ProcessStream(EntityUid entity, AudioComponent component, Transform } // Max distance check - delta = worldPos - listener.Position; + var delta = worldPos - listener.Position; var distance = delta.Length(); // Out of range so just clip it for us. diff --git a/Robust.Shared/CVars.cs b/Robust.Shared/CVars.cs index be34d829ac4..723e1058152 100644 --- a/Robust.Shared/CVars.cs +++ b/Robust.Shared/CVars.cs @@ -1157,6 +1157,13 @@ protected CVars() public static readonly CVarDef AudioRaycastLength = CVarDef.Create("audio.raycast_length", SharedAudioSystem.DefaultSoundRange, CVar.ARCHIVE | CVar.CLIENTONLY); + /// + /// Tickrate for audio calculations. + /// OpenAL recommends 30TPS. This is to avoid running raycasts every frame especially for high-refresh rate monitors. + /// + public static readonly CVarDef AudioTickRate = + CVarDef.Create("audio.tick_rate", 30, CVar.CLIENTONLY); + public static readonly CVarDef AudioZOffset = CVarDef.Create("audio.z_offset", -5f, CVar.REPLICATED);