Fix audio clock drift and adaptive jitter buffering
.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

This commit is contained in:
2026-09-20 16:26:03 +02:00
parent 3ee0df11a9
commit dd811a0bb8
23 changed files with 401 additions and 61 deletions
@@ -34,6 +34,7 @@ public sealed class AudioSettingsForm : Form
private readonly bool _origAuxEnabled;
private readonly string? _origAuxDeviceId;
private readonly int _origAuxGain;
private readonly int _origAudioBufferMilliseconds;
private readonly ComboBox _cboDevice;
private readonly Button _btnRefresh;
@@ -54,6 +55,7 @@ public sealed class AudioSettingsForm : Form
private readonly Button _btnAuxRefresh;
private readonly Label _lblAuxGain;
private readonly TrackBar _trkAuxGain;
private readonly ComboBox _cboBuffer;
private Keys _pttKey;
@@ -80,6 +82,7 @@ public sealed class AudioSettingsForm : Form
_origAuxEnabled = settings.AuxEnabled;
_origAuxDeviceId = settings.AuxDeviceId;
_origAuxGain = settings.AuxGain;
_origAudioBufferMilliseconds = settings.AudioBufferMilliseconds;
Text = "Audio settings";
FormBorderStyle = FormBorderStyle.FixedDialog;
@@ -87,7 +90,7 @@ public sealed class AudioSettingsForm : Form
MinimizeBox = false;
StartPosition = FormStartPosition.CenterParent;
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(420, 639);
ClientSize = new Size(420, 690);
// ── Device row ────────────────────────────────────────────────────────
var lblDevice = new Label
@@ -319,19 +322,34 @@ public sealed class AudioSettingsForm : Form
"Volume of the aux input stream. 100 is unity gain; range 0400 percent.";
_trkAuxGain.Scroll += TrkAuxGain_Scroll;
var lblBuffer = new Label { Text = "Audio &buffering:", Location = new Point(12, 590), AutoSize = true };
_cboBuffer = new ComboBox
{
Location = new Point(130, 586), Width = 190, DropDownStyle = ComboBoxStyle.DropDownList,
AccessibleName = "Audio buffering",
AccessibleDescription = "Local capture and playback buffering. Lower values reduce latency; higher values tolerate more scheduling jitter."
};
_cboBuffer.Items.AddRange(["Low latency (20 ms)", "Balanced (40 ms)", "Stable (60 ms)"]);
_cboBuffer.SelectedIndex = settings.AudioBufferMilliseconds switch { 20 => 0, 60 => 2, _ => 1 };
_cboBuffer.SelectedIndexChanged += (_, _) =>
{
_settings.AudioBufferMilliseconds = _cboBuffer.SelectedIndex switch { 0 => 20, 2 => 60, _ => 40 };
_client.SetAudioBufferMilliseconds(_settings.AudioBufferMilliseconds);
};
// ── OK / Cancel ───────────────────────────────────────────────────────
var btnOk = new Button
{
Text = "&OK",
DialogResult = DialogResult.OK,
Location = new Point(228, 600),
Location = new Point(228, 642),
Size = new Size(80, 27),
};
var btnCancel = new Button
{
Text = "&Cancel",
DialogResult = DialogResult.Cancel,
Location = new Point(316, 600),
Location = new Point(316, 642),
Size = new Size(80, 27),
};
@@ -350,6 +368,7 @@ public sealed class AudioSettingsForm : Form
_radioPtt, _lblPttKey, _btnChangePtt, _chkSystemWidePtt, _radioAlwaysOn,
lblGain, _trkGain, _chkNoiseReduction, _chkStereoMic,
_chkAux, _lblAuxDevice, _cboAuxDevice, _btnAuxRefresh, _lblAuxGain, _trkAuxGain,
lblBuffer, _cboBuffer,
btnOk, btnCancel,
]);
@@ -534,6 +553,8 @@ public sealed class AudioSettingsForm : Form
_settings.StereoMic = _origStereoMic;
_settings.PttKey = (int)_origPttKey;
_settings.SystemWidePtt = _origSystemWidePtt;
_settings.AudioBufferMilliseconds = _origAudioBufferMilliseconds;
_client.SetAudioBufferMilliseconds(_origAudioBufferMilliseconds);
if (_micStreamId != 0)
{
@@ -109,8 +109,11 @@ public partial class MainForm : Form
BootstrapFromServer();
}
private void ApplyPersistedVoiceSettings() =>
private void ApplyPersistedVoiceSettings()
{
_pttKey = (Keys)_voiceSettings.PttKey;
_client.SetAudioBufferMilliseconds(_voiceSettings.AudioBufferMilliseconds);
}
// ── Startup ──────────────────────────────────────────────────────────────