2024-07-02 22:56:53 +07:00
|
|
|
|
using System.IO;
|
2024-01-28 18:37:24 +07:00
|
|
|
|
using Content.Shared._White;
|
|
|
|
|
|
using Content.Shared._White.TTS;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
using Robust.Client.Audio;
|
2024-07-02 22:56:53 +07:00
|
|
|
|
using Robust.Shared.Audio;
|
|
|
|
|
|
using Robust.Shared.Audio.Components;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
using Robust.Shared.Configuration;
|
2024-07-02 22:56:53 +07:00
|
|
|
|
// ReSharper disable InconsistentNaming
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-01-28 17:32:55 +07:00
|
|
|
|
namespace Content.Client._White.TTS;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Plays TTS audio in world
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public sealed class TTSSystem : EntitySystem
|
|
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
[Dependency] private readonly IAudioManager _audioManager = default!;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
2024-07-02 22:56:53 +07:00
|
|
|
|
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-04-20 12:38:13 +07:00
|
|
|
|
private float _volume;
|
2024-07-02 22:56:53 +07:00
|
|
|
|
private readonly Dictionary<EntityUid, AudioComponent> _currentlyPlaying = new();
|
|
|
|
|
|
private readonly Dictionary<EntityUid, Queue<AudioStreamWithParams>> _enquedStreams = new();
|
|
|
|
|
|
|
|
|
|
|
|
// Same as Server.ChatSystem.VoiceRange
|
|
|
|
|
|
private const float VoiceRange = 10;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
|
{
|
|
|
|
|
|
_cfg.OnValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged, true);
|
|
|
|
|
|
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Shutdown()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Shutdown();
|
|
|
|
|
|
_cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged);
|
2024-07-02 22:56:53 +07:00
|
|
|
|
ClearQueues();
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void FrameUpdate(float frameTime)
|
|
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
foreach (var (uid, audioComponent) in _currentlyPlaying)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (audioComponent is { Running: true, Playing: true })
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (!_enquedStreams.TryGetValue(uid, out var queue))
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
continue;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (!queue.TryDequeue(out var toPlay))
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-04-20 12:38:13 +07:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var audio = _audioSystem.PlayEntity(toPlay.Stream, uid, toPlay.Params);
|
|
|
|
|
|
if (!audio.HasValue)
|
2024-04-20 12:38:13 +07:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
continue;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
2024-04-20 12:38:13 +07:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
_currentlyPlaying[uid] = audio.Value.Component;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnTtsVolumeChanged(float volume)
|
|
|
|
|
|
{
|
|
|
|
|
|
_volume = volume;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnPlayTTS(PlayTTSEvent ev)
|
|
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
PlayTTS(GetEntity(ev.Uid), ev.Data, ev.BoostVolume ? _volume + 5 : _volume);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
public void PlayTTS(EntityUid uid, byte[] data, float volume)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (_volume <= -20f)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
return;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var stream = CreateAudioStream(data);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var audioParams = new AudioParams
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
Volume = volume,
|
|
|
|
|
|
MaxDistance = VoiceRange
|
|
|
|
|
|
};
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var audioStream = new AudioStreamWithParams(stream, audioParams);
|
|
|
|
|
|
EnqueueAudio(uid, audioStream);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
public void StopCurrentTTS(EntityUid uid)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (!_currentlyPlaying.TryGetValue(uid, out var audio))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
_audioSystem.Stop(audio.Owner);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
private void EnqueueAudio(EntityUid uid, AudioStreamWithParams audioStream)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (!_currentlyPlaying.ContainsKey(uid))
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var audio = _audioSystem.PlayEntity(audioStream.Stream, uid, audioStream.Params);
|
|
|
|
|
|
if (!audio.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
_currentlyPlaying[uid] = audio.Value.Component;
|
|
|
|
|
|
return;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
if (_enquedStreams.TryGetValue(uid, out var queue))
|
|
|
|
|
|
{
|
|
|
|
|
|
queue.Enqueue(audioStream);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
return;
|
2024-07-02 22:56:53 +07:00
|
|
|
|
}
|
2023-04-27 08:03:44 +06:00
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
queue = new Queue<AudioStreamWithParams>();
|
|
|
|
|
|
queue.Enqueue(audioStream);
|
|
|
|
|
|
_enquedStreams[uid] = queue;
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
private void ClearQueues()
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
foreach (var (_, queue) in _enquedStreams)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
queue.Clear();
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
private AudioStream CreateAudioStream(byte[] data)
|
2023-04-27 08:03:44 +06:00
|
|
|
|
{
|
2024-07-02 22:56:53 +07:00
|
|
|
|
var dataStream = new MemoryStream(data) { Position = 0 };
|
|
|
|
|
|
return _audioManager.LoadAudioOggVorbis(dataStream);
|
2023-04-27 08:03:44 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 22:56:53 +07:00
|
|
|
|
private record AudioStreamWithParams(AudioStream Stream, AudioParams Params);
|
2024-04-20 12:38:13 +07:00
|
|
|
|
}
|