Files
voice-cat/clients/windows/VoiceCat.App/Models/VoiceSettings.cs
Talon 8bb2ba933c feat(clients): unify volume boost cap to 4x across all clients
Mic input gain (was 3x) and per-user receive gain (was 2x) had
asymmetric boost ceilings. Raise both, plus the desktop aux input
gain (was 3x), to a uniform 4x (400%) on macOS, iOS, and Windows.

The master Output volume slider is unchanged (still 1x). No core
changes needed: the C ABI only clamps negatives, so the ceilings
live entirely in the client UI sliders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 12:18:10 +02:00

82 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
namespace VoiceCat.App.Models;
/// <summary>
/// User's send-side voice input preferences — transmission mode, VAD sensitivity, mic input
/// gain, and the push-to-talk key. Persisted to %AppData%\VoiceCat\voice.json, same pattern as
/// <see cref="ServerListStore"/> and FeedbackSettings: a missing or corrupt file yields defaults
/// rather than throwing. Slider-position values are stored as-is so MainForm can restore the
/// TrackBars directly.
/// </summary>
public sealed class VoiceSettings
{
/// <summary>Transmission mode: 0 = voice activation, 1 = push-to-talk, 2 = always on
/// (matches Interop's VcInputMode).</summary>
public int InputMode { get; set; } = 0;
/// <summary>VAD sensitivity slider position, 1100 (default mirrors the designer's 76).</summary>
public int VadThresholdSlider { get; set; } = 76;
/// <summary>Microphone input gain slider position, 0400 percent (100 = unity).</summary>
public int MicGain { get; set; } = 100;
/// <summary>Send-side mic noise reduction (RNNoise) toggle. MIC stream only, mono only;
/// denoises captured mic PCM before input gain and VAD/PTT gate so everyone hears the
/// cleaned signal. Independent of the per-listener receive-side NR.</summary>
public bool MicNoiseReduction { get; set; } = false;
/// <summary>Capture the mic in stereo (interleaved L/R) instead of mono. Off by default. Real
/// stereo only reaches the wire on a stereo channel; on a mono channel the core folds the mic
/// to mono. Applied when the capture device next starts (Join Voice or an audio restart).</summary>
public bool StereoMic { get; set; } = false;
/// <summary>Push-to-talk key, stored as the integer value of System.Windows.Forms.Keys.</summary>
public int PttKey { get; set; } = (int)Keys.F8;
/// <summary>Saved device ID from the last session; null means use the system default.</summary>
public string? InputDeviceId { get; set; } = null;
/// <summary>Whether the secondary "aux" outgoing stream is enabled. The aux stream is a
/// second hardware input device the client captures itself and feeds to the core via
/// vc_stream_feed_pcm (kind = AUX_DEVICE, external_feed). Lets a user transmit e.g. mic +
/// a line-in at once.</summary>
public bool AuxEnabled { get; set; } = false;
/// <summary>WASAPI endpoint id of the aux capture device; null = system default capture
/// device. NOTE: this is a WASAPI device id (from <see cref="Audio.InputDeviceEnumerator"/>),
/// NOT a core/miniaudio id — the aux device is opened client-side, so the two id spaces differ.</summary>
public string? AuxDeviceId { get; set; } = null;
/// <summary>Aux input volume slider position, 0400 percent (100 = unity). Applied client-side
/// to the captured PCM before feeding (the core's input gain is mic-only and global).</summary>
public int AuxGain { get; set; } = 100;
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
private static string AppDataDir => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "VoiceCat");
private static string FilePath => Path.Combine(AppDataDir, "voice.json");
public static VoiceSettings Load()
{
try
{
if (!File.Exists(FilePath)) return new VoiceSettings();
string json = File.ReadAllText(FilePath);
return JsonSerializer.Deserialize<VoiceSettings>(json) ?? new VoiceSettings();
}
catch
{
return new VoiceSettings();
}
}
public void Save()
{
Directory.CreateDirectory(AppDataDir);
File.WriteAllText(FilePath, JsonSerializer.Serialize(this, JsonOptions));
}
}