Files
voice-cat/clients/windows/VoiceCat.App/Models/VoiceSettings.cs
T
Talon dd811a0bb8
.NET port / test (macos-latest) (push) Canceled after 0s
.NET port / test (ubuntu-24.04) (push) Canceled after 0s
.NET port / test (windows-latest) (push) Canceled after 0s
.NET port / apple-client (push) Canceled after 0s
Fix audio clock drift and adaptive jitter buffering
2026-09-20 16:26:03 +02:00

94 lines
4.6 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>Make push-to-talk work system-wide — i.e. while another app is focused. When on,
/// MainForm registers a background Raw Input keyboard device (WM_INPUT + RIDEV_INPUTSINK) so the
/// PTT key is observed even when VoiceCat is not in the foreground; when off, PTT is focus-scoped
/// (only fires while the VoiceCat window has focus). Raw Input is used instead of a low-level
/// keyboard hook to avoid antivirus keylogger heuristics.</summary>
public bool SystemWidePtt { get; set; } = true;
/// <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;
/// <summary>Local capture/playback safety buffer in milliseconds: 20, 40, or 60.</summary>
public int AudioBufferMilliseconds { get; set; } = 40;
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);
VoiceSettings result = JsonSerializer.Deserialize<VoiceSettings>(json) ?? new VoiceSettings();
if (result.AudioBufferMilliseconds is not (20 or 40 or 60)) result.AudioBufferMilliseconds = 40;
return result;
}
catch
{
return new VoiceSettings();
}
}
public void Save()
{
Directory.CreateDirectory(AppDataDir);
File.WriteAllText(FilePath, JsonSerializer.Serialize(this, JsonOptions));
}
}