Port managed client audio and Windows application
.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 / cpp-conformance (push) Canceled after 0s

This commit is contained in:
2026-09-16 16:48:06 +02:00
parent 5a226ba543
commit 82ad4c2811
56 changed files with 2304 additions and 250 deletions
@@ -64,15 +64,15 @@ public sealed class ProcessLoopbackCapture : IDisposable
{
_running = false;
_bufferEvent?.Set();
_captureThread?.Join(500);
if (_audioClientPtr != IntPtr.Zero) AC_Stop(_audioClientPtr);
if (_captureThread is not null && !_captureThread.Join(5000))
throw new TimeoutException("Process capture did not stop.");
}
private int _disposed;
public void Dispose()
{
if (Interlocked.Exchange(ref _disposed, 1) != 0) return;
Stop();
ComRelease(ref _captureClientPtr);
ComRelease(ref _audioClientPtr);
_bufferEvent?.Dispose();
_initDone.Dispose();
}
@@ -81,10 +81,23 @@ public sealed class ProcessLoopbackCapture : IDisposable
private void CaptureThreadProc()
{
_initOk = ActivateAndStart();
_initDone.Set();
if (!_initOk) return;
CaptureLoop();
try
{
_initOk = ActivateAndStart();
_initDone.Set();
if (_initOk && _running) CaptureLoop();
}
catch
{
_initOk = false;
_initDone.Set();
}
finally
{
if (_audioClientPtr != IntPtr.Zero) AC_Stop(_audioClientPtr);
ComRelease(ref _captureClientPtr);
ComRelease(ref _audioClientPtr);
}
}
private bool ActivateAndStart()
@@ -274,9 +287,9 @@ public sealed class ProcessLoopbackCapture : IDisposable
private void FlushFrame()
{
var copy = new short[_accumBuf.Length];
_accumBuf.AsSpan().CopyTo(copy);
PcmFrameReady?.Invoke(copy, FrameSamples, _channels);
// The callback borrows this buffer until it returns. This capture owner cannot
// overwrite it concurrently, which avoids one allocation every 20 ms.
PcmFrameReady?.Invoke(_accumBuf, FrameSamples, _channels);
_accumCount = 0;
}