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) { LibUtils.PrintLog("Lock失败, DSERROR = {0}", dsErr); return(LibErrors.DS_ERROR); } // 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(LibErrors.SUCCESS); }
public int Stop() { if (!this.isInit) { return(LibErrors.NOT_INITIALIZED); } if (this.stream == null) { return(LibErrors.STREAM_NOT_OPENED); } this.isPlaying = false; uint dsErr = this.dsb8.Stop(); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("Stop失败, DSERR = {0}", dsErr); } this.stream.Seek(0); LibNatives.SetEvent(this.notifyHwnd_close[0]); return(LibErrors.SUCCESS); }
/// <summary> /// 打开音频源 /// </summary> /// <param name="source"></param> /// <returns></returns> public int Open(IAudioSource source) { if (this.stream != null) { this.Close(); } this.stream = IAudioStream.Create(source); if (this.stream == null) { LibUtils.PrintLog("不支持的音频源:{0}", source); return(LibErrors.NOT_SUPPORTED); } int ret = this.stream.Open(); if (ret != LibErrors.SUCCESS) { return(ret); } this.stream.PlaybackProgressChanged += this.Stream_PlaybackProgressChanged; this.stream.DownloadProgressChanged += this.Stream_DownloadProgressChanged; return(LibErrors.SUCCESS); }
public int Initialize() { #region waveInOpen WAVEFORMATEX wfx = new WAVEFORMATEX() { nChannels = Channels, nSamplesPerSec = SamplesPerSec, wBitsPerSample = BitsPerSample, nBlockAlign = BlockAlign, nAvgBytesPerSec = (uint)(BlockAlign * SamplesPerSec), cbSize = 0, wFormatTag = 1 }; this.free_pwfx = LibUtils.StructureToPtr(wfx); this.waveInProcDlg = new waveNatives.waveInProcDlg(this.waveInProc); int retValue = waveNatives.waveInOpen(out this.hwi, waveNatives.WAVE_MAPPER, this.free_pwfx, this.waveInProcDlg, 0, waveNatives.WAVE_FORMAT_DIRECT | waveNatives.CALLBACK_FUNCTION); if (retValue != MMSYSERR.MMSYSERR_NOERROR) { LibUtils.PrintLog("waveInOpen失败, MMSYSERROR = {0}", retValue); return(retValue); } #endregion #region waveInPrepareHeader wavehdr_tag wh = new wavehdr_tag() { lpData = this.free_pAudioData = Marshal.AllocHGlobal((int)(BlockAlign * SamplesPerSec)), dwBufferLength = (BlockAlign * SamplesPerSec), dwFlags = 0x00000002 }; this.whSize = Marshal.SizeOf(typeof(wavehdr_tag)); this.free_pwh = LibUtils.StructureToPtr(wh); retValue = waveNatives.waveInPrepareHeader(hwi, this.free_pwh, (uint)this.whSize); if (retValue != MMSYSERR.MMSYSERR_NOERROR) { LibUtils.PrintLog("waveInPrepareHeader失败, MMSYSERROR = {0}", retValue); return(retValue); } #endregion #region waveInAddBuffer retValue = waveNatives.waveInAddBuffer(hwi, this.free_pwh, (uint)this.whSize); if (retValue != MMSYSERR.MMSYSERR_NOERROR) { LibUtils.PrintLog("waveInAddBuffer失败, MMSYSERROR = {0}", retValue); return(retValue); } #endregion return(MMSYSERR.MMSYSERR_NOERROR); }
public int Stop() { uint dsErr = this.dscb8.Stop(); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("停止录音失败, DSERR = {0}", dsErr); } return(LibErrors.SUCCESS); }
public int Stop() { this.isStop = true; int retValue = waveNatives.waveInStop(this.hwi); if (retValue != MMSYSERR.MMSYSERR_NOERROR) { LibUtils.PrintLog("waveInStop失败, MMSYSERROR = {0}", retValue); } return(MMSYSERR.MMSYSERR_NOERROR); }
private bool CreateCaptureBuffer() { uint dsErr = DSERR.DS_OK; #region 创建默认音频流格式 this.wfx = new tWAVEFORMATEX() { nChannels = LibConsts.Channels, nSamplesPerSec = LibConsts.SamplesPerSec, wBitsPerSample = LibConsts.BitsPerSample, nBlockAlign = LibConsts.BlockAlign, nAvgBytesPerSec = LibConsts.Bps, cbSize = 0, wFormatTag = LibNatives.WAVE_FORMAT_PCM }; this.pwfx_free = LibUtils.StructureToPtr(this.wfx); this.dsbd = new _DSCBUFFERDESC() { dwFlags = 0, dwSize = Marshal.SizeOf(typeof(_DSCBUFFERDESC)), dwReserved = 0, dwFXCount = 0, dwBufferBytes = LibConsts.BufferSize, lpwfxFormat = this.pwfx_free, lpDSCFXDesc = IntPtr.Zero }; #endregion IntPtr pdscb; Guid iid_dscb8; dsErr = this.dsc8.CreateCaptureBuffer(ref this.dsbd, 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 { LibUtils.PrintLog("CreateCaptureBuffer失败, DSERROR = {0}", dsErr); return(false); } return(true); }
private bool CreateBufferNotifications() { uint 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) { LibUtils.PrintLog("GetFormat失败, DSERROR = {0}", dsErr); return(false); } _DSBPOSITIONNOTIFY[] rgdsbpn = new _DSBPOSITIONNOTIFY[LibConsts.NotifyEvents]; this.notifyHwnd_close = new IntPtr[LibConsts.NotifyEvents]; for (int i = 0; i < LibConsts.NotifyEvents; i++) { this.notifyHwnd_close[i] = LibNatives.CreateEvent(IntPtr.Zero, true, false, null); } rgdsbpn[0].dwOffset = (uint)(wfx.nAvgBytesPerSec - 1); rgdsbpn[0].hEventNotify = this.notifyHwnd_close[0]; rgdsbpn[1].dwOffset = LibNatives.DSBPN_OFFSETSTOP; rgdsbpn[1].hEventNotify = this.notifyHwnd_close[1]; dsErr = dsNotify8.SetNotificationPositions(LibConsts.NotifyEvents, Marshal.UnsafeAddrOfPinnedArrayElement(rgdsbpn, 0)); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("SetNotificationPositions失败, DSERROR = {0}", dsErr); return(false); } } finally { Marshal.Release(pdsNotify8); } return(true); }
private bool CreateIDirectSoundCapture8() { uint dsErr = DSERR.DS_OK; dsErr = LibNatives.DirectSoundCaptureCreate8(IntPtr.Zero, out this.pdsc8, IntPtr.Zero); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("DirectSoundCaptureCreate8失败, DSERROR = {0}", dsErr); return(false); } this.dsc8 = Marshal.GetObjectForIUnknown(this.pdsc8) as IDirectSoundCapture8; return(true); }
private bool CreateBufferNotifications() { uint dsErr = DSERR.DS_OK; // 获取IDirectSoundNotify8接口 Guid iid_dsNotify8 = new Guid(IID.IID_IDirectSoundNotify8); IntPtr pdsNotify8; IDirectSoundNotify8 dsNotify8; Marshal.QueryInterface(this.pdsb8, ref iid_dsNotify8, out pdsNotify8); dsNotify8 = Marshal.GetObjectForIUnknown(pdsNotify8) as IDirectSoundNotify8; try { uint written; tWAVEFORMATEX wfx; dsErr = this.dsb8.GetFormat(out wfx, (uint)Marshal.SizeOf(typeof(tWAVEFORMATEX)), out written); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("GetFormat失败, DSERR = {0}", dsErr); return(false); } this.rgdsbpn = new _DSBPOSITIONNOTIFY[LibConsts.BUFF_NOTIFY_TIMES]; this.notifyHwnd_close = new IntPtr[LibConsts.BUFF_NOTIFY_TIMES]; for (int idx = 0; idx < LibConsts.BUFF_NOTIFY_TIMES; idx++) { IntPtr pHandle = LibNatives.CreateEvent(IntPtr.Zero, false, false, null); this.notifyHwnd_close[idx] = pHandle; this.rgdsbpn[idx].dwOffset = (uint)(LibConsts.BUFF_NOTIFY_SIZE * idx); this.rgdsbpn[idx].hEventNotify = pHandle; } dsErr = dsNotify8.SetNotificationPositions(LibConsts.BUFF_NOTIFY_TIMES, Marshal.UnsafeAddrOfPinnedArrayElement(rgdsbpn, 0)); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("SetNotificationPositions失败, DSERROR = {0}", dsErr); return(false); } } finally { Marshal.Release(pdsNotify8); } return(true); }
private bool CreateSecondaryBuffer() { uint dsErr = DSERR.DS_OK; #region 创建默认音频流格式 this.wfx = new tWAVEFORMATEX() { nChannels = LibConsts.Channels, nSamplesPerSec = LibConsts.SamplesPerSec, wBitsPerSample = LibConsts.BitsPerSample, nBlockAlign = LibConsts.BlockAlign, nAvgBytesPerSec = LibConsts.Bps, cbSize = 0, wFormatTag = LibNatives.WAVE_FORMAT_PCM }; this.pwfx_free = LibUtils.StructureToPtr(this.wfx); this.dsbd = new _DSBUFFERDESC() { dwSize = Marshal.SizeOf(typeof(_DSBUFFERDESC)), dwFlags = DSBCAPS.DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS.DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS.DSBCAPS_GLOBALFOCUS | DSBCAPS.DSBCAPS_CTRLVOLUME, lpwfxFormat = this.pwfx_free, guid3DAlgorithm = new _GUID(), dwBufferBytes = LibConsts.PLAY_BUFF_SIZE, dwReserved = 0 }; #endregion IntPtr pdsb; dsErr = this.ds8.CreateSoundBuffer(ref this.dsbd, out pdsb, IntPtr.Zero); if (dsErr != DSERR.DS_OK) { LibUtils.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); }
private bool WriteDataToBuffer(uint offset, byte[] data) { IntPtr audioPtr1, audioPtr2; uint audioBytes1, audioBytes2, dataLength = (uint)data.Length; uint dsErr = this.dsb8.Lock(offset, dataLength, out audioPtr1, out audioBytes1, out audioPtr2, out audioBytes2, 0); if (dsErr == DSERR.DSERR_BUFFERLOST) { this.dsb8.Restore(); dsErr = this.dsb8.Lock(offset, dataLength, out audioPtr1, out audioBytes1, out audioPtr2, out audioBytes2, 0); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("Lock失败, DSERR = {0}", dsErr); return(false); } } if (data != null && data.Length > 0) { Marshal.Copy(data, 0, audioPtr1, (int)audioBytes1); if (audioBytes2 > 0 && 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, audioBytes1, audioPtr2, audioBytes2); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("Unlock失败, DSERR = {0}", dsErr); return(false); } return(true); }
private void HandleNotification(uint offset, int playSize, SynchronizationContext ctx) { byte[] buffer; int ret = this.stream.Read(playSize, out buffer); if (ret == LibErrors.SUCCESS) { #region 读取音频流成功 ctx.Send((o) => { //DSLibUtils.PrintLog("播放缓冲区数据, 大小:{0}字节", buffer.Length); try { if (this.WriteDataToBuffer(offset, buffer)) { } } catch (Exception ex) { LibUtils.PrintLog("播放音频流异常, Exception = {0}", ex); } }, null); #endregion } else if (ret == LibErrors.NO_DATA) { #region 没数据了, 播放完毕 ctx.Send((o) => { LibUtils.PrintLog("缓冲区播放完毕, 停止播放"); this.Stop(); this.NotifyStatusChanged(DSLibPlayerStatus.Stopped, 0); }, null); #endregion } }
//public int Pause() //{ // return DSERR.DS_OK; //} //public int Restore() //{ // return DSERR.DS_OK; //} #endregion #region 实例方法 private bool CreateIDirectSound8(IntPtr hwnd) { uint dsErr = LibNatives.DirectSoundCreate8(IntPtr.Zero, out this.pds8, IntPtr.Zero); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("DirectSoundCreate8失败, DSERR = {0}", dsErr); return(false); } this.ds8 = Marshal.GetObjectForIUnknown(this.pds8) as IDirectSound8; dsErr = this.ds8.SetCooperativeLevel(hwnd, DSSCL.DSSCL_NORMAL); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("SetCooperativeLevel失败, DSERR = {0}", dsErr); return(false); } return(true); }
private void waveInProc(IntPtr hwi, uint uMsg, uint dwInstance, uint dwParam1, uint dwParam2) { switch (uMsg) { case (uint)waveNatives.uMsgEnum.WIM_OPEN: LibUtils.PrintLog("OPEN"); break; case (uint)waveNatives.uMsgEnum.WIM_DATA: if (this.isStop) { break; } wavehdr_tag hdr = (wavehdr_tag)Marshal.PtrToStructure(this.free_pwh, typeof(wavehdr_tag)); // 处理音频数据 { byte[] buffer = new byte[hdr.dwBytesRecorded]; Marshal.Copy(hdr.lpData, buffer, 0, buffer.Length); if (this.AudioCaptured != null) { this.AudioCaptured(buffer); } } int retValue = waveNatives.waveInAddBuffer(hwi, this.free_pwh, (uint)this.whSize); if (retValue != MMSYSERR.MMSYSERR_NOERROR) { LibUtils.PrintLog("waveInAddBuffer失败, MMSYSERROR = {0}", retValue); } break; case (uint)waveNatives.uMsgEnum.WIM_CLOSE: LibUtils.PrintLog("CLOSE"); break; } }
public override int Open() { if (!File.Exists(this.source.Path)) { LibUtils.PrintLog("AudioSource.Open失败, 文件不存在, Uri = {0}", this.source.Path); return(LibErrors.FILE_NOT_EXISTS); } base.isDownloading = true; try { this.stream = File.Open(this.source.Path, FileMode.Open); } catch (Exception ex) { LibUtils.PrintLog("AudioSource.Open失败, 打开文件失败, 异常信息:{0}", ex); return(LibErrors.OPEN_FILE_FAILED); } base.isDownloading = false; return(LibErrors.SUCCESS); }
public int Start() { uint dsErr = this.dscb8.Start(LibNatives.DSCBSTART_LOOPING); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("开始录音失败, DSERROR = {0}", dsErr); return(LibErrors.DS_ERROR); } 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 (LibNatives.WaitForMultipleObjects(LibConsts.NotifyEvents, lpHandles, false, LibNatives.INFINITE)) { case LibNatives.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.OnCaptured != null) { this.OnCaptured(audioData); } } } catch (Exception ex) { LibUtils.PrintLog("保存音频流异常, Exception = {0}", ex); } }, null); LibNatives.ResetEvent(this.notifyHwnd_close[0]); } break; case LibNatives.WAIT_OBJECT_0 + 1: { // 录音结束 LibNatives.ResetEvent(this.notifyHwnd_close[1]); this.isRunning = false; } break; case LibNatives.WAIT_FAILED: { int error = Marshal.GetLastWin32Error(); // 失败, 句柄已经被销毁 LibUtils.PrintLog("WAIT_FAILED, LastWin32Error = {0}", error); this.isRunning = false; this.Stop(); if (this.OnError != null) { this.OnError(error); } } break; } } }, SynchronizationContext.Current); return(LibErrors.SUCCESS); }
public int Play() { if (!this.isInit) { return(LibErrors.NOT_INITIALIZED); } if (this.stream == null) { return(LibErrors.STREAM_NOT_OPENED); } this.dsb8.SetCurrentPosition(0); uint dsErr = this.dsb8.Play(0, 0, DSBPLAY.DSBPLAY_LOOPING); if (dsErr != DSERR.DS_OK) { LibUtils.PrintLog("Play失败, DSERR = {0}", dsErr); return(LibErrors.DS_ERROR); } this.isPlaying = true; this.NotifyStatusChanged(DSLibPlayerStatus.Playing, 0); uint offset = (uint)LibConsts.BUFF_NOTIFY_SIZE; Task.Factory.StartNew((state) => { while (this.isPlaying) { IntPtr lpHandles = Marshal.UnsafeAddrOfPinnedArrayElement(this.notifyHwnd_close, 0); uint notifyIdx = LibNatives.WaitForMultipleObjects(LibConsts.BUFF_NOTIFY_TIMES, lpHandles, false, LibNatives.INFINITE); if ((notifyIdx >= LibNatives.WAIT_OBJECT_0) && (notifyIdx <= LibNatives.WAIT_OBJECT_0 + LibConsts.BUFF_NOTIFY_TIMES)) { if (!this.isPlaying) { // 通知是异步的,在调用了Stop之后, 如果收到通知的速度比音频流Seek(0)的速度慢(也就是说先重置了音频流,然后又收到了一次通知), 有可能会再次读取一次数据 break; } this.HandleNotification(offset, LibConsts.BUFF_NOTIFY_SIZE, state as SynchronizationContext); offset += (uint)LibConsts.BUFF_NOTIFY_SIZE; offset %= (uint)(LibConsts.BUFF_NOTIFY_SIZE * LibConsts.BUFF_NOTIFY_TIMES); //Console.WriteLine("dwOffset = {0}, offset = {1}", this.rgdsbpn[notifyIdx].dwOffset, offset); } else if (notifyIdx == LibNatives.WAIT_FAILED) { int winErr = Marshal.GetLastWin32Error(); LibUtils.PrintLog("等待信号失败, LastWin32Error = {0}", winErr); (state as SynchronizationContext).Send((o) => { this.Stop(); }, null); this.NotifyStatusChanged(DSLibPlayerStatus.Error, winErr); } } LibUtils.PrintLog("跳出循环"); }, SynchronizationContext.Current); return(LibErrors.SUCCESS); }
/// <summary> /// 向DirectSound缓冲区Put音频数据 /// </summary> /// <param name="buffer">要Put的数据</param> /// <param name="type">Put的数据类型</param> public void PutBuffer(byte[] buffer) { LibUtils.PrintLog("PutBuffer, Size = {0}", buffer.Length); this.audioStream.PutBuffer(buffer); }