private void SilenceGenerationRoutine(int bufferSize, WaveFormatEx format) { try { var buffer = new float[bufferSize * format.Channels]; var bufferDurationMs = bufferSize * 1000 / format.SampleRate; while (_continueSilenceThread) { _audioClientForRendering.GetCurrentPadding(out var padding); int numFramesAvailable = bufferSize - padding; _audioRenderClient.GetBuffer(numFramesAvailable, out var nativeBuffer); if (nativeBuffer != IntPtr.Zero) { Marshal.Copy(buffer, 0, nativeBuffer, numFramesAvailable * format.Channels); _audioRenderClient.ReleaseBuffer(numFramesAvailable, AudioClientBufferFlags.None); } _stopReading.WaitOne(bufferDurationMs / 2); } } catch (Exception e) { Log.Warning(e, "Error in Silence generator. Exiting"); } }
private void CheckFormat(WaveFormatEx format) { if (format.WaveFormat != 65534 || format.SubFormat != new Guid("00000003-0000-0010-8000-00aa00389b71")) { throw new InvalidOperationException($"Unsupported DesktopAudio Format {format.WaveFormat} - {format.SubFormat}"); } }
private void StartSilenceGeneration() { IntPtr mixFormatPtr = IntPtr.Zero; try { Checked(_endpoint.Activate(ref IAudioClientId, ClsCtxEnum.All, IntPtr.Zero, out var obj), "Silence.Activate"); _audioClientForRendering = (IAudioClient)obj; Checked(_audioClientForRendering.GetMixFormat(out mixFormatPtr), "Silence.GetMixFormat"); WaveFormatEx format = (WaveFormatEx)Marshal.PtrToStructure(mixFormatPtr, typeof(WaveFormatEx)); CheckFormat(format); Checked(_audioClientForRendering.Initialize(AudioClientShareModeEnum.Shared, AudioClientStreamFlagsEnum.None, 10_000_000 * 5, 0, mixFormatPtr, Guid.Empty), "Silence.Initialize"); Checked(_audioClientForRendering.GetBufferSize(out var bufferSize), "Silence.GetBufferSize"); Checked(_audioClientForRendering.GetService(IAudioRenderClientId, out var renderObj), "Silence.GetService"); _audioRenderClient = (IAudioRenderClient)renderObj; Checked(_audioClientForRendering.Start(), "Silence.Start"); _silenceThread = new Thread(() => SilenceGenerationRoutine(bufferSize, format)); _silenceThread.Name = "Silence generator"; _silenceThread.Start(); } catch (Exception e) { ReleaseComObject(ref _audioClientForRendering); ReleaseComObject(ref _audioRenderClient); Core.LogError(e, "Faied to StartSilenceGeneration"); } finally { if (mixFormatPtr != IntPtr.Zero) { Marshal.FreeCoTaskMem(mixFormatPtr); } } }
public WaveFormatEx Open() { StopSilenceThread(); Log.Information("Opening DesktopAudio"); IMMDeviceEnumerator deviceEnumerator = null; IntPtr mixFormatPtr = IntPtr.Zero; try { bool render = true; deviceEnumerator = Activator.CreateInstance(typeof(MMDeviceEnumerator)) as IMMDeviceEnumerator; var res = deviceEnumerator.GetDefaultAudioEndpoint( render ? DataFlowEnum.Render : DataFlowEnum.Capture, render ? RoleEnum.Console : RoleEnum.Communications, out _endpoint); if (render) { StartSilenceGeneration(); } Checked(_endpoint.Activate(ref IAudioClientId, ClsCtxEnum.All, IntPtr.Zero, out var obj), "Activate"); _audioClient = (IAudioClient)obj; Checked(_audioClient.GetMixFormat(out mixFormatPtr), "GetMixFormat"); WaveFormatEx outputFormat = (WaveFormatEx)Marshal.PtrToStructure(mixFormatPtr, typeof(WaveFormatEx)); if (!render) // for render it is checked in the StartSilenceGeneration(); { CheckFormat(outputFormat); } _bytesPerFrame = outputFormat.BlockAlign; var flags = AudioClientStreamFlagsEnum.StreamFlagsEventCallback | (render ? AudioClientStreamFlagsEnum.StreamFlagsLoopback : AudioClientStreamFlagsEnum.None); Checked(_audioClient.Initialize(AudioClientShareModeEnum.Shared, flags, 10_000_000 * 5, 0, mixFormatPtr, Guid.Empty), "Initialize"); Checked(_audioClient.GetService(IAudioCaptureClientId, out var captureObj), "GetService"); _audioCaptureClient = (IAudioCaptureClient)captureObj; #pragma warning disable CS0618 // Type or member is obsolete Checked(_audioClient.SetEventHandle(_dataAvailable.Handle), "SetEventHandle"); #pragma warning restore CS0618 // Type or member is obsolete Checked(_audioClient.Start(), "Start"); return(outputFormat); } catch (Exception e) { Core.LogError(e, "Open desktop audio failed"); StopSilenceThread(); ReleaseComFields(); throw; } finally { if (mixFormatPtr != IntPtr.Zero) { Marshal.FreeCoTaskMem(mixFormatPtr); } ReleaseComObject(ref deviceEnumerator); } }