/// <summary> /// Stop playback without flushing buffers /// </summary> public void Pause() { if (PlaybackState == EPlaybackState.Playing) { PlaybackState = EPlaybackState.Paused; } }
/// <summary> /// Stop playback and flush buffers /// </summary> public void Stop() { if (PlaybackState != EPlaybackState.Stopped) { PlaybackState = EPlaybackState.Stopped; Debug.WriteLine("[render]Task ending..."); playTask?.Wait(); playTask = null; Debug.WriteLine("[render]Task Done."); } }
/* * private void PlayThread() * { * IWaveProvider playbackProvider = this.sourceProvider; * Exception exception = null; * try * { * // fill a whole buffer * var bufferFrameCount = audioClient.BufferSize; * //var bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; * * readBuffer = new byte[bufferFrameCount * outputFormat.BlockAlign]; * FillBuffer(playbackProvider, bufferFrameCount); * * // Create WaitHandle for sync * //WaitHandle[] waitHandles = new WaitHandle[] { frameEventWaitHandle }; * * audioClient.Start(); * * while (PlaybackState != EPlaybackState.Stopped) * { * // If using Event Sync, Wait for notification from AudioClient or Sleep half latency * int indexHandle = 0; * if (isUsingEventSync) * { * //indexHandle = WaitHandle.WaitAny(waitHandles, 3 * latencyMilliseconds, false); * frameEventWaitHandle.WaitOne(3 * latencyMilliseconds); * } * else * { * Thread.Sleep(latencyMilliseconds / 2); * } * * // If still playing and notification is ok * if (PlaybackState == EPlaybackState.Playing && indexHandle != WaitHandle.WaitTimeout) * { * // See how much buffer space is available. * int numFramesPadding = 0; * if (isUsingEventSync) * { * // In exclusive mode, always ask the max = bufferFrameCount = audioClient.BufferSize * numFramesPadding = (shareMode == EAudioClientShareMode.Shared) ? audioClient.CurrentPadding : 0; * } * else * { * numFramesPadding = audioClient.CurrentPadding; * } * int numFramesAvailable = bufferFrameCount - numFramesPadding; * if (numFramesAvailable > 0) * { * FillBuffer(playbackProvider, numFramesAvailable); * } * } * } * Thread.Sleep(latencyMilliseconds / 2); * audioClient.Stop(); * if (PlaybackState == EPlaybackState.Stopped) * { * audioClient.Reset(); * } * } * catch (Exception e) * { * exception = e; * } * finally * { * //RaisePlaybackStopped(exception); * } * } */ /* * private void RaisePlaybackStopped(Exception e) * { * var handler = PlaybackStopped; * if (handler != null) * { * if (this.syncContext == null) * { * handler(this, new StoppedEventArgs(e)); * } * else * { * syncContext.Post(state => handler(this, new StoppedEventArgs(e)), null); * } * } * } */ private void FillBuffer(IWaveProvider playbackProvider, int frameCount) { IntPtr buffer = renderClient.GetBuffer(frameCount); int readLength = frameCount * outputFormat.BlockAlign; int read = playbackProvider.Read(readBuffer, 0, readLength); if (read == 0) { PlaybackState = EPlaybackState.Stopped; } Marshal.Copy(readBuffer, 0, buffer, read); int actualFrameCount = read / outputFormat.BlockAlign; /*if (actualFrameCount != frameCount) * { * Debug.WriteLine(String.Format("WASAPI wanted {0} frames, supplied {1}", frameCount, actualFrameCount )); * }*/ renderClient.ReleaseBuffer(actualFrameCount, EAudioClientBufferFlags.None); }
/// <summary> /// Begin Playback /// </summary> public void Play() { if (PlaybackState == EPlaybackState.Playing) { return; } if (PlaybackState == EPlaybackState.Paused) { PlaybackState = EPlaybackState.Playing; return; } Debug.WriteLine("[render]Task starting..."); playTask = Task.Run(() => { IWaveProvider playbackProvider = this.sourceProvider; AudioClient client = this.audioClient; Exception exception = null; PlaybackState = EPlaybackState.Playing; try { // fill a whole buffer var bufferFrameCount = client.BufferSize; var bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; readBuffer = new byte[bufferFrameCount * bytesPerFrame]; //FillBuffer(playbackProvider, bufferFrameCount); client.Start(); while (PlaybackState != EPlaybackState.Stopped) { // If using Event Sync, Wait for notification from AudioClient or Sleep half latency if (isUsingEventSync) { //indexHandle = WaitHandle.WaitAny(waitHandles, 3 * latencyMilliseconds, false); frameEventWaitHandle.WaitOne(3 * latencyMilliseconds); } else { Task.Delay(latencyMilliseconds / 2); } // If still playing and notification is ok if (PlaybackState != EPlaybackState.Playing) { continue; } // See how much buffer space is available. int numFramesPadding = 0; if (isUsingEventSync) { // In exclusive mode, always ask the max = bufferFrameCount = audioClient.BufferSize numFramesPadding = (shareMode == EAudioClientShareMode.Shared) ? client.CurrentPadding : 0; } else { numFramesPadding = client.CurrentPadding; } int numFramesAvailable = bufferFrameCount - numFramesPadding; if (numFramesAvailable > 0) { FillBuffer(playbackProvider, numFramesAvailable); } } } catch (Exception e) { Debug.WriteLine("[render]Task catch Exception."); Debug.WriteLine(e.Message); Debug.WriteLine(e.Source); Debug.WriteLine(e.StackTrace); exception = e; } finally { client.Stop(); client.Reset(); Debug.WriteLine("[render]Task stop detected."); RaisePlaybackStopped(exception); } }); Debug.WriteLine("[render]Task started"); }