public void Stop() { if (IntPtr.Zero == _hWaveout) { return; } _started = false; int result = Native.waveOutReset(_hWaveout); System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR); ReleaseBuffers(); result = Native.waveOutClose(_hWaveout); System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR); _gchThis.Free(); _hWaveout = IntPtr.Zero; _callback = null; _fmt = null; }
public bool Start(WinMMAudioRenderCallback callback, int sampleRate, int channels, int bitsPerSample) { if (null == callback) { return(false); } if ((0 == sampleRate) || (0 == channels) || (0 == bitsPerSample)) { return(false); } // only mono and stereo are supported if (channels > 2) { return(false); } Stop(); _callback = callback; _fmt = new Native.WAVEFORMATEX(); _fmt.wFormatTag = Native.WAVE_FORMAT_PCM; _fmt.nChannels = (short)channels; _fmt.nSamplesPerSec = sampleRate; _fmt.nBlockAlign = (short)((bitsPerSample >> 3) * channels); _fmt.nAvgBytesPerSec = _fmt.nBlockAlign * sampleRate; _fmt.wBitsPerSample = (short)bitsPerSample; _fmt.cbSize = (short)Marshal.SizeOf(_fmt); _gchThis = GCHandle.Alloc(this); int result = Native.waveOutOpen(out _hWaveout, Native.WAVE_MAPPER, _fmt, _waveOutProc, (IntPtr)_gchThis, Native.CALLBACK_FUNCTION); if (result != Native.MMSYSERR_NOERROR) { _gchThis.Free(); _hWaveout = IntPtr.Zero; return(false); } _started = true; _totalDuration = 0; CreateBuffers(5, _fmt.nBlockAlign * (_fmt.nSamplesPerSec / 50)); // 5 buffers, 20ms each buffer result = Native.waveOutPause(_hWaveout); System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR); // write the empty buffers for (int i = 0; i < _buffers.Count; i++) { WaveOutBuffer buffer = _buffers[i]; buffer._hdr.dwBufferLength = 0; result = Native.waveOutWrite(_hWaveout, buffer._gchHdr.AddrOfPinnedObject(), Marshal.SizeOf(buffer._hdr)); System.Diagnostics.Debug.Assert(Native.MMSYSERR_NOERROR == result); } result = Native.waveOutRestart(_hWaveout); System.Diagnostics.Debug.Assert(result == Native.MMSYSERR_NOERROR); return(true); }