Files
wwdpublic/Content.Client/_White/TTS/TTSSystem.cs
Cinkafox 916d889fc4 - add: Bark (#827)
* - add: bark

* - tweak: Bark now in client side

* - add: bark config in options

* - add: migration prepare

* - add: Migrations

* - add: more barks

* - add: bark preference in character profile

* - add: knob

* - add: change value by mouse wheel

* - tweak: optimise WWDP thinks

* - tweak: improve NeoTabContainer optimisation

* - add: limit of barks

* - fix: кролькины фиксы

* - fix: change things in tab id

* Update Content.Client/_White/TTS/TTSSystem.cs

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* - fix: спатисон дурак блин ты сломал что то..

* - fix: спатисонов фиксы

* Update Content.Server/_White/Bark/BarkSystem.cs

* - fix: буковки

* Apply suggestions from code review

---------

Co-authored-by: Spatison <137375981+Spatison@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-09-06 03:37:39 +10:00

127 lines
3.8 KiB
C#

using Content.Shared._White.Bark;
using Content.Shared._White.Bark.Systems;
using Content.Shared._White.CCVar;
using Content.Shared.Chat;
using Content.Shared._White.TTS;
using Content.Shared.GameTicking;
using Robust.Client.Audio;
using Robust.Client.ResourceManagement;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.Utility;
namespace Content.Client._White.TTS;
/// <summary>
/// Plays TTS audio in world
/// </summary>
// ReSharper disable once InconsistentNaming
public sealed class TTSSystem : EntitySystem
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IResourceManager _res = default!;
[Dependency] private readonly AudioSystem _audio = default!;
private ISawmill _sawmill = default!;
private readonly MemoryContentRoot _contentRoot = new();
private ResPath _prefix;
/// <summary>
/// Reducing the volume of the TTS when whispering. Will be converted to logarithm.
/// </summary>
private const float WhisperFade = 4f;
private float _volume = 0.0f;
private ulong _fileIdx = 0;
private static ulong _shareIdx = 0;
private bool _clientSideEnabled;
public override void Initialize()
{
_prefix = ResPath.Root / $"TTS{_shareIdx++}";
_sawmill = Logger.GetSawmill("tts");
_res.AddRoot(_prefix, _contentRoot);
_cfg.OnValueChanged(WhiteCVars.TTSVolume, OnTtsVolumeChanged, true);
_cfg.OnValueChanged(WhiteCVars.VoiceType, OnVoiceTypeChanged, true);
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestart);
}
private void OnRoundRestart(RoundRestartCleanupEvent ev)
{
_contentRoot.Clear();
}
public override void Shutdown()
{
base.Shutdown();
_cfg.UnsubValueChanged(WhiteCVars.TTSVolume, OnTtsVolumeChanged);
_cfg.UnsubValueChanged(WhiteCVars.VoiceType, OnVoiceTypeChanged);
_contentRoot.Dispose();
}
public void RequestGlobalTTS(VoiceRequestType text, string voiceId)
{
RaiseNetworkEvent(new RequestPreviewTTSEvent(voiceId));
}
private void OnTtsVolumeChanged(float volume)
{
_volume = volume;
}
private void OnVoiceTypeChanged(CharacterVoiceType voiceType)
{
_clientSideEnabled = voiceType == CharacterVoiceType.TTS;
}
private void OnPlayTTS(PlayTTSEvent ev)
{
if(!_clientSideEnabled)
return;
_sawmill.Verbose($"Play TTS audio {ev.Data.Length} bytes from {ev.SourceUid} entity");
var filePath = new ResPath($"{_fileIdx++}.ogg");
_contentRoot.AddOrUpdateFile(filePath, ev.Data);
var audioResource = new AudioResource();
audioResource.Load(IoCManager.Instance!, _prefix / filePath);
var audioParams = AudioParams.Default
.WithVolume(AdjustVolume(ev.IsWhisper))
.WithMaxDistance(AdjustDistance(ev.IsWhisper));
if (ev.SourceUid != null)
{
var sourceUid = GetEntity(ev.SourceUid.Value);
if(sourceUid.IsValid())
_audio.PlayEntity(audioResource.AudioStream, sourceUid, null, audioParams);
}
else
{
_audio.PlayGlobal(audioResource.AudioStream, null, audioParams);
}
_contentRoot.RemoveFile(filePath);
}
private float AdjustVolume(bool isWhisper)
{
var volume = SharedAudioSystem.GainToVolume(_volume);
if (isWhisper)
volume -= SharedAudioSystem.GainToVolume(WhisperFade);
return volume;
}
private float AdjustDistance(bool isWhisper)
{
return isWhisper ? SharedChatSystem.WhisperMuffledRange : SharedChatSystem.VoiceRange;
}
}