public int Release() { Marshal.FreeHGlobal(this.pBufferDesc_free); Marshal.FreeHGlobal(this.pwfx_free); Marshal.Release(this.pdscb8); Marshal.Release(this.pdsc8); //Marshal.ReleaseComObject(this.dscb8); //Marshal.ReleaseComObject(this.dsc8); Marshal.FinalReleaseComObject(this.dscb8); Marshal.FinalReleaseComObject(this.dsc8); this.pBufferDesc_free = IntPtr.Zero; this.pwfx_free = IntPtr.Zero; this.pdscb8 = IntPtr.Zero; this.pdsc8 = IntPtr.Zero; this.dscb8 = null; this.dsc8 = null; foreach (var hwnd in this.notifyHwnd_close) { DSLibNatives.CloseHandle(hwnd); } this.notifyHwnd_close = null; return((int)DSERR.DS_OK); }
private bool CreateBufferNotifications(out uint dsErr) { dsErr = DSERR.DS_OK; // 获取IDirectSoundNotify8接口 Guid iid_dsNotify8 = new Guid(IID.IID_IDirectSoundNotify8); IntPtr pdsNotify8; IDirectSoundNotify8 dsNotify8; Marshal.QueryInterface(this.pdscb8, ref iid_dsNotify8, out pdsNotify8); dsNotify8 = Marshal.GetObjectForIUnknown(pdsNotify8) as IDirectSoundNotify8; try { tWAVEFORMATEX wfx; int pdwSizeWritten; dsErr = this.dscb8.GetFormat(out wfx, Marshal.SizeOf(typeof(tWAVEFORMATEX)), out pdwSizeWritten); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("GetFormat失败, DSERROR = {0}", dsErr); return(false); } _DSBPOSITIONNOTIFY[] rgdsbpn = new _DSBPOSITIONNOTIFY[DSLibConsts.NotifyEvents]; this.notifyHwnd_close = new IntPtr[DSLibConsts.NotifyEvents]; for (int i = 0; i < DSLibConsts.NotifyEvents; i++) { this.notifyHwnd_close[i] = DSLibNatives.CreateEvent(IntPtr.Zero, true, false, null); } rgdsbpn[0].dwOffset = (uint)(wfx.nAvgBytesPerSec - 1); rgdsbpn[0].hEventNotify = this.notifyHwnd_close[0]; rgdsbpn[1].dwOffset = DSLibNatives.DSBPN_OFFSETSTOP; rgdsbpn[1].hEventNotify = this.notifyHwnd_close[1]; dsErr = dsNotify8.SetNotificationPositions(DSLibConsts.NotifyEvents, Marshal.UnsafeAddrOfPinnedArrayElement(rgdsbpn, 0)); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("SetNotificationPositions失败, DSERROR = {0}", dsErr); return(false); } } finally { Marshal.Release(pdsNotify8); } return(true); }
private bool CreateIDirectSoundCapture8(out uint dsErr) { dsErr = DSERR.DS_OK; dsErr = DSLibNatives.DirectSoundCaptureCreate8(IntPtr.Zero, out this.pdsc8, IntPtr.Zero); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("DirectSoundCaptureCreate8失败, DSERROR = {0}", dsErr); return(false); } this.dsc8 = Marshal.GetObjectForIUnknown(this.pdsc8) as IDirectSoundCapture8; return(true); }
public int Stop() { this.isPlaying = false; uint dsErr = this.dsb8.Stop(); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("Stop失败, DSERR = {0}", dsErr); } DSLibNatives.SetEvent(this.notifyHwnd_close[0]); return((int)dsErr); }
//public int Pause() //{ // return DSERR.DS_OK; //} //public int Restore() //{ // return DSERR.DS_OK; //} #endregion #region 实例方法 private bool CreateIDirectSound8(IntPtr hwnd, out uint dsErr) { dsErr = DSLibNatives.DirectSoundCreate8(IntPtr.Zero, out this.pds8, IntPtr.Zero); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("DirectSoundCreate8失败, DSERR = {0}", dsErr); return(false); } this.ds8 = Marshal.GetObjectForIUnknown(this.pds8) as IDirectSound8; dsErr = this.ds8.SetCooperativeLevel(hwnd, (int)DSSCL.DSSCL_NORMAL); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("SetCooperativeLevel失败, DSERR = {0}", dsErr); return(false); } return(true); }
public int Start() { uint dsErr = this.dscb8.Start(DSLibNatives.DSCBSTART_LOOPING); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("开始录音失败, DSERROR = {0}", dsErr); return((int)dsErr); } this.isRunning = true; Task.Factory.StartNew((state) => { while (this.isRunning) { // 这里需要实时获取通知对象的指针, 因为这个指针的值每隔一段时间会改变。。。 IntPtr lpHandles = Marshal.UnsafeAddrOfPinnedArrayElement(this.notifyHwnd_close, 0); // DSLibNatives.WaitForSingleObject(this.close_notifyHwnd[0], DSLibNatives.INFINITE); switch (DSLibNatives.WaitForMultipleObjects(DSLibConsts.NotifyEvents, lpHandles, false, DSLibNatives.INFINITE)) { case DSLibNatives.WAIT_OBJECT_0: { (state as SynchronizationContext).Send((o) => { try { byte[] audioData = null; if (this.RecordCapturedData(0, (uint)this.wfx.nAvgBytesPerSec, out audioData) == DSERR.DS_OK) { if (this.AudioDataCaptured != null) { this.AudioDataCaptured(audioData); } } } catch (Exception ex) { DSLibUtils.PrintLog("保存音频流异常, Exception = {0}", ex); } }, null); DSLibNatives.ResetEvent(this.notifyHwnd_close[0]); } break; case DSLibNatives.WAIT_OBJECT_0 + 1: { // 录音结束 DSLibNatives.ResetEvent(this.notifyHwnd_close[1]); this.isRunning = false; } break; case DSLibNatives.WAIT_FAILED: { int error = Marshal.GetLastWin32Error(); // 失败, 句柄已经被销毁 DSLibUtils.PrintLog("WAIT_FAILED, LastWin32Error = {0}", error); this.isRunning = false; this.Stop(); if (this.OnError != null) { this.OnError(error); } } break; } } }, SynchronizationContext.Current); return((int)dsErr); }
public int Play() { uint dsErr = this.dsb8.Play(0, 0, (int)DSBPLAY.DSBPLAY_LOOPING); if (dsErr != DSERR.DS_OK) { DSLibUtils.PrintLog("Play失败, DSERR = {0}", dsErr); return((int)dsErr); } this.isPlaying = true; this.NotifyStatusChanged(DSLibPlayerStatus.Playing, 0); Task.Factory.StartNew((state) => { while (this.isPlaying) { //IntPtr lpHandles = Marshal.UnsafeAddrOfPinnedArrayElement(this.notifyHwnd_close, 0); //switch (DSLibNatives.WaitForMultipleObjects(DSLibConsts.NotifyEvents, lpHandles, false, DSLibNatives.INFINITE)) switch (DSLibNatives.WaitForSingleObject(this.notifyHwnd_close[0], DSLibNatives.INFINITE)) { case DSLibNatives.WAIT_OBJECT_0: { if (this.StreamSource == null) { // 空数据 DSLibNatives.ResetEvent(this.notifyHwnd_close[0]); DSLibUtils.PrintLog("StreamSource为空, 继续等待通知"); break; } if (!this.isPlaying) { // 通知是异步的,在调用了Stop之后, 如果收到通知的速度比音频流重置的速度慢(也就是说先重置了音频流,然后又收到了一次通知), 有可能会再次读取一次数据 break; } byte[] buffer = new byte[this.dsbd.dwBufferBytes]; if (this.StreamSource.Read(buffer, 0, buffer.Length) == 0) { // 没有数据 if (this.IsStreamingBuffer) { DSLibUtils.PrintLog("缓冲区中没有数据, 继续等待通知"); // 清空播放缓冲区的音频数据, 不然会一直播放最后一个Buffer里的数据 (state as SynchronizationContext).Send((o) => { uint e; this.WriteDataToBuffer(EmptyBuffer, out e); }, null); } else { DSLibUtils.PrintLog("缓冲区播放完毕, 停止播放"); this.Stop(); this.NotifyStatusChanged(DSLibPlayerStatus.Stopped, 0); } DSLibNatives.ResetEvent(this.notifyHwnd_close[0]); break; } // 缓冲区通知 (state as SynchronizationContext).Send((o) => { DSLibUtils.PrintLog("播放缓冲区数据, 大小:{0}字节", buffer.Length); try { uint error; if (this.WriteDataToBuffer(buffer, out error)) { } } catch (Exception ex) { DSLibUtils.PrintLog("处理缓冲区回调异常, Exception = {0}", ex); } }, null); DSLibNatives.ResetEvent(this.notifyHwnd_close[0]); } break; case DSLibNatives.WAIT_OBJECT_0 + 1: { } break; case DSLibNatives.WAIT_FAILED: { int winErr = Marshal.GetLastWin32Error(); DSLibUtils.PrintLog("等待信号失败, LastWin32Error = {0}", winErr); this.Stop(); this.NotifyStatusChanged(DSLibPlayerStatus.Error, winErr); } break; } } Console.WriteLine("跳出循环"); }, SynchronizationContext.Current); return((int)dsErr); }