Exemple #1
0
        private int RecordCapturedData(uint offset, uint dataSize, out byte[] audioData)
        {
            audioData = null;
            IntPtr pbCaptureData;
            int    dwCaptureLength;
            IntPtr pbCaptureData2;
            int    dwCaptureLength2;
            uint   dsErr = DSERR.DS_OK;

            dsErr = this.dscb8.Lock(offset, dataSize, out pbCaptureData, out dwCaptureLength, out pbCaptureData2, out dwCaptureLength2, 0);
            if (dsErr != DSERR.DS_OK)
            {
                DSLibUtils.PrintLog("Lock失败, DSERROR = {0}", dsErr);
                return((int)dsErr);
            }

            // Unlock the capture buffer.
            this.dscb8.Unlock(pbCaptureData, dwCaptureLength, pbCaptureData2, dwCaptureLength2);

            // 拷贝音频数据
            int audioLength = dwCaptureLength + dwCaptureLength2;

            audioData = new byte[audioLength];
            Marshal.Copy(pbCaptureData, audioData, 0, dwCaptureLength);
            if (pbCaptureData2 != IntPtr.Zero)
            {
                Marshal.Copy(pbCaptureData2, audioData, dwCaptureLength, dwCaptureLength2);
            }

            return((int)dsErr);
        }
Exemple #2
0
        public int Stop()
        {
            uint dsErr = this.dscb8.Stop();

            if (dsErr != DSERR.DS_OK)
            {
                DSLibUtils.PrintLog("停止录音失败, DSERR = {0}", dsErr);
            }

            return((int)dsErr);
        }
Exemple #3
0
        private bool CreateCaptureBuffer(out uint dsErr)
        {
            dsErr = DSERR.DS_OK;

            #region 创建默认音频流格式

            this.wfx = new tWAVEFORMATEX()
            {
                nChannels       = DSLibConsts.Channels,
                nSamplesPerSec  = DSLibConsts.SamplesPerSec,
                wBitsPerSample  = DSLibConsts.BitsPerSample,
                nBlockAlign     = DSLibConsts.BlockAlign,
                nAvgBytesPerSec = DSLibConsts.Bps,
                cbSize          = 0,
                wFormatTag      = DSLibNatives.WAVE_FORMAT_PCM
            };

            this.pwfx_free = DSLibUtils.StructureToPtr(this.wfx);

            this.bufferDesc = new _DSCBUFFERDESC()
            {
                dwFlags       = 0,
                dwSize        = Marshal.SizeOf(typeof(_DSCBUFFERDESC)),
                dwReserved    = 0,
                dwFXCount     = 0,
                dwBufferBytes = DSLibConsts.BufferSize,
                lpwfxFormat   = this.pwfx_free,
                lpDSCFXDesc   = IntPtr.Zero
            };

            this.pBufferDesc_free = DSLibUtils.StructureToPtr(this.bufferDesc);

            #endregion

            IntPtr pdscb;
            Guid   iid_dscb8;
            dsErr = this.dsc8.CreateCaptureBuffer(this.pBufferDesc_free, out pdscb, IntPtr.Zero); //TestInvoke2(this.free_bufferDesc, out ppDSCBuff);
            if (dsErr == DSERR.DS_OK)
            {
                // 获取IDirectSoundCaptureBuffer8接口实例
                iid_dscb8 = new Guid(IID.IID_IDirectSoundCaptureBuffer8);
                Marshal.QueryInterface(pdscb, ref iid_dscb8, out this.pdscb8);
                Marshal.Release(pdscb);
                this.dscb8 = Marshal.GetObjectForIUnknown(this.pdscb8) as IDirectSoundCaptureBuffer8;
            }
            else
            {
                DSLibUtils.PrintLog("CreateCaptureBuffer失败, DSERROR = {0}", dsErr);
                return(false);
            }

            return(true);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        private bool CreateSecondaryBuffer(out uint dsErr)
        {
            dsErr = DSERR.DS_OK;

            #region 创建默认音频流格式

            this.wfx = new tWAVEFORMATEX()
            {
                nChannels       = DSLibConsts.Channels,
                nSamplesPerSec  = DSLibConsts.SamplesPerSec,
                wBitsPerSample  = DSLibConsts.BitsPerSample,
                nBlockAlign     = DSLibConsts.BlockAlign,
                nAvgBytesPerSec = DSLibConsts.Bps,
                cbSize          = 0,
                wFormatTag      = DSLibNatives.WAVE_FORMAT_PCM
            };

            this.pwfx_free = DSLibUtils.StructureToPtr(this.wfx);

            this.dsbd = new _DSBUFFERDESC()
            {
                dwSize          = Marshal.SizeOf(typeof(_DSBUFFERDESC)),
                dwFlags         = (int)DSBCAPS.DSBCAPS_CTRLPOSITIONNOTIFY | (int)DSBCAPS.DSBCAPS_GETCURRENTPOSITION2 | (int)DSBCAPS.DSBCAPS_GLOBALFOCUS,
                lpwfxFormat     = this.pwfx_free,
                guid3DAlgorithm = new _GUID(),
                dwBufferBytes   = DSLibConsts.BufferSize,
                dwReserved      = 0
            };

            #endregion

            IntPtr pdsb;
            dsErr = this.ds8.CreateSoundBuffer(ref this.dsbd, out pdsb, IntPtr.Zero);
            if (dsErr != DSERR.DS_OK)
            {
                DSLibUtils.PrintLog("CreateSoundBuffer失败, DSERR = {0}", dsErr);
                return(false);
            }

            Guid iid_dsb8 = new Guid(IID.IID_IDirectSoundBuffer8);
            Marshal.QueryInterface(pdsb, ref iid_dsb8, out this.pdsb8);
            Marshal.Release(pdsb);
            this.dsb8 = Marshal.GetObjectForIUnknown(this.pdsb8) as IDirectSoundBuffer8;

            return(true);
        }
Exemple #8
0
        private bool WriteDataToBuffer(byte[] data, out uint dsErr)
        {
            IntPtr audioPtr1, audioPtr2;
            uint   audioBytes1, audioBytes2;

            dsErr = this.dsb8.Lock(0, data.Length, out audioPtr1, out audioBytes1, out audioPtr2, out audioBytes2, 0);
            if (dsErr == DSERR.DSERR_BUFFERLOST)
            {
                this.dsb8.Restore();
                dsErr = this.dsb8.Lock(0, data.Length, out audioPtr1, out audioBytes1, out audioPtr2, out audioBytes2, 0);
                if (dsErr != DSERR.DS_OK)
                {
                    DSLibUtils.PrintLog("Lock失败, DSERR = {0}", dsErr);
                    return(false);
                }
            }

            if (data != null && data.Length > 0)
            {
                Marshal.Copy(data, 0, audioPtr1, (int)audioBytes1);
                if (audioPtr2 != IntPtr.Zero)
                {
                    Marshal.Copy(data, (int)audioBytes1, audioPtr2, (int)audioBytes2);
                }
            }
            else
            {
                // 填充空数据
                //DSLibNatives.memset(audioPtr1, 0, audioBytes1);
                //if (audioPtr2 != IntPtr.Zero)
                //{
                //    DSLibNatives.memset(audioPtr2, 0, audioBytes2);
                //}
            }

            dsErr = this.dsb8.Unlock(audioPtr1, (int)audioBytes1, audioPtr2, (int)audioBytes2);
            if (dsErr != DSERR.DS_OK)
            {
                DSLibUtils.PrintLog("Unlock失败, DSERR = {0}", dsErr);
                return(false);
            }

            return(true);
        }
Exemple #9
0
        //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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
        }