/// <summary> /// Stop playback /// </summary> private void StopPlayback() { lock (this.m_LockObject) { if (secondaryBuffer != null) { CleanUpSecondaryBuffer(); secondaryBuffer.Stop(); Marshal.ReleaseComObject(secondaryBuffer); secondaryBuffer = null; } if (primarySoundBuffer != null) { primarySoundBuffer.Stop(); Marshal.ReleaseComObject(primarySoundBuffer); primarySoundBuffer = null; } if (directSound != null) { Marshal.ReleaseComObject(directSound); directSound = null; } } }
public void Dispose() { // This doesn't follow the Microsoft Dispose pattern because that one sucks (http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html) // This also doesn't follow the Cleary's pattern because it's too much work. // If an IDisposable field were added to this class, this code would need further work because of that, but until then this is acceptable. if (soundBufferDescription.lpwfxFormat != IntPtr.Zero) { Marshal.FreeHGlobal(soundBufferDescription.lpwfxFormat); soundBufferDescription.lpwfxFormat = IntPtr.Zero; } if (directSoundDevice != null) { Marshal.ReleaseComObject(directSoundDevice); directSoundDevice = null; } }
public Beeper() { // Silently fail DirectSound creation if (!WinAPI.ModuleContainsFunction(DirectSoundModuleName, "DirectSoundCreate", true, true)) { return; } if (DirectSoundCreate(IntPtr.Zero, out directSoundDevice, IntPtr.Zero) < 0) { return; } if (directSoundDevice.SetCooperativeLevel(GetDesktopWindow(), DSSCL_NORMAL) < 0) { Marshal.ReleaseComObject(directSoundDevice); directSoundDevice = null; return; } WAVEFORMATEX waveFormat; waveFormat.cbSize = (short)Marshal.SizeOf(typeof(WAVEFORMATEX)); waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = NumberOfChannels; waveFormat.wBitsPerSample = BitsPerSamplePerChannel; waveFormat.nSamplesPerSec = SamplingRate; waveFormat.nBlockAlign = (short)(waveFormat.nChannels * waveFormat.wBitsPerSample / 8); waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; // The wave format never changes so we marshal it to unmanaged memory and reuse it in calls // to CreateSoundBuffer. IntPtr unmanagedWaveFormat = Marshal.AllocHGlobal(waveFormat.cbSize); Marshal.StructureToPtr(waveFormat, unmanagedWaveFormat, false); // These fields never change soundBufferDescription.dwSize = Marshal.SizeOf(typeof(DSBUFFERDESC)); soundBufferDescription.dwReserved = 0; soundBufferDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS; soundBufferDescription.lpwfxFormat = unmanagedWaveFormat; }
public Beeper() { // Silently fail DirectSound creation if (!WinAPI.ModuleContainsFunction(DirectSoundModuleName, "DirectSoundCreate", true, true)) return; if (DirectSoundCreate(IntPtr.Zero, out directSoundDevice, IntPtr.Zero) < 0) return; if (directSoundDevice.SetCooperativeLevel(GetDesktopWindow(), DSSCL_NORMAL) < 0) { Marshal.ReleaseComObject(directSoundDevice); directSoundDevice = null; return; } WAVEFORMATEX waveFormat; waveFormat.cbSize = (short) Marshal.SizeOf(typeof(WAVEFORMATEX)); waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = NumberOfChannels; waveFormat.wBitsPerSample = BitsPerSamplePerChannel; waveFormat.nSamplesPerSec = SamplingRate; waveFormat.nBlockAlign = (short) (waveFormat.nChannels * waveFormat.wBitsPerSample / 8); waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; // The wave format never changes so we marshal it to unmanaged memory and reuse it in calls // to CreateSoundBuffer. IntPtr unmanagedWaveFormat = Marshal.AllocHGlobal(waveFormat.cbSize); Marshal.StructureToPtr(waveFormat, unmanagedWaveFormat, false); // These fields never change soundBufferDescription.dwSize = Marshal.SizeOf(typeof(DSBUFFERDESC)); soundBufferDescription.dwReserved = 0; soundBufferDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS; soundBufferDescription.lpwfxFormat = unmanagedWaveFormat; }
private void InitializeDirectSound() { // Open DirectSound lock (this.m_LockObject) { directSound = null; DirectSoundCreate(ref device, out directSound, IntPtr.Zero); if (directSound != null) { // Set Cooperative Level to PRIORITY (priority level can call the SetFormat and Compact methods) directSound.SetCooperativeLevel(GetDesktopWindow(), DirectSoundCooperativeLevel.DSSCL_PRIORITY); // ------------------------------------------------------------------------------------- // Create PrimaryBuffer // ------------------------------------------------------------------------------------- // Fill BufferDescription for PrimaryBuffer BufferDescription bufferDesc = new BufferDescription(); bufferDesc.dwSize = Marshal.SizeOf(bufferDesc); bufferDesc.dwBufferBytes = 0; bufferDesc.dwFlags = DirectSoundBufferCaps.DSBCAPS_PRIMARYBUFFER; bufferDesc.dwReserved = 0; bufferDesc.lpwfxFormat = IntPtr.Zero; bufferDesc.guidAlgo = Guid.Empty; object soundBufferObj; // Create PrimaryBuffer directSound.CreateSoundBuffer(bufferDesc, out soundBufferObj, IntPtr.Zero); primarySoundBuffer = (IDirectSoundBuffer)soundBufferObj; // Play & Loop on the PrimarySound Buffer primarySoundBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING); // ------------------------------------------------------------------------------------- // Create SecondaryBuffer // ------------------------------------------------------------------------------------- // A frame of samples equals to Desired Latency samplesFrameSize = MsToBytes(desiredLatency); // Fill BufferDescription for SecondaryBuffer BufferDescription bufferDesc2 = new BufferDescription(); bufferDesc2.dwSize = Marshal.SizeOf(bufferDesc2); bufferDesc2.dwBufferBytes = (uint)(samplesFrameSize * 2); bufferDesc2.dwFlags = DirectSoundBufferCaps.DSBCAPS_GETCURRENTPOSITION2 | DirectSoundBufferCaps.DSBCAPS_CTRLPOSITIONNOTIFY | DirectSoundBufferCaps.DSBCAPS_GLOBALFOCUS | DirectSoundBufferCaps.DSBCAPS_CTRLVOLUME | DirectSoundBufferCaps.DSBCAPS_STICKYFOCUS | DirectSoundBufferCaps.DSBCAPS_GETCURRENTPOSITION2; bufferDesc2.dwReserved = 0; GCHandle handleOnWaveFormat = GCHandle.Alloc(waveFormat, GCHandleType.Pinned); // Ptr to waveFormat bufferDesc2.lpwfxFormat = handleOnWaveFormat.AddrOfPinnedObject(); // set Ptr to waveFormat bufferDesc2.guidAlgo = Guid.Empty; // Create SecondaryBuffer directSound.CreateSoundBuffer(bufferDesc2, out soundBufferObj, IntPtr.Zero); secondaryBuffer = (IDirectSoundBuffer)soundBufferObj; handleOnWaveFormat.Free(); // Get effective SecondaryBuffer size BufferCaps dsbCaps = new BufferCaps(); dsbCaps.dwSize = Marshal.SizeOf(dsbCaps); secondaryBuffer.GetCaps(dsbCaps); nextSamplesWriteIndex = 0; samplesTotalSize = dsbCaps.dwBufferBytes; samples = new byte[samplesTotalSize]; System.Diagnostics.Debug.Assert(samplesTotalSize == (2 * samplesFrameSize), "Invalid SamplesTotalSize vs SamplesFrameSize"); // ------------------------------------------------------------------------------------- // Create double buffering notification. // Use DirectSoundNotify at Position [0, 1/2] and Stop Position (0xFFFFFFFF) // ------------------------------------------------------------------------------------- IDirectSoundNotify notify = (IDirectSoundNotify)soundBufferObj; frameEventWaitHandle1 = new EventWaitHandle(false, EventResetMode.AutoReset); frameEventWaitHandle2 = new EventWaitHandle(false, EventResetMode.AutoReset); endEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); DirectSoundBufferPositionNotify[] notifies = new DirectSoundBufferPositionNotify[3]; notifies[0] = new DirectSoundBufferPositionNotify(); notifies[0].dwOffset = 0; notifies[0].hEventNotify = frameEventWaitHandle1.SafeWaitHandle.DangerousGetHandle(); notifies[1] = new DirectSoundBufferPositionNotify(); notifies[1].dwOffset = (uint)samplesFrameSize; notifies[1].hEventNotify = frameEventWaitHandle2.SafeWaitHandle.DangerousGetHandle(); notifies[2] = new DirectSoundBufferPositionNotify(); notifies[2].dwOffset = 0xFFFFFFFF; notifies[2].hEventNotify = endEventWaitHandle.SafeWaitHandle.DangerousGetHandle(); notify.SetNotificationPositions(3, notifies); } } }
static extern void DirectSoundCreate(ref Guid GUID, [Out, MarshalAs(UnmanagedType.Interface)] out IDirectSound directSound, IntPtr pUnkOuter);
private void InitializeDirectSound() { // Open DirectSound lock (this.m_LockObject) { directSound = null; DirectSoundCreate(ref device, out directSound, IntPtr.Zero); if (directSound != null) { // Set Cooperative Level to PRIORITY (priority level can call the SetFormat and Compact methods) directSound.SetCooperativeLevel(GetDesktopWindow(), DirectSoundCooperativeLevel.DSSCL_PRIORITY); // ------------------------------------------------------------------------------------- // Create PrimaryBuffer // ------------------------------------------------------------------------------------- // Fill BufferDescription for PrimaryBuffer BufferDescription bufferDesc = new BufferDescription(); bufferDesc.dwSize = Marshal.SizeOf(bufferDesc); bufferDesc.dwBufferBytes = 0; bufferDesc.dwFlags = DirectSoundBufferCaps.DSBCAPS_PRIMARYBUFFER; bufferDesc.dwReserved = 0; bufferDesc.lpwfxFormat = IntPtr.Zero; bufferDesc.guidAlgo = Guid.Empty; object soundBufferObj; // Create PrimaryBuffer directSound.CreateSoundBuffer(bufferDesc, out soundBufferObj, IntPtr.Zero); primarySoundBuffer = (IDirectSoundBuffer)soundBufferObj; // Play & Loop on the PrimarySound Buffer primarySoundBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING); // ------------------------------------------------------------------------------------- // Create SecondaryBuffer // ------------------------------------------------------------------------------------- // A frame of samples equals to Desired Latency samplesFrameSize = MsToBytes(desiredLatency); // Fill BufferDescription for SecondaryBuffer BufferDescription bufferDesc2 = new BufferDescription(); bufferDesc2.dwSize = Marshal.SizeOf(bufferDesc2); bufferDesc2.dwBufferBytes = (uint)(samplesFrameSize * 2); bufferDesc2.dwFlags = DirectSoundBufferCaps.DSBCAPS_GETCURRENTPOSITION2 | DirectSoundBufferCaps.DSBCAPS_CTRLPOSITIONNOTIFY | DirectSoundBufferCaps.DSBCAPS_GLOBALFOCUS | DirectSoundBufferCaps.DSBCAPS_CTRLVOLUME | DirectSoundBufferCaps.DSBCAPS_STICKYFOCUS; bufferDesc2.dwReserved = 0; GCHandle handleOnWaveFormat = GCHandle.Alloc(waveFormat, GCHandleType.Pinned); // Ptr to waveFormat bufferDesc2.lpwfxFormat = handleOnWaveFormat.AddrOfPinnedObject(); // set Ptr to waveFormat bufferDesc2.guidAlgo = Guid.Empty; // Create SecondaryBuffer directSound.CreateSoundBuffer(bufferDesc2, out soundBufferObj, IntPtr.Zero); secondaryBuffer = (IDirectSoundBuffer)soundBufferObj; handleOnWaveFormat.Free(); // Get effective SecondaryBuffer size BufferCaps dsbCaps = new BufferCaps(); dsbCaps.dwSize = Marshal.SizeOf(dsbCaps); secondaryBuffer.GetCaps(dsbCaps); nextSamplesWriteIndex = 0; samplesTotalSize = dsbCaps.dwBufferBytes; samples = new byte[samplesTotalSize]; System.Diagnostics.Debug.Assert(samplesTotalSize == (2 * samplesFrameSize), "Invalid SamplesTotalSize vs SamplesFrameSize"); // ------------------------------------------------------------------------------------- // Create double buffering notification. // Use DirectSoundNotify at Position [0, 1/2] and Stop Position (0xFFFFFFFF) // ------------------------------------------------------------------------------------- IDirectSoundNotify notify = (IDirectSoundNotify)soundBufferObj; frameEventWaitHandle1 = new EventWaitHandle(false, EventResetMode.AutoReset); frameEventWaitHandle2 = new EventWaitHandle(false, EventResetMode.AutoReset); endEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); DirectSoundBufferPositionNotify[] notifies = new DirectSoundBufferPositionNotify[3]; notifies[0] = new DirectSoundBufferPositionNotify(); notifies[0].dwOffset = 0; notifies[0].hEventNotify = frameEventWaitHandle1.SafeWaitHandle.DangerousGetHandle(); notifies[1] = new DirectSoundBufferPositionNotify(); notifies[1].dwOffset = (uint)samplesFrameSize; notifies[1].hEventNotify = frameEventWaitHandle2.SafeWaitHandle.DangerousGetHandle(); notifies[2] = new DirectSoundBufferPositionNotify(); notifies[2].dwOffset = 0xFFFFFFFF; notifies[2].hEventNotify = endEventWaitHandle.SafeWaitHandle.DangerousGetHandle(); notify.SetNotificationPositions(3, notifies); } } }
extern static int DirectSoundCreate(IntPtr pcGuidDevice, out IDirectSound ppDS, IntPtr pUnkOuter);
public static extern int DirectSoundCreate(IntPtr pcGuidDevice, [MarshalAs(UnmanagedType.Interface)] out IDirectSound pDS, IntPtr pUnkOuter);
static extern int DirectSoundCreate(IntPtr pcGuidDevice, out IDirectSound ppDS, IntPtr pUnkOuter);