Skip to content

Commit

Permalink
Refactor audio system to send collection IDs over the network
Browse files Browse the repository at this point in the history
This is important groundwork for future features such as captioning,
as a caption and other data can be associated with the collection
prototype instead of passing extra data everywhere with the sound.
  • Loading branch information
pontaoski committed Dec 15, 2024
1 parent af4d53f commit ef1b41b
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 93 deletions.
12 changes: 4 additions & 8 deletions Robust.Client/Animations/AnimationTrackPlaySound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,7 @@ public override (int KeyFrameIndex, float FramePlayingTime)
var keyFrame = KeyFrames[keyFrameIndex];

var audioParams = keyFrame.AudioParamsFunc.Invoke();
var audio = new SoundPathSpecifier(keyFrame.Resource)
{
Params = audioParams
};
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>().PlayEntity(audio, Filter.Local(), entity, true);
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<AudioSystem>().PlayEntity(keyFrame.Specifier, Filter.Local(), entity, true, audioParams);
}

return (keyFrameIndex, playingTime);
Expand All @@ -55,7 +51,7 @@ public struct KeyFrame
/// <summary>
/// The RSI state to play when this keyframe gets triggered.
/// </summary>
public readonly string Resource;
public readonly ResolvedSoundSpecifier Specifier;

/// <summary>
/// A function that returns the audio parameter to be used.
Expand All @@ -69,9 +65,9 @@ public struct KeyFrame
/// </summary>
public readonly float KeyTime;

public KeyFrame(string resource, float keyTime, Func<AudioParams>? audioParams = null)
public KeyFrame(ResolvedSoundSpecifier specifier, float keyTime, Func<AudioParams>? audioParams = null)
{
Resource = resource;
Specifier = specifier;
KeyTime = keyTime;
AudioParamsFunc = audioParams ?? (() => AudioParams.Default);
}
Expand Down
100 changes: 55 additions & 45 deletions Robust.Client/Audio/AudioSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,16 @@ public float GetOcclusion(MapCoordinates listener, Vector2 delta, float distance
return occlusion;
}

private bool TryGetAudio(ResolvedSoundSpecifier specifier, [NotNullWhen(true)] out AudioResource? audio)
{
var filename = GetAudioPath(specifier) ?? string.Empty;
if (_resourceCache.TryGetResource(new ResPath(filename), out audio))
return true;

Log.Error($"Server tried to play audio file {filename} which does not exist.");
return false;
}

private bool TryGetAudio(string filename, [NotNullWhen(true)] out AudioResource? audio)
{
if (_resourceCache.TryGetResource(new ResPath(filename), out audio))
Expand All @@ -433,15 +443,15 @@ private bool TryGetAudio(AudioStream stream, [NotNullWhen(true)] out AudioResour
return false;
}

public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string? filename, EntityCoordinates coordinates,
public override (EntityUid Entity, AudioComponent Component)? PlayPvs(ResolvedSoundSpecifier? specifier, EntityCoordinates coordinates,
AudioParams? audioParams = null)
{
return PlayStatic(filename, Filter.Local(), coordinates, true, audioParams);
return PlayStatic(specifier, Filter.Local(), coordinates, true, audioParams);
}

public override (EntityUid Entity, AudioComponent Component)? PlayPvs(string? filename, EntityUid uid, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayPvs(ResolvedSoundSpecifier? specifier, EntityUid uid, AudioParams? audioParams = null)
{
return PlayEntity(filename, Filter.Local(), uid, true, audioParams);
return PlayEntity(specifier, Filter.Local(), uid, true, audioParams);
}

/// <inheritdoc />
Expand Down Expand Up @@ -477,31 +487,31 @@ public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(Soun
/// </summary>
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
/// <param name="audioParams"></param>
private (EntityUid Entity, AudioComponent Component)? PlayGlobal(string? filename, AudioParams? audioParams = null, bool recordReplay = true)
private (EntityUid Entity, AudioComponent Component)? PlayGlobal(ResolvedSoundSpecifier? specifier, AudioParams? audioParams = null, bool recordReplay = true)
{
if (string.IsNullOrEmpty(filename))
if (specifier is null)
return null;

if (recordReplay && _replayRecording.IsRecording)
{
_replayRecording.RecordReplayMessage(new PlayAudioGlobalMessage
{
FileName = filename,
Specifier = specifier,
AudioParams = audioParams ?? AudioParams.Default
});
}

return TryGetAudio(filename, out var audio) ? PlayGlobal(audio, audioParams) : default;
return TryGetAudio(specifier, out var audio) ? PlayGlobal(audio, specifier, audioParams) : default;
}

/// <summary>
/// Play an audio stream globally, without position.
/// </summary>
/// <param name="stream">The audio stream to play.</param>
/// <param name="audioParams"></param>
public (EntityUid Entity, AudioComponent Component)? PlayGlobal(AudioStream stream, AudioParams? audioParams = null)
public (EntityUid Entity, AudioComponent Component)? PlayGlobal(AudioStream stream, ResolvedSoundSpecifier? specifier, AudioParams? audioParams = null)
{
var (entity, component) = CreateAndStartPlayingStream(audioParams, stream);
var (entity, component) = CreateAndStartPlayingStream(audioParams, specifier, stream);
component.Global = true;
component.Source.Global = true;
Dirty(entity, component);
Expand All @@ -513,22 +523,22 @@ public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(Soun
/// </summary>
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
/// <param name="entity">The entity "emitting" the audio.</param>
private (EntityUid Entity, AudioComponent Component)? PlayEntity(string? filename, EntityUid entity, AudioParams? audioParams = null, bool recordReplay = true)
private (EntityUid Entity, AudioComponent Component)? PlayEntity(ResolvedSoundSpecifier? specifier, EntityUid entity, AudioParams? audioParams = null, bool recordReplay = true)
{
if (string.IsNullOrEmpty(filename))
if (specifier is null)
return null;

if (recordReplay && _replayRecording.IsRecording)
{
_replayRecording.RecordReplayMessage(new PlayAudioEntityMessage
{
FileName = filename,
Specifier = specifier,
NetEntity = GetNetEntity(entity),
AudioParams = audioParams ?? AudioParams.Default
});
}

return TryGetAudio(filename, out var audio) ? PlayEntity(audio, entity, audioParams) : default;
return TryGetAudio(specifier, out var audio) ? PlayEntity(audio, entity, specifier, audioParams) : default;
}

/// <summary>
Expand All @@ -537,15 +547,15 @@ public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(Soun
/// <param name="stream">The audio stream to play.</param>
/// <param name="entity">The entity "emitting" the audio.</param>
/// <param name="audioParams"></param>
public (EntityUid Entity, AudioComponent Component)? PlayEntity(AudioStream stream, EntityUid entity, AudioParams? audioParams = null)
public (EntityUid Entity, AudioComponent Component)? PlayEntity(AudioStream stream, EntityUid entity, ResolvedSoundSpecifier? specifier, AudioParams? audioParams = null)
{
if (TerminatingOrDeleted(entity))
{
Log.Error($"Tried to play coordinates audio on a terminating / deleted entity {ToPrettyString(entity)}");
return null;
}

var playing = CreateAndStartPlayingStream(audioParams, stream);
var playing = CreateAndStartPlayingStream(audioParams, specifier, stream);
_xformSys.SetCoordinates(playing.Entity, new EntityCoordinates(entity, Vector2.Zero));

return playing;
Expand All @@ -557,22 +567,22 @@ public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(Soun
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
/// <param name="coordinates">The coordinates at which to play the audio.</param>
/// <param name="audioParams"></param>
private (EntityUid Entity, AudioComponent Component)? PlayStatic(string? filename, EntityCoordinates coordinates, AudioParams? audioParams = null, bool recordReplay = true)
private (EntityUid Entity, AudioComponent Component)? PlayStatic(ResolvedSoundSpecifier? specifier, EntityCoordinates coordinates, AudioParams? audioParams = null, bool recordReplay = true)
{
if (string.IsNullOrEmpty(filename))
if (specifier is null)
return null;

if (recordReplay && _replayRecording.IsRecording)
{
_replayRecording.RecordReplayMessage(new PlayAudioPositionalMessage
{
FileName = filename,
Specifier = specifier,
Coordinates = GetNetCoordinates(coordinates),
AudioParams = audioParams ?? AudioParams.Default
});
}

return TryGetAudio(filename, out var audio) ? PlayStatic(audio, coordinates, audioParams) : default;
return TryGetAudio(specifier, out var audio) ? PlayStatic(audio, coordinates, specifier, audioParams) : default;
}

/// <summary>
Expand All @@ -581,41 +591,41 @@ public override (EntityUid Entity, AudioComponent Component)? PlayPredicted(Soun
/// <param name="stream">The audio stream to play.</param>
/// <param name="coordinates">The coordinates at which to play the audio.</param>
/// <param name="audioParams"></param>
public (EntityUid Entity, AudioComponent Component)? PlayStatic(AudioStream stream, EntityCoordinates coordinates, AudioParams? audioParams = null)
public (EntityUid Entity, AudioComponent Component)? PlayStatic(AudioStream stream, EntityCoordinates coordinates, ResolvedSoundSpecifier? specifier, AudioParams? audioParams = null)
{
if (TerminatingOrDeleted(coordinates.EntityId))
{
Log.Error($"Tried to play coordinates audio on a terminating / deleted entity {ToPrettyString(coordinates.EntityId)}");
return null;
}

var playing = CreateAndStartPlayingStream(audioParams, stream);
var playing = CreateAndStartPlayingStream(audioParams, specifier, stream);
_xformSys.SetCoordinates(playing.Entity, coordinates);
return playing;
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string? filename, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(ResolvedSoundSpecifier? specifier, Filter playerFilter, bool recordReplay, AudioParams? audioParams = null)
{
return PlayGlobal(filename, audioParams);
return PlayGlobal(specifier, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string? filename, Filter playerFilter, EntityUid entity, bool recordReplay, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(ResolvedSoundSpecifier? specifier, Filter playerFilter, EntityUid entity, bool recordReplay, AudioParams? audioParams = null)
{
return PlayEntity(filename, entity, audioParams);
return PlayEntity(specifier, entity, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string? filename, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(ResolvedSoundSpecifier? specifier, Filter playerFilter, EntityCoordinates coordinates, bool recordReplay, AudioParams? audioParams = null)
{
return PlayStatic(filename, coordinates, audioParams);
return PlayStatic(specifier, coordinates, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string? filename, ICommonSession recipient, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(ResolvedSoundSpecifier? specifier, ICommonSession recipient, AudioParams? audioParams = null)
{
return PlayGlobal(filename, audioParams);
return PlayGlobal(specifier, audioParams);
}

public override void LoadStream<T>(Entity<AudioComponent> entity, T stream)
Expand All @@ -629,39 +639,39 @@ public override void LoadStream<T>(Entity<AudioComponent> entity, T stream)
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(string? filename, EntityUid recipient, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayGlobal(ResolvedSoundSpecifier? specifier, EntityUid recipient, AudioParams? audioParams = null)
{
return PlayGlobal(filename, audioParams);
return PlayGlobal(specifier, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string? filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(ResolvedSoundSpecifier? specifier, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
{
return PlayEntity(filename, uid, audioParams);
return PlayEntity(specifier, uid, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(string? filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayEntity(ResolvedSoundSpecifier? specifier, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
{
return PlayEntity(filename, uid, audioParams);
return PlayEntity(specifier, uid, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string? filename, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(ResolvedSoundSpecifier? specifier, ICommonSession recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
{
return PlayStatic(filename, coordinates, audioParams);
return PlayStatic(specifier, coordinates, audioParams);
}

/// <inheritdoc />
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(string? filename, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
public override (EntityUid Entity, AudioComponent Component)? PlayStatic(ResolvedSoundSpecifier? specifier, EntityUid recipient, EntityCoordinates coordinates, AudioParams? audioParams = null)
{
return PlayStatic(filename, coordinates, audioParams);
return PlayStatic(specifier, coordinates, audioParams);
}

private (EntityUid Entity, AudioComponent Component) CreateAndStartPlayingStream(AudioParams? audioParams, AudioStream stream)
private (EntityUid Entity, AudioComponent Component) CreateAndStartPlayingStream(AudioParams? audioParams, ResolvedSoundSpecifier? specifier, AudioStream stream)
{
var audioP = audioParams ?? AudioParams.Default;
var entity = SetupAudio(null, audioP, initialize: false, length: stream.Length);
var entity = SetupAudio(specifier, audioP, initialize: false, length: stream.Length);
LoadStream(entity, stream);
EntityManager.InitializeAndStartEntity(entity);
var comp = entity.Comp;
Expand Down Expand Up @@ -694,17 +704,17 @@ private void ApplyAudioParams(AudioParams audioParams, IAudioSource source)

private void OnEntityCoordinates(PlayAudioPositionalMessage ev)
{
PlayStatic(ev.FileName, GetCoordinates(ev.Coordinates), ev.AudioParams, false);
PlayStatic(ev.Specifier, GetCoordinates(ev.Coordinates), ev.AudioParams, false);
}

private void OnEntityAudio(PlayAudioEntityMessage ev)
{
PlayEntity(ev.FileName, GetEntity(ev.NetEntity), ev.AudioParams, false);
PlayEntity(ev.Specifier, GetEntity(ev.NetEntity), ev.AudioParams, false);
}

private void OnGlobalAudio(PlayAudioGlobalMessage ev)
{
PlayGlobal(ev.FileName, ev.AudioParams, false);
PlayGlobal(ev.Specifier, ev.AudioParams, false);
}

protected override TimeSpan GetAudioLengthImpl(string filename)
Expand Down
Loading

0 comments on commit ef1b41b

Please sign in to comment.