-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
49 changed files
with
6,336 additions
and
779 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System.Linq; | ||
using Content.Client.Corvax.TTS; | ||
using Content.Client.Lobby; | ||
using Content.Shared.Corvax.TTS; | ||
using Content.Shared.Preferences; | ||
|
||
namespace Content.Client.Lobby.UI; | ||
|
||
public sealed partial class HumanoidProfileEditor | ||
{ | ||
private List<TTSVoicePrototype> _voiceList = new(); | ||
|
||
private void InitializeVoice() | ||
{ | ||
_voiceList = _prototypeManager | ||
.EnumeratePrototypes<TTSVoicePrototype>() | ||
.Where(o => o.RoundStart) | ||
.OrderBy(o => Loc.GetString(o.Name)) | ||
.ToList(); | ||
|
||
VoiceButton.OnItemSelected += args => | ||
{ | ||
VoiceButton.SelectId(args.Id); | ||
SetVoice(_voiceList[args.Id].ID); | ||
}; | ||
|
||
VoicePlayButton.OnPressed += _ => PlayPreviewTTS(); | ||
} | ||
|
||
private void UpdateTTSVoicesControls() | ||
{ | ||
if (Profile is null) | ||
return; | ||
|
||
VoiceButton.Clear(); | ||
|
||
var firstVoiceChoiceId = 1; | ||
for (var i = 0; i < _voiceList.Count; i++) | ||
{ | ||
var voice = _voiceList[i]; | ||
if (!HumanoidCharacterProfile.CanHaveVoice(voice, Profile.Sex)) | ||
continue; | ||
|
||
var name = Loc.GetString(voice.Name); | ||
VoiceButton.AddItem(name, i); | ||
|
||
if (firstVoiceChoiceId == 1) | ||
firstVoiceChoiceId = i; | ||
} | ||
|
||
var voiceChoiceId = _voiceList.FindIndex(x => x.ID == Profile.Voice); | ||
if (!VoiceButton.TrySelectId(voiceChoiceId) && | ||
VoiceButton.TrySelectId(firstVoiceChoiceId)) | ||
{ | ||
SetVoice(_voiceList[firstVoiceChoiceId].ID); | ||
} | ||
} | ||
|
||
private void PlayPreviewTTS() | ||
{ | ||
if (Profile is null) | ||
return; | ||
|
||
_entManager.System<TTSSystem>().RequestPreviewTTS(Profile.Voice); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
using Content.Shared.Chat; | ||
using Content.Shared.Corvax.CCCVars; | ||
using Content.Shared.Corvax.TTS; | ||
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.Corvax.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 static readonly ResPath Prefix = ResPath.Root / "TTS"; | ||
|
||
/// <summary> | ||
/// Reducing the volume of the TTS when whispering. Will be converted to logarithm. | ||
/// </summary> | ||
private const float WhisperFade = 4f; | ||
|
||
/// <summary> | ||
/// The volume at which the TTS sound will not be heard. | ||
/// </summary> | ||
private const float MinimalVolume = -10f; | ||
|
||
private float _volume = 0.0f; | ||
private int _fileIdx = 0; | ||
|
||
public override void Initialize() | ||
{ | ||
_sawmill = Logger.GetSawmill("tts"); | ||
_res.AddRoot(Prefix, _contentRoot); | ||
_cfg.OnValueChanged(CCCVars.TTSVolume, OnTtsVolumeChanged, true); | ||
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS); | ||
} | ||
|
||
public override void Shutdown() | ||
{ | ||
base.Shutdown(); | ||
_cfg.UnsubValueChanged(CCCVars.TTSVolume, OnTtsVolumeChanged); | ||
_contentRoot.Dispose(); | ||
} | ||
|
||
public void RequestPreviewTTS(string voiceId) | ||
{ | ||
RaiseNetworkEvent(new RequestPreviewTTSEvent(voiceId)); | ||
} | ||
|
||
private void OnTtsVolumeChanged(float volume) | ||
{ | ||
_volume = volume; | ||
} | ||
|
||
private void OnPlayTTS(PlayTTSEvent ev) | ||
{ | ||
_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); | ||
_audio.PlayEntity(audioResource.AudioStream, sourceUid, audioParams); | ||
} | ||
else | ||
{ | ||
_audio.PlayGlobal(audioResource.AudioStream, audioParams); | ||
} | ||
|
||
_contentRoot.RemoveFile(filePath); | ||
} | ||
|
||
private float AdjustVolume(bool isWhisper) | ||
{ | ||
var volume = MinimalVolume + SharedAudioSystem.GainToVolume(_volume); | ||
|
||
if (isWhisper) | ||
{ | ||
volume -= SharedAudioSystem.GainToVolume(WhisperFade); | ||
} | ||
|
||
return volume; | ||
} | ||
|
||
private float AdjustDistance(bool isWhisper) | ||
{ | ||
return isWhisper ? SharedChatSystem.WhisperMuffledRange : SharedChatSystem.VoiceRange; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.