diff --git a/Robovoice.App/AudioOutput.cs b/Robovoice.App/AudioOutput.cs index b9cb923..72c14e0 100644 --- a/Robovoice.App/AudioOutput.cs +++ b/Robovoice.App/AudioOutput.cs @@ -8,7 +8,6 @@ internal sealed class AudioOutput : IDisposable private BufferedWaveProvider? _bufferProvider; private int _sampleRate; private string _deviceName = string.Empty; - private bool _playing; private bool _disposed; public Action? Log { get; set; } @@ -35,7 +34,6 @@ internal sealed class AudioOutput : IDisposable _waveOut.Init(_bufferProvider); _waveOut.PlaybackStopped += OnPlaybackStopped; - _playing = true; _waveOut.Play(); } @@ -60,7 +58,6 @@ internal sealed class AudioOutput : IDisposable private void OnPlaybackStopped(object? sender, StoppedEventArgs e) { - _playing = false; } public void Stop() @@ -74,7 +71,6 @@ internal sealed class AudioOutput : IDisposable } _bufferProvider?.ClearBuffer(); _bufferProvider = null; - _playing = false; } private static int FindDevice(string? deviceName) diff --git a/Robovoice.App/MainForm.Designer.cs b/Robovoice.App/MainForm.Designer.cs index ae078d5..ce17482 100644 --- a/Robovoice.App/MainForm.Designer.cs +++ b/Robovoice.App/MainForm.Designer.cs @@ -1,3 +1,4 @@ +#nullable enable namespace Robovoice.App; partial class MainForm @@ -22,6 +23,15 @@ partial class MainForm private Label lblTextInput = null!; private TextBox txtTextInput = null!; private Button btnSpeakInput = null!; + private Label lblNoise = null!; + private TrackBar trkNoise = null!; + private Label lblNoiseVal = null!; + private Label lblSpeed = null!; + private TrackBar trkSpeed = null!; + private Label lblSpeedVal = null!; + private Label lblNoiseW = null!; + private TrackBar trkNoiseW = null!; + private Label lblNoiseWVal = null!; protected override void Dispose(bool disposing) { @@ -52,6 +62,15 @@ partial class MainForm lblTextInput = new Label(); txtTextInput = new TextBox(); btnSpeakInput = new Button(); + lblNoise = new Label(); + trkNoise = new TrackBar(); + lblNoiseVal = new Label(); + lblSpeed = new Label(); + trkSpeed = new TrackBar(); + lblSpeedVal = new Label(); + lblNoiseW = new Label(); + trkNoiseW = new TrackBar(); + lblNoiseWVal = new Label(); SuspendLayout(); @@ -126,23 +145,86 @@ partial class MainForm lblLineStatus.TextAlign = ContentAlignment.MiddleRight; lblLineStatus.ForeColor = Color.DarkBlue; + // lblNoise + lblNoise.Text = "Noise:"; + lblNoise.Location = new Point(12, 82); + lblNoise.Size = new Size(40, 23); + lblNoise.TextAlign = ContentAlignment.MiddleLeft; + + // trkNoise (0-1000 → 0.0-1.0, default 667) + trkNoise.Location = new Point(52, 78); + trkNoise.Size = new Size(120, 45); + trkNoise.Minimum = 0; + trkNoise.Maximum = 1000; + trkNoise.Value = 667; + trkNoise.TickFrequency = 200; + trkNoise.Orientation = Orientation.Horizontal; + + // lblNoiseVal + lblNoiseVal.Text = "0.667"; + lblNoiseVal.Location = new Point(175, 82); + lblNoiseVal.Size = new Size(35, 23); + lblNoiseVal.TextAlign = ContentAlignment.MiddleLeft; + + // lblSpeed + lblSpeed.Text = "Speed:"; + lblSpeed.Location = new Point(220, 82); + lblSpeed.Size = new Size(40, 23); + lblSpeed.TextAlign = ContentAlignment.MiddleLeft; + + // trkSpeed (50-300 → 0.5-3.0, default 100) + trkSpeed.Location = new Point(260, 78); + trkSpeed.Size = new Size(120, 45); + trkSpeed.Minimum = 50; + trkSpeed.Maximum = 300; + trkSpeed.Value = 100; + trkSpeed.TickFrequency = 50; + trkSpeed.Orientation = Orientation.Horizontal; + + // lblSpeedVal + lblSpeedVal.Text = "1.00"; + lblSpeedVal.Location = new Point(383, 82); + lblSpeedVal.Size = new Size(35, 23); + lblSpeedVal.TextAlign = ContentAlignment.MiddleLeft; + + // lblNoiseW + lblNoiseW.Text = "NoiseW:"; + lblNoiseW.Location = new Point(428, 82); + lblNoiseW.Size = new Size(45, 23); + lblNoiseW.TextAlign = ContentAlignment.MiddleLeft; + + // trkNoiseW (0-1000 → 0.0-1.0, default 800) + trkNoiseW.Location = new Point(475, 78); + trkNoiseW.Size = new Size(120, 45); + trkNoiseW.Minimum = 0; + trkNoiseW.Maximum = 1000; + trkNoiseW.Value = 800; + trkNoiseW.TickFrequency = 200; + trkNoiseW.Orientation = Orientation.Horizontal; + + // lblNoiseWVal + lblNoiseWVal.Text = "0.800"; + lblNoiseWVal.Location = new Point(598, 82); + lblNoiseWVal.Size = new Size(45, 23); + lblNoiseWVal.TextAlign = ContentAlignment.MiddleLeft; + // txtLog - txtLog.Location = new Point(12, 112); + txtLog.Location = new Point(12, 149); txtLog.Size = new Size(800, 310); // lblTextInput lblTextInput.Text = "Text:"; - lblTextInput.Location = new Point(12, 84); + lblTextInput.Location = new Point(12, 121); lblTextInput.Size = new Size(35, 23); lblTextInput.TextAlign = ContentAlignment.MiddleLeft; // txtTextInput - txtTextInput.Location = new Point(50, 81); + txtTextInput.Location = new Point(50, 118); txtTextInput.Size = new Size(680, 23); // btnSpeakInput btnSpeakInput.Text = "Speak"; - btnSpeakInput.Location = new Point(737, 80); + btnSpeakInput.Location = new Point(737, 117); btnSpeakInput.Size = new Size(75, 25); btnSpeakInput.UseVisualStyleBackColor = true; txtLog.ReadOnly = true; @@ -152,20 +234,20 @@ partial class MainForm // chkMinimizeToTray chkMinimizeToTray.Text = "Minimize to tray on close"; - chkMinimizeToTray.Location = new Point(12, 440); + chkMinimizeToTray.Location = new Point(12, 477); chkMinimizeToTray.Size = new Size(180, 24); chkMinimizeToTray.UseVisualStyleBackColor = true; // btnClearLog btnClearLog.Text = "Clear Log"; - btnClearLog.Location = new Point(737, 438); + btnClearLog.Location = new Point(737, 475); btnClearLog.Size = new Size(75, 25); btnClearLog.UseVisualStyleBackColor = true; // MainForm AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(824, 472); + ClientSize = new Size(824, 509); Controls.Add(lblPttKey); Controls.Add(cmbPttKey); Controls.Add(lblVoice); @@ -178,13 +260,22 @@ partial class MainForm Controls.Add(btnBrowseFile); Controls.Add(lblFileName); Controls.Add(lblLineStatus); + Controls.Add(lblNoise); + Controls.Add(trkNoise); + Controls.Add(lblNoiseVal); + Controls.Add(lblSpeed); + Controls.Add(trkSpeed); + Controls.Add(lblSpeedVal); + Controls.Add(lblNoiseW); + Controls.Add(trkNoiseW); + Controls.Add(lblNoiseWVal); Controls.Add(lblTextInput); Controls.Add(txtTextInput); Controls.Add(btnSpeakInput); Controls.Add(txtLog); Controls.Add(chkMinimizeToTray); Controls.Add(btnClearLog); - MinimumSize = new Size(840, 510); + MinimumSize = new Size(840, 547); Text = "Robovoice"; FormBorderStyle = FormBorderStyle.FixedSingle; MaximizeBox = false; diff --git a/Robovoice.App/MainForm.cs b/Robovoice.App/MainForm.cs index 930e15e..ce8237c 100644 --- a/Robovoice.App/MainForm.cs +++ b/Robovoice.App/MainForm.cs @@ -49,6 +49,13 @@ internal sealed partial class MainForm : Form cmbOutput.SelectedIndexChanged += OnOutputChanged; cmbVoice.SelectedIndexChanged += OnVoiceChanged; + trkNoise.Scroll += OnSliderScroll; + trkSpeed.Scroll += OnSliderScroll; + trkNoiseW.Scroll += OnSliderScroll; + trkNoise.MouseUp += OnSliderReleased; + trkSpeed.MouseUp += OnSliderReleased; + trkNoiseW.MouseUp += OnSliderReleased; + SetupTray(); await InitializeEngineAsync(); @@ -124,7 +131,12 @@ internal sealed partial class MainForm : Form _audioOutput?.Dispose(); _tts?.DisposeAsync().AsTask().Wait(); - _tts = new LibPiperTtsEngine(modelPath, _espeakDataPath); + _tts = new LibPiperTtsEngine( + modelPath, + _espeakDataPath, + noiseScale: trkNoise.Value / 1000.0f, + lengthScale: trkSpeed.Value / 100.0f, + noiseWScale: trkNoiseW.Value / 1000.0f); _audioOutput = new AudioOutput(); _sttSource = new FileSttSource(); _orchestrator?.DisposeAsync().AsTask().Wait(); @@ -272,6 +284,21 @@ internal sealed partial class MainForm : Form await InitializeEngineAsync(); } + private void OnSliderScroll(object? sender, EventArgs e) + { + lblNoiseVal.Text = $"{trkNoise.Value / 1000.0:F3}"; + lblSpeedVal.Text = $"{trkSpeed.Value / 100.0:F2}"; + lblNoiseWVal.Text = $"{trkNoiseW.Value / 1000.0:F3}"; + } + + private void OnSliderReleased(object? sender, MouseEventArgs e) + { + if (cmbVoice.SelectedItem is string name && VoiceCatalogue.IsVoiceInstalled(_voicesDir, name)) + { + _ = InitializeEngineAsync(); + } + } + private void OnPttKeyChanged(object? sender, EventArgs e) { SetupHotkey(); diff --git a/Robovoice.App/VoiceManagerForm.Designer.cs b/Robovoice.App/VoiceManagerForm.Designer.cs index 0e9fab8..77d1648 100644 --- a/Robovoice.App/VoiceManagerForm.Designer.cs +++ b/Robovoice.App/VoiceManagerForm.Designer.cs @@ -1,3 +1,4 @@ +#nullable enable namespace Robovoice.App; partial class VoiceManagerForm