/// <summary> /// Dispose /// </summary> public void Dispose() { if (captureState == WasapiCaptureState.Disposed) { return; } try { StopRecording(); NativeMethods.CloseHandle(hEvent); audioClient?.Dispose(); } catch (Exception ex) { Debug.WriteLine("Exception disposing WasapiCaptureRT: " + ex.ToString()); } hEvent = IntPtr.Zero; audioClient = null; captureState = WasapiCaptureState.Disposed; }
private async void PlayThread() { await Activate(); var playbackProvider = Init(); bool isClientRunning = false; try { if (this.resamplerNeeded) { var resampler = new WdlResamplingSampleProvider(playbackProvider.ToSampleProvider(), outputFormat.SampleRate); playbackProvider = new SampleToWaveProvider(resampler); } // fill a whole buffer bufferFrameCount = audioClient.BufferSize; bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; readBuffer = new byte[bufferFrameCount * bytesPerFrame]; FillBuffer(playbackProvider, bufferFrameCount); int timeout = 3 * latencyMilliseconds; while (playbackState != WasapiOutState.Disposed) { if (playbackState != WasapiOutState.Playing) { playThreadEvent.WaitOne(500); } // If still playing and notification is ok if (playbackState == WasapiOutState.Playing) { if (!isClientRunning) { audioClient.Start(); isClientRunning = true; } // If using Event Sync, Wait for notification from AudioClient or Sleep half latency var r = NativeMethods.WaitForSingleObjectEx(frameEventWaitHandle, timeout, true); if (r != 0) { throw new InvalidOperationException("Timed out waiting for event"); } // See how much buffer space is available. int numFramesPadding = 0; // In exclusive mode, always ask the max = bufferFrameCount = audioClient.BufferSize numFramesPadding = (shareMode == AudioClientShareMode.Shared) ? audioClient.CurrentPadding : 0; int numFramesAvailable = bufferFrameCount - numFramesPadding; if (numFramesAvailable > 0) { FillBuffer(playbackProvider, numFramesAvailable); } } if (playbackState == WasapiOutState.Stopping) { // play the buffer out while (audioClient.CurrentPadding > 0) { await Task.Delay(latencyMilliseconds / 2); } audioClient.Stop(); isClientRunning = false; audioClient.Reset(); playbackState = WasapiOutState.Stopped; RaisePlaybackStopped(null); } if (playbackState == WasapiOutState.Disposing) { audioClient.Stop(); isClientRunning = false; audioClient.Reset(); playbackState = WasapiOutState.Disposed; var disposablePlaybackProvider = playbackProvider as IDisposable; if (disposablePlaybackProvider != null) { disposablePlaybackProvider.Dispose(); // do everything on this thread, even dispose in case it is Media Foundation } RaisePlaybackStopped(null); } } } catch (Exception e) { RaisePlaybackStopped(e); } finally { audioClient.Dispose(); audioClient = null; renderClient = null; NativeMethods.CloseHandle(frameEventWaitHandle); } }