internal MmResult WaveOutOpen(out IntPtr waveOutHandle, int deviceNumber, WaveFormat waveFormat, WaveInterop.WaveCallback callback) { MmResult result; if (Strategy == WaveCallbackStrategy.FunctionCallback) { result = WaveInterop.waveOutOpen(out waveOutHandle, (IntPtr)deviceNumber, waveFormat, callback, IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackFunction); } else { result = WaveInterop.waveOutOpenWindow(out waveOutHandle, (IntPtr)deviceNumber, waveFormat, this.Handle, IntPtr.Zero, WaveInterop.WaveInOutOpenFlags.CallbackWindow); } return result; }
internal void Connect(WaveInterop.WaveCallback callback) { if (Strategy == WaveCallbackStrategy.NewWindow) { waveOutWindow = new WaveWindow(callback); waveOutWindow.CreateControl(); this.Handle = waveOutWindow.Handle; } else if (Strategy == WaveCallbackStrategy.ExistingWindow) { waveOutWindowNative = new WaveWindowNative(callback); waveOutWindowNative.AssignHandle(this.Handle); } }
private GCHandle hThis; // for the user callback /// <summary> /// creates a new wavebuffer /// </summary> /// <param name="waveInHandle">WaveIn device to write to</param> /// <param name="bufferSize">Buffer size in bytes</param> public WaveInBuffer(IntPtr waveInHandle, Int32 bufferSize) { this.bufferSize = bufferSize; this.buffer = new byte[bufferSize]; this.hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); this.waveInHandle = waveInHandle; header = new WaveHeader(); hHeader = GCHandle.Alloc(header, GCHandleType.Pinned); header.dataBuffer = hBuffer.AddrOfPinnedObject(); header.bufferLength = bufferSize; header.loops = 1; hThis = GCHandle.Alloc(this); header.userData = (IntPtr)hThis; MmException.Try(WaveInterop.waveInPrepareHeader(waveInHandle, header, Marshal.SizeOf(header)), "waveInPrepareHeader"); //MmException.Try(WaveInterop.waveInAddBuffer(waveInHandle, header, Marshal.SizeOf(header)), "waveInAddBuffer"); }
private void CloseWaveInDevice() { if (waveInHandle == IntPtr.Zero) { return; } // Some drivers need the reset to properly release buffers WaveInterop.waveInReset(waveInHandle); if (buffers != null) { for (int n = 0; n < buffers.Length; n++) { buffers[n].Dispose(); } buffers = null; } WaveInterop.waveInClose(waveInHandle); waveInHandle = IntPtr.Zero; }
/// <summary> /// Stop and reset the WaveOut device /// </summary> public void Stop() { if (playbackState != PlaybackState.Stopped) { // in the call to waveOutReset with function callbacks // some drivers will block here until OnDone is called // for every buffer playbackState = PlaybackState.Stopped; // set this here to avoid a problem with some drivers whereby MmResult result; lock (waveOutLock) { result = WaveInterop.waveOutReset(hWaveOut); } if (result != MmResult.NoError) { throw new MmException(result, "waveOutReset"); } callbackEvent.Set(); // give the thread a kick, make sure we exit } }
private GCHandle hThis; // for the user callback /// <summary> /// creates a new wavebuffer /// </summary> /// <param name="hWaveOut">WaveOut device to write to</param> /// <param name="bufferSize">Buffer size in bytes</param> /// <param name="bufferFillStream">Stream to provide more data</param> /// <param name="waveOutLock">Lock to protect WaveOut API's from being called on >1 thread</param> public WaveOutBuffer(IntPtr hWaveOut, Int32 bufferSize, IWaveProvider bufferFillStream, object waveOutLock) { this.bufferSize = bufferSize; this.buffer = new byte[bufferSize]; this.hBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); this.hWaveOut = hWaveOut; this.waveStream = bufferFillStream; this.waveOutLock = waveOutLock; header = new WaveHeader(); hHeader = GCHandle.Alloc(header, GCHandleType.Pinned); header.dataBuffer = hBuffer.AddrOfPinnedObject(); header.bufferLength = bufferSize; header.loops = 1; hThis = GCHandle.Alloc(this); header.userData = (IntPtr)hThis; lock (waveOutLock) { MmException.Try(WaveInterop.waveOutPrepareHeader(hWaveOut, header, Marshal.SizeOf(header)), "waveOutPrepareHeader"); } }
/// <summary> /// Stop recording /// </summary> public void StopRecording() { if (recording) { recording = false; MmException.Try(WaveInterop.waveInStop(waveInHandle), "waveInStop"); // report the last buffers, sometimes more than one, so taking care to report them in the right order for (int n = 0; n < buffers.Length; n++) { int index = (n + lastReturnedBufferIndex + 1) % buffers.Length; var buffer = buffers[index]; if (buffer.Done) { RaiseDataAvailable(buffer); } } RaiseRecordingStopped(null); } //MmException.Try(WaveInterop.waveInReset(waveInHandle), "waveInReset"); // Don't actually close yet so we get the last buffer }
internal static void SetWaveOutVolume(float value, IntPtr hWaveOut, object lockObject) { if (value < 0) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } if (value > 1) { throw new ArgumentOutOfRangeException("value", "Volume must be between 0.0 and 1.0"); } float left = value; float right = value; int stereoVolume = (int)(left * 0xFFFF) + ((int)(right * 0xFFFF) << 16); MmResult result; lock (lockObject) { result = WaveInterop.waveOutSetVolume(hWaveOut, stereoVolume); } MmException.Try(result, "waveOutSetVolume"); }
/// <summary> /// Called when we get a new buffer of recorded data /// </summary> private void Callback(IntPtr waveInHandle, WaveInterop.WaveMessage message, IntPtr userData, WaveHeader waveHeader, IntPtr reserved) { if (message == WaveInterop.WaveMessage.WaveInData) { if (recording) { var hBuffer = (GCHandle)waveHeader.userData; var buffer = (WaveInBuffer)hBuffer.Target; if (buffer == null) return; lastReturnedBufferIndex = Array.IndexOf(buffers, buffer); RaiseDataAvailable(buffer); try { buffer.Reuse(); } catch (Exception e) { recording = false; RaiseRecordingStopped(e); } } } }
/// <summary> /// Stop recording /// </summary> public void StopRecording() { recording = false; this.callbackEvent.Set(); // signal the thread to exit MmException.Try(WaveInterop.waveInStop(waveInHandle), "waveInStop"); }
// made non-static so that playing can be stopped here private void Callback(IntPtr hWaveOut, WaveInterop.WaveMessage uMsg, IntPtr dwInstance, WaveHeader wavhdr, IntPtr dwReserved) { if (uMsg == WaveInterop.WaveMessage.WaveOutDone) { GCHandle hBuffer = (GCHandle)wavhdr.userData; WaveOutBuffer buffer = (WaveOutBuffer)hBuffer.Target; Interlocked.Decrement(ref queuedBuffers); Exception exception = null; // check that we're not here through pressing stop if (PlaybackState == PlaybackState.Playing) { // to avoid deadlocks in Function callback mode, // we lock round this whole thing, which will include the // reading from the stream. // this protects us from calling waveOutReset on another // thread while a WaveOutWrite is in progress lock (waveOutLock) { try { if (buffer.OnDone()) { Interlocked.Increment(ref queuedBuffers); } } catch (Exception e) { // one likely cause is soundcard being unplugged exception = e; } } } if (queuedBuffers == 0) { if (callbackInfo.Strategy == WaveCallbackStrategy.FunctionCallback && playbackState == Wave.PlaybackState.Stopped) { // the user has pressed stop // DO NOT raise the playback stopped event from here // since on the main thread we are still in the waveOutReset function // Playback stopped will be raised elsewhere } else { playbackState = PlaybackState.Stopped; // set explicitly for when we reach the end of the audio RaisePlaybackStoppedEvent(exception); } } } }