-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Port] TTS #121
[Port] TTS #121
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,15 @@ | |
<Control HorizontalExpand="True"/> | ||
<OptionButton Name="SexButton" HorizontalAlignment="Right" /> | ||
</BoxContainer> | ||
<!--WD EDIT START--> | ||
<!--TTS--> | ||
<BoxContainer HorizontalExpand="True"> | ||
<Label Text="{Loc 'humanoid-profile-editor-voice-label'}" /> | ||
<Control HorizontalExpand="True"/> | ||
<OptionButton Name="VoiceButton" HorizontalAlignment="Right" /> | ||
<Button Name="VoicePlayButton" Text="▶" MaxWidth="80" /> | ||
</BoxContainer> | ||
<!--WD EDIT END--> | ||
Comment on lines
+83
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Based on the gathered information, I can now provide the final response: Voice playback implementation needs error handling improvements The current implementation lacks proper error handling for several critical scenarios:
🔗 Analysis chainVerify voice playback functionality. Since the PR description mentions that testing wasn't possible due to API unavailability, we should ensure proper error handling is implemented. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Check for error handling in voice playback implementation
# Look for error handling in the voice playback implementation
rg -A 5 "VoicePlayButton" --type cs
# Check for TTSManager integration
rg -A 5 "TTSManager" --type cs
# Look for any exception handling related to TTS
ast-grep --pattern 'try {
$$$
tts$$$
$$$
} catch ($$$) {
$$$
}'
Length of output: 5134 Script: #!/bin/bash
# Let's check the PlayTTS implementation and error handling
# Check the PlayTTS method implementation
rg -A 10 "PlayTTS\(\)" --type cs
# Look for error handling in TTS-related files
rg -A 5 "catch|error|Exception" Content.Client/_White/TTS/
# Check TTSSystem implementation for error handling
rg -A 10 "TTSSystem" --type cs --type-add cs:*.cs
Length of output: 6831 Script: #!/bin/bash
# Let's check the TTSManager implementation for error handling during requests
# Check TTSManager's RequestTTS implementation
rg -A 15 "RequestTTS" --type cs
# Look for network-related error handling
rg -A 10 "NetManager|NetworkManager" Content.Client/_White/TTS/
# Check for any audio-related error handling
rg -A 10 "AudioComponent|IAudioManager" Content.Client/_White/TTS/
Length of output: 7512 |
||
<!-- Pronouns --> | ||
<BoxContainer HorizontalExpand="True"> | ||
<Label Text="{Loc 'humanoid-profile-editor-pronouns-label'}" /> | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -149,6 +149,14 @@ public HumanoidProfileEditor( | |||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
#endregion Sex | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// WD EDIT START | ||||||||||||||||||||||||||||||||||||||||||||
#region Voice | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
InitializeVoice(); | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
#endregion | ||||||||||||||||||||||||||||||||||||||||||||
// WD EDIT END | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+152
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for voice initialization. The voice initialization block should include try-catch error handling to gracefully handle any initialization failures. // WD EDIT START
#region Voice
+ try {
InitializeVoice();
+ } catch (Exception ex) {
+ Logger.Error($"Failed to initialize TTS voices: {ex}");
+ }
#endregion
// WD EDIT END 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
#region Age | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
AgeEdit.OnTextChanged += args => | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -636,6 +644,7 @@ public void SetProfile(HumanoidCharacterProfile? profile, int? slot) | |||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
UpdateNameEdit(); | ||||||||||||||||||||||||||||||||||||||||||||
UpdateSexControls(); | ||||||||||||||||||||||||||||||||||||||||||||
UpdateTTSVoicesControls(); // WD EDIT | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Implementation of The implementation shows that the method:
However, there are a few issues:
🔗 Analysis chainVerify the implementation of The method is called after sex changes and during profile updates, suggesting that voice options may be sex-dependent. However:
Also applies to: 1134-1134 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Search for the UpdateTTSVoicesControls implementation
ast-grep --pattern 'private void UpdateTTSVoicesControls() {
$$$
}'
Length of output: 71 Script: #!/bin/bash
# Let's try a broader search pattern to find the method implementation
rg -l "UpdateTTSVoicesControls"
# Then get the content of files containing this method
rg "UpdateTTSVoicesControls" -A 10
Length of output: 2924 Script: #!/bin/bash
# Let's see the complete implementation of UpdateTTSVoicesControls
rg -A 20 "private void UpdateTTSVoicesControls\(\)" Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs
# Also check for VoiceButton declaration and _voiceList
rg "VoiceButton|_voiceList" Content.Client/_White/TTS/HumanoidProfileEditor.TTS.cs
Length of output: 1451 |
||||||||||||||||||||||||||||||||||||||||||||
UpdateGenderControls(); | ||||||||||||||||||||||||||||||||||||||||||||
UpdateSkinColor(); | ||||||||||||||||||||||||||||||||||||||||||||
UpdateSpawnPriorityControls(); | ||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1129,10 +1138,19 @@ private void SetSex(Sex newSex) | |||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
UpdateGenderControls(); | ||||||||||||||||||||||||||||||||||||||||||||
Markings.SetSex(newSex); | ||||||||||||||||||||||||||||||||||||||||||||
UpdateTTSVoicesControls(); // WD EDIT | ||||||||||||||||||||||||||||||||||||||||||||
ReloadProfilePreview(); | ||||||||||||||||||||||||||||||||||||||||||||
SetDirty(); | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
// WD EDIT START | ||||||||||||||||||||||||||||||||||||||||||||
private void SetVoice(string newVoice) | ||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||
Profile = Profile?.WithVoice(newVoice); | ||||||||||||||||||||||||||||||||||||||||||||
IsDirty = true; | ||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||
// WD EDIT END | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1146
to
+1153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation for voice parameter. The
private void SetVoice(string newVoice)
{
+ if (string.IsNullOrEmpty(newVoice))
+ return;
+
+ // Add validation to check if newVoice is in the list of available voices
+ if (!_availableVoices.Contains(newVoice))
+ return;
+
Profile = Profile?.WithVoice(newVoice);
IsDirty = true;
}
Comment on lines
+1146
to
+1153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and documentation for SetVoice method. The SetVoice method lacks parameter validation and XML documentation comments. + /// <summary>
+ /// Updates the profile's voice setting.
+ /// </summary>
+ /// <param name="newVoice">The new voice identifier to set. Must not be null or empty.</param>
private void SetVoice(string newVoice)
{
+ if (string.IsNullOrEmpty(newVoice))
+ throw new ArgumentException("Voice identifier cannot be null or empty", nameof(newVoice));
+
Profile = Profile?.WithVoice(newVoice);
IsDirty = true;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
private void SetGender(Gender newGender) | ||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||
Profile = Profile?.WithGender(newGender); | ||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -48,6 +48,21 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Label Name="AmbientMusicVolumeLabel" MinSize="48 0" Align="Right" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Control MinSize="4 0"/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</BoxContainer> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<!--WD EDIT START--> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Label Text="{Loc 'ui-options-tts-volume'}" HorizontalExpand="True" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Control MinSize="8 0" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Slider Name="TtsVolumeSlider" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MinValue="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MaxValue="200" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HorizontalExpand="True" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+56
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Normalize the volume slider maximum value. The TTS volume slider has a maximum value of 200, while all other volume controls use 100. This inconsistency might confuse users and complicate volume management. - MaxValue="200"
+ MaxValue="100" 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MinSize="80 0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Rounded="True" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Control MinSize="8 0" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Label Name="TtsVolumeLabel" MinSize="48 0" Align="Right" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Control MinSize="4 0" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</BoxContainer> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<!--WD EDIT END--> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+51
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification 🛠️ Refactor suggestion Volume slider range should be 100, not 200 The codebase evidence shows that the TTS volume slider value is divided by 100 in the code and uses a multiplier of 1.0, consistent with other volume controls: _cfg.SetCVar(WhiteCVars.TtsVolume, TtsVolumeSlider.Value / 100f * ContentAudioSystem.TTSMultiplier); The MaxValue should be changed to 100 to match:
- MaxValue="200"
+ MaxValue="100" 🔗 Analysis chainConsider standardizing the volume slider range. The TTS volume slider has a maximum value of 200, while all other volume sliders in the file use a maximum value of 100. This inconsistency might:
Let's check if there's a specific reason for this range difference: Consider one of these approaches:
- MaxValue="200"
+ MaxValue="100"
MaxValue="200"
+ ToolTip="{Loc 'ui-options-tts-volume-extended-range-tooltip'}" 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for TTSMultiplier or volume-related constants
rg -A 2 "TTSMultiplier|VolumeMultiplier"
Length of output: 3749
Comment on lines
+51
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider aligning TTS volume range with other sliders. While the implementation follows the UI pattern well, the TTS volume slider uses a range of 0-200 while all other volume sliders use 0-100. This inconsistency might confuse users. Consider this change: <Slider Name="TtsVolumeSlider"
MinValue="0"
- MaxValue="200"
+ MaxValue="100"
HorizontalExpand="True"
MinSize="80 0"
Rounded="True" /> If higher volume range is necessary for TTS, consider applying the amplification in the audio system rather than exposing it in the UI. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<BoxContainer Orientation="Horizontal" Margin="5 0 0 0"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Label Text="{Loc 'ui-options-ambience-volume'}" HorizontalExpand="True" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Control MinSize="8 0" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using Content.Client.Audio; | ||
using Content.Shared._White; | ||
using Content.Shared.CCVar; | ||
using Robust.Client.Audio; | ||
using Robust.Client.AutoGenerated; | ||
|
@@ -40,6 +41,7 @@ public AudioTab() | |
LobbyVolumeSlider, | ||
InterfaceVolumeSlider, | ||
AnnouncerVolumeSlider, | ||
TtsVolumeSlider, // WD EDIT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add TtsVolumeSlider to DetachUpdateChangesHandler The TtsVolumeSlider is registered in AttachUpdateChangesHandler but missing from DetachUpdateChangesHandler. This inconsistency could lead to memory leaks or event handler issues. Add TtsVolumeSlider to the DetachUpdateChangesHandler parameters: DetachUpdateChangesHandler(
MasterVolumeSlider,
MidiVolumeSlider,
AmbientMusicVolumeSlider,
AmbienceVolumeSlider,
AmbienceSoundsSlider,
LobbyVolumeSlider,
InterfaceVolumeSlider,
AnnouncerVolumeSlider,
+ TtsVolumeSlider,
LobbyMusicCheckBox,
RestartSoundsCheckBox,
EventMusicCheckBox,
AnnouncerDisableMultipleSoundsCheckBox,
AdminSoundsCheckBox
); Also applies to: 82-95 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add TtsVolumeSlider to DetachUpdateChangesHandler. The TtsVolumeSlider is added to AttachUpdateChangesHandler but missing from DetachUpdateChangesHandler. This asymmetry could lead to memory leaks as event handlers aren't properly cleaned up on disposal. Add TtsVolumeSlider to DetachUpdateChangesHandler parameters: InterfaceVolumeSlider,
AnnouncerVolumeSlider,
+ TtsVolumeSlider,
|
||
|
||
LobbyMusicCheckBox, | ||
RestartSoundsCheckBox, | ||
|
@@ -125,6 +127,7 @@ private void OnApplyButtonPressed(BaseButton.ButtonEventArgs args) | |
_cfg.SetCVar(CCVars.LobbyMusicVolume, LobbyVolumeSlider.Value / 100f * ContentAudioSystem.LobbyMultiplier); | ||
_cfg.SetCVar(CCVars.InterfaceVolume, InterfaceVolumeSlider.Value / 100f * ContentAudioSystem.InterfaceMultiplier); | ||
_cfg.SetCVar(CCVars.AnnouncerVolume, AnnouncerVolumeSlider.Value / 100f * ContentAudioSystem.AnnouncerMultiplier); | ||
_cfg.SetCVar(WhiteCVars.TtsVolume, TtsVolumeSlider.Value / 100f * ContentAudioSystem.TTSMultiplier); // WD EDIT | ||
|
||
_cfg.SetCVar(CCVars.MaxAmbientSources, (int)AmbienceSoundsSlider.Value); | ||
|
||
|
@@ -151,6 +154,7 @@ private void Reset() | |
LobbyVolumeSlider.Value = _cfg.GetCVar(CCVars.LobbyMusicVolume) * 100f / ContentAudioSystem.LobbyMultiplier; | ||
InterfaceVolumeSlider.Value = _cfg.GetCVar(CCVars.InterfaceVolume) * 100f / ContentAudioSystem.InterfaceMultiplier; | ||
AnnouncerVolumeSlider.Value = _cfg.GetCVar(CCVars.AnnouncerVolume) * 100f / ContentAudioSystem.AnnouncerMultiplier; | ||
TtsVolumeSlider.Value = _cfg.GetCVar(WhiteCVars.TtsVolume) * 100f / ContentAudioSystem.TTSMultiplier; // WD EDIT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add TTS volume comparison to UpdateChanges The TTS volume reset is implemented correctly, but the Add the following code: var isAnnouncerVolumeSame =
Math.Abs(AnnouncerVolumeSlider.Value - _cfg.GetCVar(CCVars.AnnouncerVolume) * 100f / ContentAudioSystem.AnnouncerMultiplier) < 0.01f;
+var isTtsVolumeSame =
+ Math.Abs(TtsVolumeSlider.Value - _cfg.GetCVar(WhiteCVars.TtsVolume) * 100f / ContentAudioSystem.TTSMultiplier) < 0.01f;
var isAmbientSoundsSame = (int)AmbienceSoundsSlider.Value == _cfg.GetCVar(CCVars.MaxAmbientSources);
// ... other comparisons ...
var isEverythingSame = isMasterVolumeSame && isMidiVolumeSame && isAmbientVolumeSame
&& isAmbientMusicVolumeSame && isAmbientSoundsSame && isLobbySame && isRestartSoundsSame && isEventSame
&& isAnnouncerDisableMultipleSoundsSame && isAdminSoundsSame && isLobbyVolumeSame
- && isInterfaceVolumeSame && isAnnouncerVolumeSame;
+ && isInterfaceVolumeSame && isAnnouncerVolumeSame && isTtsVolumeSame; Also applies to: 189-195 |
||
|
||
AmbienceSoundsSlider.Value = _cfg.GetCVar(CCVars.MaxAmbientSources); | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,77 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Linq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Client._White.TTS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Shared.Preferences; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Shared._White.TTS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Shared.Random; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ReSharper disable InconsistentNaming | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ReSharper disable once CheckNamespace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Content.Client.Lobby.UI; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public sealed partial class HumanoidProfileEditor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private TTSSystem _ttsSystem = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private TTSManager _ttsManager = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private IRobustRandom _random = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private List<TTSVoicePrototype> _voiceList = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private readonly string[] _sampleText = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Помогите, клоун насилует в технических тоннелях!", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"ХоС, ваши сотрудники украли у меня собаку и засунули ее в стиральную машину!", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Агент синдиката украл пиво из бара и взорвался!", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"Врача! Позовите врача!" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve internationalization support for sample text. The sample text is hardcoded in Russian, which limits internationalization. Consider:
- private readonly string[] _sampleText =
- [
- "Помогите, клоун насилует в технических тоннелях!",
- "ХоС, ваши сотрудники украли у меня собаку и засунули ее в стиральную машину!",
- "Агент синдиката украл пиво из бара и взорвался!",
- "Врача! Позовите врача!"
- ];
+ private string[] _sampleText => new[]
+ {
+ Loc.GetString("tts-sample-text-1"),
+ Loc.GetString("tts-sample-text-2"),
+ Loc.GetString("tts-sample-text-3"),
+ Loc.GetString("tts-sample-text-4")
+ };
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider improving sample text handling. The current implementation has several concerns:
Consider:
- private readonly string[] _sampleText =
- [
- "Помогите, клоун насилует в технических тоннелях!",
- "ХоС, ваши сотрудники украли у меня собаку и засунули ее в стиральную машину!",
- "Агент синдиката украл пиво из бара и взорвался!",
- "Врача! Позовите врача!"
- ];
+ private readonly string[] _sampleTextKeys =
+ [
+ "tts-sample-text-1",
+ "tts-sample-text-2",
+ "tts-sample-text-3",
+ "tts-sample-text-4"
+ ];
Comment on lines
+19
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider revising sample text for internationalization and professionalism. The current implementation has several concerns:
Consider implementing this alternative approach: - private readonly string[] _sampleText =
- [
- "Помогите, клоун насилует в технических тоннелях!",
- "ХоС, ваши сотрудники украли у меня собаку и засунули ее в стиральную машину!",
- "Агент синдиката украл пиво из бара и взорвался!",
- "Врача! Позовите врача!"
- ];
+ private string[] GetSampleText() => new[]
+ {
+ Loc.GetString("tts-sample-greeting"),
+ Loc.GetString("tts-sample-weather"),
+ Loc.GetString("tts-sample-announcement"),
+ Loc.GetString("tts-sample-emergency")
+ };
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void InitializeVoice() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_random = IoCManager.Resolve<IRobustRandom>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_ttsManager = IoCManager.Resolve<TTSManager>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_ttsSystem = IoCManager.Resolve<IEntityManager>().System<TTSSystem>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_voiceList = _prototypeManager.EnumeratePrototypes<TTSVoicePrototype>().Where(o => o.RoundStart).ToList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VoiceButton.OnItemSelected += args => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VoiceButton.SelectId(args.Id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SetVoice(_voiceList[args.Id].ID); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VoicePlayButton.OnPressed += _ => { PlayTTS(); }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+43
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix potential issues in voice selection logic. There are several concerns in the voice control update logic:
Apply these fixes: - var firstVoiceChoiceId = 1;
+ var firstVoiceChoiceId = -1; // Use -1 as sentinel value
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)
+ if (firstVoiceChoiceId == -1)
firstVoiceChoiceId = i;
}
+ if (firstVoiceChoiceId == -1)
+ {
+ Logger.Warning("No compatible voices found for profile");
+ return;
+ } 📝 Committable suggestion
Suggested change
Comment on lines
+43
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Fix potential issue with voice selection logic. The
Consider this improved approach: - var firstVoiceChoiceId = 1;
+ var firstValidVoiceId = -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;
+ if (firstValidVoiceId == -1)
+ firstValidVoiceId = i;
}
var voiceChoiceId = _voiceList.FindIndex(x => x.ID == Profile.Voice);
- if (!VoiceButton.TrySelectId(voiceChoiceId) && VoiceButton.TrySelectId(firstVoiceChoiceId))
- SetVoice(_voiceList[firstVoiceChoiceId].ID);
+ if (!VoiceButton.TrySelectId(voiceChoiceId) && firstValidVoiceId != -1 && VoiceButton.TrySelectId(firstValidVoiceId))
+ SetVoice(_voiceList[firstValidVoiceId].ID); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void PlayTTS() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (Profile is null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_ttsSystem.StopCurrentTTS(PreviewDummy); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_ttsManager.RequestTTS(PreviewDummy, _random.Pick(_sampleText), Profile.Voice); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,24 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Shared._White.TTS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Shared.Network; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Content.Client._White.TTS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ReSharper disable once InconsistentNaming | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public sealed class TTSManager | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Dependency] private readonly IClientNetManager _netMgr = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Dependency] private readonly EntityManager _entityManager = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void Initialize() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_netMgr.RegisterNetMessage<MsgRequestTTS>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ReSharper disable once InconsistentNaming | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void RequestTTS(EntityUid uid, string text, string voiceId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var netEntity = _entityManager.GetNetEntity(uid); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var msg = new MsgRequestTTS { Text = text, Uid = netEntity, VoiceId = voiceId }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_netMgr.ClientSendMessage(msg); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Spatison marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+18
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation and error handling. The
Consider implementing these safeguards: - public void RequestTTS(EntityUid uid, string text, string voiceId)
+ public void RequestTTS(EntityUid uid, string text, string voiceId)
+ {
+ if (string.IsNullOrEmpty(text))
+ throw new ArgumentException("Text cannot be null or empty", nameof(text));
+
+ if (string.IsNullOrEmpty(voiceId))
+ throw new ArgumentException("Voice ID cannot be null or empty", nameof(voiceId));
+
+ if (text.Length > 1000) // Add appropriate limit
+ throw new ArgumentException("Text exceeds maximum length", nameof(text));
+
+ try
+ {
+ var netEntity = _entityManager.GetNetEntity(uid);
+ var msg = new MsgRequestTTS { Text = text, Uid = netEntity, VoiceId = voiceId };
+ _netMgr.ClientSendMessage(msg);
+ }
+ catch (Exception ex)
+ {
+ // Consider logging the error
+ throw new InvalidOperationException("Failed to send TTS request", ex);
+ }
+ } 📝 Committable suggestion
Suggested change
Comment on lines
+17
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add input validation and error handling. The
+ /// <summary>
+ /// Requests a TTS message to be played for the specified entity.
+ /// </summary>
+ /// <param name="uid">The entity to play the TTS for</param>
+ /// <param name="text">The text to convert to speech (max 1000 characters)</param>
+ /// <param name="voiceId">The voice identifier (format: language-voice, e.g., "en-US-1")</param>
+ /// <exception cref="ArgumentException">Thrown when inputs are invalid</exception>
public void RequestTTS(EntityUid uid, string text, string voiceId)
{
+ if (string.IsNullOrEmpty(text))
+ throw new ArgumentException("Text cannot be empty", nameof(text));
+ if (string.IsNullOrEmpty(voiceId))
+ throw new ArgumentException("VoiceId cannot be empty", nameof(voiceId));
+ if (text.Length > 1000)
+ throw new ArgumentException("Text exceeds maximum length of 1000 characters", nameof(text));
+
var netEntity = _entityManager.GetNetEntity(uid);
- var msg = new MsgRequestTTS { Text = text, Uid = netEntity, VoiceId = voiceId };
- _netMgr.ClientSendMessage(msg);
+ try {
+ var msg = new MsgRequestTTS { Text = text.Trim(), Uid = netEntity, VoiceId = voiceId };
+ _netMgr.ClientSendMessage(msg);
+ } catch (Exception e) {
+ Logger.ErrorS("tts", e, "Failed to send TTS request");
+ throw;
+ }
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,130 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.IO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Shared._White; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Content.Shared._White.TTS.Events; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Client.Audio; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Shared.Audio; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Shared.Audio.Components; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Robust.Shared.Configuration; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Content.Client._White.TTS; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// ReSharper disable InconsistentNaming | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public sealed class TTSSystem : EntitySystem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Dependency] private readonly IAudioManager _audioManager = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Dependency] private readonly IConfigurationManager _cfg = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Dependency] private readonly AudioSystem _audioSystem = default!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private float _volume; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public override void Initialize() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_cfg.OnValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged, true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SubscribeNetworkEvent<PlayTTSEvent>(OnPlayTTS); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public override void Shutdown() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
base.Shutdown(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_cfg.UnsubValueChanged(WhiteCVars.TtsVolume, OnTtsVolumeChanged); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ClearQueues(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public override void FrameUpdate(float frameTime) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach (var (uid, audioComponent) in _currentlyPlaying) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!Deleted(uid) && audioComponent is { Running: true, Playing: true } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|| !_enquedStreams.TryGetValue(uid, out var queue) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|| !queue.TryDequeue(out var toPlay)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+43
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Logical error in the conditional statement within 'FrameUpdate' The use of logical OR ( Apply this diff to correct the conditional logic: - if (!Deleted(uid) && audioComponent is { Running: true, Playing: true }
- || !_enqueuedStreams.TryGetValue(uid, out var queue)
- || !queue.TryDequeue(out var toPlay))
+ if ((!Deleted(uid) && audioComponent is { Running: true, Playing: true })
+ || (!_enqueuedStreams.TryGetValue(uid, out var queue))
+ || (!queue.TryDequeue(out var toPlay)))
continue; Alternatively, refactor the condition for better readability: if ((!Deleted(uid) && audioComponent.Running && audioComponent.Playing))
continue;
if (!_enqueuedStreams.TryGetValue(uid, out var queue))
continue;
if (!queue.TryDequeue(out var toPlay))
continue; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var audio = _audioSystem.PlayEntity(toPlay.Stream, uid, toPlay.Params); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!audio.HasValue) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_currentlyPlaying[uid] = audio.Value.Component; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+42
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Clean up The Modify the public override void FrameUpdate(float frameTime)
{
+ var uidsToRemove = new List<EntityUid>();
foreach (var (uid, audioComponent) in _currentlyPlaying)
{
- if (!Deleted(uid) && audioComponent is { Running: true, Playing: true }
+ if (Deleted(uid) || audioComponent is not { Running: true, Playing: true })
+ {
+ uidsToRemove.Add(uid);
+ continue;
+ }
if (!_enqueuedStreams.TryGetValue(uid, out var queue)
|| !queue.TryDequeue(out var toPlay))
continue;
var audio = _audioSystem.PlayEntity(toPlay.Stream, uid, toPlay.Params);
if (!audio.HasValue)
continue;
_currentlyPlaying[uid] = audio.Value.Component;
}
+ foreach (var uid in uidsToRemove)
+ {
+ _currentlyPlaying.Remove(uid);
+ _enqueuedStreams.Remove(uid);
+ }
} This ensures that entries for completed audio are removed, preventing potential memory leaks. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void OnTtsVolumeChanged(float volume) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_volume = volume; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void OnPlayTTS(PlayTTSEvent ev) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PlayTTS(GetEntity(ev.Uid), ev.Data, ev.BoostVolume ? _volume + 5 : _volume); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect parameter passed to The Apply this diff to fix the issue: - PlayTTS(GetEntity(ev.Uid), ev.Data, ev.BoostVolume ? _volume + 5 : _volume);
+ PlayTTS(ev.Uid, ev.Data, ev.BoostVolume ? _volume + 5 : _volume); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void PlayTTS(EntityUid uid, byte[] data, float volume) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (_volume <= -20f) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+67
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent volume check using In the Apply this diff to correct the volume check: -public void PlayTTS(EntityUid uid, byte[] data, float volume)
-{
- if (_volume <= -20f)
+public void PlayTTS(EntityUid uid, byte[] data, float volume)
+{
+ if (volume <= -20f)
return; This ensures the method behaves correctly based on the actual volume being used. 📝 Committable suggestion
Suggested change
Comment on lines
+68
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Confusion between '_volume' and 'volume' parameters in 'PlayTTS' method The method Consider updating the volume check to use the - if (_volume <= -20f)
+ if (volume <= -20f)
return; This ensures that the method behaves correctly based on the volume specified when calling 📝 Committable suggestion
Suggested change
💡 Codebase verification Based on the search results, I can now provide a final response: Volume threshold of -20f is too restrictive for TTS audio The TTS volume is configured through a client-side CVar with a default value of 0f, and the UI allows users to adjust it through a slider that's scaled appropriately with a TTS multiplier. The -20f threshold appears to be an arbitrary cutoff that could prevent TTS playback even when users have set a low but intentional volume.
🔗 Analysis chainVerify the volume threshold logic in 'PlayTTS' The condition Run the following script to check where This will help ensure that the volume logic is consistent and that users can adjust the volume as expected. This will help us understand the TTS volume configuration and verify if -20f is a well-defined threshold. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Verify the usage of '_volume' in relation to volume settings.
# Search for all assignments to '_volume' and references in the codebase
rg '_volume' -A 3 -B 3
# Check the default and minimum volume settings in configuration files
rg 'TtsVolume' **/*.cs
Length of output: 12770 Script: #!/bin/bash
# Search for TTS volume related settings and configurations
rg -A 3 -B 3 'TtsVolume|tts.*volume' --type cs
# Search for volume-related constants or thresholds in audio systems
ast-grep --pattern 'const float $_ = -20'
Length of output: 4250 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+69
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure volume levels remain within acceptable limits. When boosting the volume, there's a risk of exceeding the maximum volume threshold, which could cause audio distortion. Implement a check to cap the volume. Adjust the public void PlayTTS(EntityUid uid, byte[] data, float volume)
{
if (_volume <= -20f)
return;
+ // Cap the volume to a maximum of 0dB
+ if (volume > 0f)
+ volume = 0f;
var stream = CreateAudioStream(data);
var audioParams = new AudioParams
{
Volume = volume,
MaxDistance = VoiceRange
}; This prevents the volume from exceeding the maximum allowable level. Also applies to: 76-78 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var stream = CreateAudioStream(data); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var audioParams = new AudioParams | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Volume = volume, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MaxDistance = VoiceRange | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var audioStream = new AudioStreamWithParams(stream, audioParams); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
EnqueueAudio(uid, audioStream); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void StopCurrentTTS(EntityUid uid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!_currentlyPlaying.TryGetValue(uid, out var audio)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_audioSystem.Stop(audio.Owner); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+86
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Check for null before stopping audio to prevent exceptions In Consider adding a null check: if (!_currentlyPlaying.TryGetValue(uid, out var audio) || audio?.Owner == null)
return;
_audioSystem.Stop(audio.Owner); This ensures the method safely handles cases where the audio component may not be valid. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void EnqueueAudio(EntityUid uid, AudioStreamWithParams audioStream) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!_currentlyPlaying.ContainsKey(uid)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var audio = _audioSystem.PlayEntity(audioStream.Stream, uid, audioStream.Params); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!audio.HasValue) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_currentlyPlaying[uid] = audio.Value.Component; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (_enquedStreams.TryGetValue(uid, out var queue)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
queue.Enqueue(audioStream); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
queue = new Queue<AudioStreamWithParams>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
queue.Enqueue(audioStream); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_enquedStreams[uid] = queue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void ClearQueues() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
foreach (var (_, queue) in _enquedStreams) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
queue.Clear(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private AudioStream CreateAudioStream(byte[] data) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var dataStream = new MemoryStream(data) { Position = 0 }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return _audioManager.LoadAudioOggVorbis(dataStream); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+125
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure The Modify the method to dispose of the stream: -private AudioStream CreateAudioStream(byte[] data)
-{
- var dataStream = new MemoryStream(data) { Position = 0 };
- return _audioManager.LoadAudioOggVorbis(dataStream);
-}
+private AudioStream CreateAudioStream(byte[] data)
+{
+ using var dataStream = new MemoryStream(data) { Position = 0 };
+ return _audioManager.LoadAudioOggVorbis(dataStream);
+} Alternatively, confirm if
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+123
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add exception handling for audio stream creation. The Modify the method to catch exceptions: private AudioStream CreateAudioStream(byte[] data)
{
var dataStream = new MemoryStream(data) { Position = 0 };
- return _audioManager.LoadAudioOggVorbis(dataStream);
+ try
+ {
+ return _audioManager.LoadAudioOggVorbis(dataStream);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorS("tts", $"Failed to load audio stream: {ex.Message}");
+ return null;
+ }
} Ensure calling methods handle the possibility of a 📝 Committable suggestion
Suggested change
Comment on lines
+124
to
+127
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle exceptions when loading audio streams in 'CreateAudioStream' The Consider wrapping the audio loading code in a try-catch block to handle exceptions: private AudioStream CreateAudioStream(byte[] data)
{
var dataStream = new MemoryStream(data) { Position = 0 };
+ try
+ {
return _audioManager.LoadAudioOggVorbis(dataStream);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorS("tts", $"Failed to load audio stream: {ex.Message}");
+ // Handle the exception as appropriate, e.g., return a default stream or null
+ return null;
+ }
} Additionally, update the calling methods to handle a potential
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private record AudioStreamWithParams(AudioStream Stream, AudioParams Params); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
🛠️ Refactor suggestion
The review comment is correct and should be implemented.
The codebase analysis reveals:
The original review suggestions are valid and align with the codebase's patterns. Creating an ITTSManager interface would:
🔗 Analysis chain
Consider registering TTSManager with an interface.
Most other services in this file are registered with interfaces (e.g.,
IParallaxManager
,IChatManager
). Consider creating anITTSManager
interface to:Example implementation:
Additionally, since the PR mentions no API is available for testing:
Let's check if TTSManager is used with dependency injection elsewhere:
Let me check the actual usage of TTSManager in those files to better understand how it's being injected.
Let me check the TTSManager class implementation to see its current structure and determine if it's already implementing any interfaces.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 147
Script:
Length of output: 1113
Script:
Length of output: 8064