public DirectSound( Form form, int sampleRate, int bufferCount) { if ((sampleRate % 50) != 0) { throw new ArgumentOutOfRangeException("sampleRate", "Sample rate must be a multiple of 50!"); } _sampleRate = sampleRate; var bufferSize = sampleRate / 50; for (int i = 0; i < bufferCount; i++) { _fillQueue.Enqueue(new uint[bufferSize]); } _bufferSize = bufferSize; _bufferCount = bufferCount; _zeroValue = 0; var hWnd = form != null ? form.Handle : IntPtr.Zero; _device = new DirectSound8(); _device.SetCooperativeLevel(hWnd, DSSCL.PRIORITY); // we always use 16 bit stereo (uint per sample) const short channels = 2; const short bitsPerSample = 16; const int sampleSize = 4; // channels * (bitsPerSample / 8); var wf = new WaveFormat(_sampleRate, bitsPerSample, channels); // Create a buffer var bufferDesc = new DSBUFFERDESC(); bufferDesc.dwBufferBytes = _bufferSize * sampleSize * _bufferCount; bufferDesc.dwFlags = DSBCAPS_FLAGS.CTRLVOLUME | DSBCAPS_FLAGS.CTRLPOSITIONNOTIFY | DSBCAPS_FLAGS.GLOBALFOCUS | DSBCAPS_FLAGS.GETCURRENTPOSITION2; bufferDesc.Format = wf; _soundBuffer = new SecondarySoundBuffer(_device, bufferDesc); var posNotify = new DSBPOSITIONNOTIFY[_bufferCount]; for (int i = 0; i < posNotify.Length; i++) { posNotify[i] = new DSBPOSITIONNOTIFY(); posNotify[i].dwOffset = i * _bufferSize * sampleSize; posNotify[i].WaitHandle = _fillEvent; } _soundBuffer.SetNotificationPositions(posNotify); _wavePlayThread = new Thread(WavePlayThreadProc); _wavePlayThread.IsBackground = true; _wavePlayThread.Name = "WavePlay"; _wavePlayThread.Priority = ThreadPriority.Highest; _wavePlayThread.Start(); }
private bool CreateBufferNotifications() { uint error = DSERR.DS_OK; // 获取IDirectSoundNotify8接口 Guid iid_dsNotify8 = new Guid(InterfaceID.IID_IDirectSoundNotify8); IntPtr pdsNotify8; IDirectSoundNotify8 dsNotify8; Marshal.QueryInterface(this.pdscb8, ref iid_dsNotify8, out pdsNotify8); dsNotify8 = Marshal.GetObjectForIUnknown(pdsNotify8) as IDirectSoundNotify8; try { WAVEFORMATEX wfx; int pdwSizeWritten; if ((error = this.dscb8.GetFormat(out wfx, Marshal.SizeOf(typeof(WAVEFORMATEX)), out pdwSizeWritten)) != DSERR.DS_OK) { logger.ErrorFormat("GetFormat失败, DSERROR = {0}", error); return(false); } DSBPOSITIONNOTIFY[] rgdsbpn = new DSBPOSITIONNOTIFY[this.NotifyEvents]; this.notifyHandle_close = new IntPtr[this.NotifyEvents]; for (int i = 0; i < this.NotifyEvents; i++) { this.notifyHandle_close[i] = Win32API.CreateEvent(IntPtr.Zero, true, false, null); } rgdsbpn[0].dwOffset = (uint)(wfx.nAvgBytesPerSec - 1); rgdsbpn[0].hEventNotify = this.notifyHandle_close[0]; rgdsbpn[1].dwOffset = Win32API.DSBPN_OFFSETSTOP; rgdsbpn[1].hEventNotify = this.notifyHandle_close[1]; if ((error = dsNotify8.SetNotificationPositions(this.NotifyEvents, Marshal.UnsafeAddrOfPinnedArrayElement(rgdsbpn, 0))) != DSERR.DS_OK) { logger.ErrorFormat("SetNotificationPositions失败, DSERROR = {0}", error); return(false); } } finally { Marshal.Release(pdsNotify8); } return(true); }