/// <inheritdoc /> public void Start() { if (DeviceHandle != IntPtr.Zero || IsDisposed) { throw new InvalidOperationException($"{nameof(LegacyAudioPlayer)} was already started"); } var bufferSize = Renderer.WaveFormat.ConvertMillisToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers); // Acquire a device handle DeviceHandle = WaveInterop.OpenAudioDevice( DeviceNumber, Renderer.WaveFormat, DriverCallbackEvent.SafeWaitHandle, IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent); // Create the buffers Buffers = new WaveOutBuffer[NumberOfBuffers]; for (var n = 0; n < NumberOfBuffers; n++) { Buffers[n] = new WaveOutBuffer(DeviceHandle, bufferSize, Renderer); } // Start the playback thread DriverCallbackEvent.Set(); // give the thread an initial kick PlaybackState = PlaybackState.Playing; StartAsync(); }
/// <summary> /// Initializes the specified wave provider. /// </summary> /// <param name="waveProvider">The wave provider.</param> /// <exception cref="System.InvalidOperationException">Can't re-initialize during playback</exception> public void Init(IWaveProvider waveProvider) { if (m_PlaybackState != PlaybackState.Stopped) { throw new InvalidOperationException("Can't re-initialize during playback"); } if (DeviceHandle != IntPtr.Zero) { // normally we don't allow calling Init twice, but as experiment, see if we can clean up and go again // try to allow reuse of this waveOut device // n.b. risky if Playback thread has not exited DisposeBuffers(); CloseWaveOut(); } CallbackEvent = new AutoResetEvent(false); WaveStream = waveProvider; var bufferSize = waveProvider.WaveFormat.ConvertLatencyToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers); MmResult result; lock (WaveOutLock) { result = WaveInterop.NativeMethods.waveOutOpenWindow( out DeviceHandle, DeviceNumber, WaveStream.WaveFormat, CallbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent); } MmException.Try(result, nameof(WaveInterop.NativeMethods.waveOutOpen)); Buffers = new WaveOutBuffer[NumberOfBuffers]; m_PlaybackState = PlaybackState.Stopped; for (var n = 0; n < NumberOfBuffers; n++) { Buffers[n] = new WaveOutBuffer(DeviceHandle, bufferSize, WaveStream, WaveOutLock); } }
/// <summary> /// Begin playback /// </summary> public void Start() { if (DeviceHandle != IntPtr.Zero || IsDisposed) { throw new InvalidOperationException($"{nameof(AudioPlaybackThread)} was already started"); } PlaybackFinished.Begin(); var bufferSize = Renderer.WaveFormat.ConvertMillisToByteSize((DesiredLatency + NumberOfBuffers - 1) / NumberOfBuffers); // Acquire a device handle DeviceHandle = WaveInterop.OpenAudioDevice( DeviceNumber, Renderer.WaveFormat, DriverCallbackEvent.SafeWaitHandle.DangerousGetHandle(), IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackEvent); // Create the buffers Buffers = new WaveOutBuffer[NumberOfBuffers]; for (var n = 0; n < NumberOfBuffers; n++) { Buffers[n] = new WaveOutBuffer(DeviceHandle, bufferSize, Renderer); } // Start the playback thread DriverCallbackEvent.Set(); // give the thread an initial kick AudioPlaybackThread = new Thread(PerformContinuousPlayback) { IsBackground = true, Name = nameof(AudioPlaybackThread), Priority = ThreadPriority.AboveNormal }; // Begin the thread AudioPlaybackThread.Start(); }