source: trunk/csharp/audio/NAudio/Wave/WaveOutputs/DirectSoundOut.cs @ 1346

Revision 1346, 28.1 KB checked in by avneesh-singh, 5 years ago (diff)

adding NAudio source.

Line 
1using System;
2using System.Runtime.InteropServices;
3using System.Security;
4using System.Threading;
5
6namespace NAudio.Wave
7{
8    /// <summary>
9    /// NativeDirectSoundOut using DirectSound COM interop.
10    /// Contact author: Alexandre Mutel - alexandre_mutel at yahoo.fr
11    /// Modified by: Graham "Gee" Plumb
12    /// </summary>
13    public class DirectSoundOut : IWavePlayer
14    {
15        /// <summary>
16        /// Playback Stopped
17        /// </summary>
18        public event EventHandler PlaybackStopped;
19
20        private PlaybackState playbackState;
21        private WaveFormat waveFormat;
22        private int samplesTotalSize;
23        private int samplesFrameSize;
24        private int nextSamplesWriteIndex;
25        private int desiredLatency;
26        private WaveBuffer samples;
27        private IWaveProvider waveStream = null;
28        private IDirectSound directSound = null;
29        private IDirectSoundBuffer primarySoundBuffer = null;
30        private IDirectSoundBuffer secondaryBuffer = null;
31        private EventWaitHandle frameEventWaitHandle1;
32        private EventWaitHandle frameEventWaitHandle2;
33        private EventWaitHandle endEventWaitHandle;
34        private Thread notifyThread;
35
36        // Used purely for locking
37        private Object m_LockObject = new Object();
38
39
40        /// <summary>
41        /// Initializes a new instance of the <see cref="DirectSoundOut"/> class.
42        /// </summary>
43        public DirectSoundOut()
44            : this(40)
45        {
46        }
47
48        /// <summary>
49        /// Initializes a new instance of the <see cref="DirectSoundOut"/> class.
50        /// (40ms seems to work under Vista).
51        /// </summary>
52        /// <param name="latency">The latency.</param>
53        public DirectSoundOut(int latency)
54        {
55            desiredLatency = latency;
56        }
57
58        /// <summary>
59        /// Releases unmanaged resources and performs other cleanup operations before the
60        /// <see cref="DirectSoundOut"/> is reclaimed by garbage collection.
61        /// </summary>
62        ~DirectSoundOut()
63        {
64            Dispose();
65        }
66
67        /// <summary>
68        /// Begin playback
69        /// </summary>
70        public void Play()
71        {
72            if (playbackState == PlaybackState.Stopped)
73            {
74                // -------------------------------------------------------------------------------------
75                // Thread that process samples
76                // -------------------------------------------------------------------------------------
77                notifyThread = new Thread(new ThreadStart(processSamples));
78                // put this back to highest when we are confident we don't have any bugs in the thread proc
79                notifyThread.Priority = ThreadPriority.Normal;
80                notifyThread.IsBackground = true;
81                notifyThread.Start();
82            }
83
84            lock (m_LockObject)
85            {
86                playbackState = PlaybackState.Playing;
87            }
88        }
89
90        /// <summary>
91        /// Stop playback
92        /// </summary>
93        public void Stop()
94        {
95            // Try and tidy up nicely
96            if (Monitor.TryEnter(m_LockObject, 50))
97            {
98                playbackState = PlaybackState.Stopped;
99                Monitor.Exit(m_LockObject);
100            }
101            else
102            {
103                // No joy - abort the thread!
104                if (notifyThread != null)
105                {
106                    notifyThread.Abort();
107                    notifyThread = null;
108                }
109            }
110        }
111
112        /// <summary>
113        /// Pause Playback
114        /// </summary>
115        public void Pause()
116        {
117            lock (m_LockObject)
118            {
119                playbackState = PlaybackState.Paused;
120            }
121        }
122
123
124        /// <summary>
125        /// Initialise playback
126        /// </summary>
127        /// <param name="waveProvider">The waveprovider to be played</param>
128        public void Init(IWaveProvider waveProvider)
129        {
130            this.waveStream = waveProvider;
131            this.waveFormat = waveProvider.WaveFormat;
132        }
133
134        private void InitialiseDirectSound()
135        {
136            try
137            {
138                // Open DirectSound
139                lock (this.m_LockObject)
140                {
141                    directSound = null;
142                    DirectSoundCreate(IntPtr.Zero, out directSound, IntPtr.Zero);
143
144                    if (directSound != null)
145                    {
146                        // Set Cooperative Level to PRIORITY (priority level can call the SetFormat and Compact methods)
147                        directSound.SetCooperativeLevel(GetDesktopWindow(), DirectSoundCooperativeLevel.DSSCL_PRIORITY);
148
149                        // -------------------------------------------------------------------------------------
150                        // Create PrimaryBuffer
151                        // -------------------------------------------------------------------------------------
152
153                        // Fill BufferDescription for PrimaryBuffer
154                        BufferDescription bufferDesc = new BufferDescription();
155                        bufferDesc.dwSize = Marshal.SizeOf(bufferDesc);
156                        bufferDesc.dwBufferBytes = 0;
157                        bufferDesc.dwFlags = DirectSoundBufferCaps.DSBCAPS_PRIMARYBUFFER;
158                        bufferDesc.dwReserved = 0;
159                        bufferDesc.lpwfxFormat = IntPtr.Zero;
160                        bufferDesc.guidAlgo = Guid.Empty;
161
162                        object soundBufferObj;
163                        // Create PrimaryBuffer
164                        directSound.CreateSoundBuffer(bufferDesc, out soundBufferObj, IntPtr.Zero);
165                        primarySoundBuffer = (IDirectSoundBuffer)soundBufferObj;
166
167                        // Play & Loop on the PrimarySound Buffer
168                        primarySoundBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING);
169
170                        // -------------------------------------------------------------------------------------
171                        // Create SecondaryBuffer
172                        // -------------------------------------------------------------------------------------
173
174                        // A frame of samples equals to Desired Latency
175                        samplesFrameSize = MsToBytes(desiredLatency);
176
177                        // Fill BufferDescription for SecondaryBuffer
178                        BufferDescription bufferDesc2 = new BufferDescription();
179                        bufferDesc2.dwSize = Marshal.SizeOf(bufferDesc2);
180                        bufferDesc2.dwBufferBytes = (uint)(samplesFrameSize * 2);
181                        bufferDesc2.dwFlags = DirectSoundBufferCaps.DSBCAPS_GETCURRENTPOSITION2
182                            | DirectSoundBufferCaps.DSBCAPS_CTRLPOSITIONNOTIFY
183                            | DirectSoundBufferCaps.DSBCAPS_GLOBALFOCUS
184                            | DirectSoundBufferCaps.DSBCAPS_CTRLVOLUME
185                            | DirectSoundBufferCaps.DSBCAPS_STICKYFOCUS;
186                        bufferDesc2.dwReserved = 0;
187                        GCHandle handleOnWaveFormat = GCHandle.Alloc(waveFormat, GCHandleType.Pinned); // Ptr to waveFormat
188                        bufferDesc2.lpwfxFormat = handleOnWaveFormat.AddrOfPinnedObject(); // set Ptr to waveFormat
189                        bufferDesc2.guidAlgo = Guid.Empty;
190
191                        // Create SecondaryBuffer
192                        directSound.CreateSoundBuffer(bufferDesc2, out soundBufferObj, IntPtr.Zero);
193                        secondaryBuffer = (IDirectSoundBuffer)soundBufferObj;
194                        handleOnWaveFormat.Free();
195
196                        // Get effective SecondaryBuffer size
197                        BufferCaps dsbCaps = new BufferCaps();
198                        dsbCaps.dwSize = Marshal.SizeOf(dsbCaps);
199                        secondaryBuffer.GetCaps(dsbCaps);
200
201                        nextSamplesWriteIndex = 0;
202                        samplesTotalSize = dsbCaps.dwBufferBytes;
203                        samples = new WaveBuffer(samplesTotalSize);
204                        System.Diagnostics.Debug.Assert(samplesTotalSize == (2 * samplesFrameSize), "Invalid SamplesTotalSize vs SamplesFrameSize");
205
206                        // -------------------------------------------------------------------------------------
207                        // Create double buffering notification.
208                        // Use DirectSoundNotify at Position [0, 1/2] and Stop Position (0xFFFFFFFF)
209                        // -------------------------------------------------------------------------------------
210                        IDirectSoundNotify notify = (IDirectSoundNotify)soundBufferObj;
211
212                        frameEventWaitHandle1 = new EventWaitHandle(false, EventResetMode.AutoReset);
213                        frameEventWaitHandle2 = new EventWaitHandle(false, EventResetMode.AutoReset);
214                        endEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
215
216                        DirectSoundBufferPositionNotify[] notifies = new DirectSoundBufferPositionNotify[3];
217                        notifies[0] = new DirectSoundBufferPositionNotify();
218                        notifies[0].dwOffset = 0;
219                        notifies[0].hEventNotify = frameEventWaitHandle1.SafeWaitHandle.DangerousGetHandle();
220
221                        notifies[1] = new DirectSoundBufferPositionNotify();
222                        notifies[1].dwOffset = (uint)samplesFrameSize;
223                        notifies[1].hEventNotify = frameEventWaitHandle2.SafeWaitHandle.DangerousGetHandle();
224
225                        notifies[2] = new DirectSoundBufferPositionNotify();
226                        notifies[2].dwOffset = 0xFFFFFFFF;
227                        notifies[2].hEventNotify = endEventWaitHandle.SafeWaitHandle.DangerousGetHandle();
228
229                        notify.SetNotificationPositions(3, notifies);
230                    }
231                }
232            }
233            catch (Exception error)
234            {
235                throw error;
236            }
237        }
238
239        /// <summary>
240        /// Current playback state
241        /// </summary>
242        /// <value></value>
243        public PlaybackState PlaybackState
244        {
245            get { return playbackState; }
246        }
247
248        /// <summary>
249        /// The volume 1.0 is full scale
250        /// </summary>
251        /// <value></value>
252        public float Volume
253        {
254            get
255            {
256                return 1.0f;
257                //return 1 + (secondaryBuffer.GetVolume()) / 10000.0f;
258            }
259            set
260            {
261                //int intVol = (int)((value - 1) * 10000.0f);
262                //secondaryBuffer.SetVolume(intVol);
263            }
264        }
265
266        /// <summary>
267        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
268        /// </summary>
269        public void Dispose()
270        {
271            Stop();
272            GC.SuppressFinalize(this);
273        }
274
275        /// <summary>
276        /// Determines whether the SecondaryBuffer is lost.
277        /// </summary>
278        /// <returns>
279        ///     <c>true</c> if [is buffer lost]; otherwise, <c>false</c>.
280        /// </returns>
281        private bool IsBufferLost()
282        {
283            return (secondaryBuffer.GetStatus() & DirectSoundBufferStatus.DSBSTATUS_BUFFERLOST) != 0 ? true : false;
284        }
285
286        /// <summary>
287        /// Convert ms to bytes size according to WaveFormat
288        /// </summary>
289        /// <param name="ms">The ms</param>
290        /// <returns>number of byttes</returns>
291        private int MsToBytes(int ms)
292        {
293            int bytes = ms * (waveFormat.AverageBytesPerSecond / 1000);
294            bytes -= bytes % waveFormat.BlockAlign;
295            return bytes;
296        }
297
298        /// <summary>
299        /// Processes the samples in a separate thread.
300        /// </summary>
301        private void processSamples()
302        {
303            // Used to determine if playback is halted
304            bool lPlaybackHalted = false;
305
306            // Incase the thread is killed
307            try
308            {
309                InitialiseDirectSound();
310                int lResult = 1;
311
312                if (PlaybackState == PlaybackState.Stopped)
313                {
314                    secondaryBuffer.SetCurrentPosition(0);
315                    nextSamplesWriteIndex = 0;
316                    lResult = Feed(samplesTotalSize);
317                }
318
319                // Incase the previous Feed method returns 0
320                if (lResult > 0)
321                {
322                    lock (m_LockObject)
323                    {
324                        playbackState = PlaybackState.Playing;
325                    }
326
327                    secondaryBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING);
328
329                    WaitHandle[] waitHandles = new WaitHandle[] { frameEventWaitHandle1, frameEventWaitHandle2, endEventWaitHandle };
330
331                    bool lContinuePlayback = true;
332                    while (PlaybackState != PlaybackState.Stopped && lContinuePlayback)
333                    {
334                        // Wait for signals on frameEventWaitHandle1 (Position 0), frameEventWaitHandle2 (Position 1/2)
335                        int indexHandle = WaitHandle.WaitAny(waitHandles, 3 * desiredLatency, false);
336
337                        // TimeOut is ok
338                        if (indexHandle != WaitHandle.WaitTimeout)
339                        {
340                            // Buffer is Stopped
341                            if (indexHandle == 2)
342                            {
343                                // (Gee) - Not sure whether to stop playback in this case or not!
344                                StopPlayback();
345                                lPlaybackHalted = true;
346                                lContinuePlayback = false;
347                            }
348                            else
349                            {
350                                indexHandle = (indexHandle == 0) ? 1 : 0;
351                                nextSamplesWriteIndex = indexHandle * samplesFrameSize;
352
353                                // Only carry on playing if we can!
354                                if (Feed(samplesFrameSize) == 0)
355                                {
356                                    StopPlayback();
357                                    lPlaybackHalted = true;
358                                    lContinuePlayback = false;
359                                }
360                            }
361                        }
362                        else
363                        {
364                            // Timed out!
365                            StopPlayback();
366                            lPlaybackHalted = true;
367                            lContinuePlayback = false;
368                        }
369                    }
370                }
371            }
372            catch (Exception)
373            {
374                // Do nothing!
375            }
376            finally
377            {
378                if (!lPlaybackHalted)
379                {
380                    StopPlayback();
381                }
382
383                lock (m_LockObject)
384                {
385                    playbackState = PlaybackState.Stopped;
386                }
387
388                // Fire playback stopped event
389                if (PlaybackStopped != null)
390                {
391                    PlaybackStopped(this, EventArgs.Empty);
392                }
393            }
394        }
395
396
397        /// <summary>
398        /// Stop playback
399        /// </summary>
400        private void StopPlayback()
401        {
402            lock (this.m_LockObject)
403            {
404                if (secondaryBuffer != null)
405                {
406                    secondaryBuffer.Stop();
407                    secondaryBuffer = null;
408                }
409                if (primarySoundBuffer != null)
410                {
411                    primarySoundBuffer.Stop();
412                    primarySoundBuffer = null;
413                }
414            }
415        }
416
417
418        /// <summary>
419        /// Feeds the SecondaryBuffer with the WaveStream
420        /// </summary>
421        /// <param name="bytesToCopy">number of bytes to feed</param>
422        private int Feed(int bytesToCopy)
423        {
424            int bytesRead = bytesToCopy;
425
426            // Restore the buffer if lost
427            if (IsBufferLost())
428            {
429                secondaryBuffer.Restore();
430            }
431
432            // Clear the bufferSamples if in Paused
433            if (playbackState == PlaybackState.Paused)
434            {
435                samples.Clear();
436            }
437            else
438            {
439                // Read data from stream (Should this be inserted between the lock / unlock?)
440                samples.ByteBufferCount = bytesToCopy;
441                bytesRead = waveStream.Read(samples);
442
443                if (bytesRead == 0)
444                {
445                    samples.Clear();
446                    return 0;
447                }
448            }
449
450            // Lock a portion of the SecondaryBuffer (starting from 0 or 1/2 the buffer)
451            IntPtr wavBuffer1;
452            int nbSamples1;
453            IntPtr wavBuffer2;
454            int nbSamples2;
455            secondaryBuffer.Lock(nextSamplesWriteIndex, (uint)bytesRead,  // (uint)bytesToCopy,
456                                 out wavBuffer1, out nbSamples1,
457                                 out wavBuffer2, out nbSamples2,
458                                 DirectSoundBufferLockFlag.None);
459
460            // Copy back to the SecondaryBuffer
461            if (wavBuffer1 != IntPtr.Zero)
462            {
463                Marshal.Copy(samples.ByteBuffer, 0, wavBuffer1, nbSamples1);
464                if (wavBuffer2 != IntPtr.Zero)
465                {
466                    Marshal.Copy(samples.ByteBuffer, 0, wavBuffer1, nbSamples1);
467                }
468            }
469
470            // Unlock the SecondaryBuffer
471            secondaryBuffer.Unlock(wavBuffer1, nbSamples1, wavBuffer2, nbSamples2);
472
473            return bytesRead;
474        }
475
476
477        //----------------------------------------------------------------------------------------------
478        // Minimal Native DirectSound COM interop interfaces
479        //----------------------------------------------------------------------------------------------
480        #region Native DirectSound COM Interface
481
482        [StructLayout(LayoutKind.Sequential, Pack = 2)]
483        internal class BufferDescription
484        {
485            public int dwSize;
486            [MarshalAs(UnmanagedType.U4)]
487            public DirectSoundBufferCaps dwFlags;
488            public uint dwBufferBytes;
489            public int dwReserved;
490            public IntPtr lpwfxFormat;
491            public Guid guidAlgo;
492        }
493
494        [StructLayout(LayoutKind.Sequential, Pack = 2)]
495        internal class BufferCaps
496        {
497            public int dwSize;
498            public int dwFlags;
499            public int dwBufferBytes;
500            public int dwUnlockTransferRate;
501            public int dwPlayCpuOverhead;
502        }
503
504        internal enum DirectSoundCooperativeLevel : uint
505        {
506            DSSCL_NORMAL = 0x00000001,
507            DSSCL_PRIORITY = 0x00000002,
508            DSSCL_EXCLUSIVE = 0x00000003,
509            DSSCL_WRITEPRIMARY = 0x00000004
510        }
511
512        [FlagsAttribute]
513        internal enum DirectSoundPlayFlags : uint
514        {
515            DSBPLAY_LOOPING = 0x00000001,
516            DSBPLAY_LOCHARDWARE = 0x00000002,
517            DSBPLAY_LOCSOFTWARE = 0x00000004,
518            DSBPLAY_TERMINATEBY_TIME = 0x00000008,
519            DSBPLAY_TERMINATEBY_DISTANCE = 0x000000010,
520            DSBPLAY_TERMINATEBY_PRIORITY = 0x000000020
521        }
522
523        internal enum DirectSoundBufferLockFlag : uint
524        {
525            None = 0,
526            FromWriteCursor = 0x00000001,
527            EntireBuffer = 0x00000002
528        }
529
530        [FlagsAttribute]
531        internal enum DirectSoundBufferStatus : uint
532        {
533            DSBSTATUS_PLAYING = 0x00000001,
534            DSBSTATUS_BUFFERLOST = 0x00000002,
535            DSBSTATUS_LOOPING = 0x00000004,
536            DSBSTATUS_LOCHARDWARE = 0x00000008,
537            DSBSTATUS_LOCSOFTWARE = 0x00000010,
538            DSBSTATUS_TERMINATED = 0x00000020
539        }
540
541        [FlagsAttribute]
542        internal enum DirectSoundBufferCaps : uint
543        {
544            DSBCAPS_PRIMARYBUFFER = 0x00000001,
545            DSBCAPS_STATIC = 0x00000002,
546            DSBCAPS_LOCHARDWARE = 0x00000004,
547            DSBCAPS_LOCSOFTWARE = 0x00000008,
548            DSBCAPS_CTRL3D = 0x00000010,
549            DSBCAPS_CTRLFREQUENCY = 0x00000020,
550            DSBCAPS_CTRLPAN = 0x00000040,
551            DSBCAPS_CTRLVOLUME = 0x00000080,
552            DSBCAPS_CTRLPOSITIONNOTIFY = 0x00000100,
553            DSBCAPS_CTRLFX = 0x00000200,
554            DSBCAPS_STICKYFOCUS = 0x00004000,
555            DSBCAPS_GLOBALFOCUS = 0x00008000,
556            DSBCAPS_GETCURRENTPOSITION2 = 0x00010000,
557            DSBCAPS_MUTE3DATMAXDISTANCE = 0x00020000,
558            DSBCAPS_LOCDEFER = 0x00040000
559        }
560
561        [StructLayout(LayoutKind.Sequential, Pack = 2)]
562        internal struct DirectSoundBufferPositionNotify
563        {
564            public UInt32 dwOffset;
565            public IntPtr hEventNotify;
566        }
567
568        /// <summary>
569        /// IDirectSound interface
570        /// </summary>
571        [ComImport,
572         Guid("279AFA83-4981-11CE-A521-0020AF0BE560"),
573         InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
574         SuppressUnmanagedCodeSecurity]
575        internal interface IDirectSound
576        {
577            //STDMETHOD(CreateSoundBuffer)    (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE;
578            void CreateSoundBuffer([In] BufferDescription desc, [Out, MarshalAs(UnmanagedType.Interface)] out object dsDSoundBuffer, IntPtr pUnkOuter);
579            //STDMETHOD(GetCaps)              (THIS_ LPDSCAPS pDSCaps) PURE;
580            void GetCaps(IntPtr caps);
581            //STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE;
582            void DuplicateSoundBuffer([In, MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer bufferOriginal, [In, MarshalAs(UnmanagedType.Interface)] IDirectSoundBuffer bufferDuplicate);
583            //STDMETHOD(SetCooperativeLevel)  (THIS_ HWND hwnd, DWORD dwLevel) PURE;
584            void SetCooperativeLevel(IntPtr HWND, [In, MarshalAs(UnmanagedType.U4)] DirectSoundCooperativeLevel dwLevel);
585            //STDMETHOD(Compact)              (THIS) PURE;
586            void Compact();
587            //STDMETHOD(GetSpeakerConfig)     (THIS_ LPDWORD pdwSpeakerConfig) PURE;
588            void GetSpeakerConfig(IntPtr pdwSpeakerConfig);
589            //STDMETHOD(SetSpeakerConfig)     (THIS_ DWORD dwSpeakerConfig) PURE;
590            void SetSpeakerConfig(uint pdwSpeakerConfig);
591            //STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;
592            void Initialize([In, MarshalAs(UnmanagedType.LPStruct)] Guid guid);
593        }
594
595        /// <summary>
596        /// IDirectSoundBuffer interface
597        /// </summary>
598        [ComImport,
599         Guid("279AFA85-4981-11CE-A521-0020AF0BE560"),
600         InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
601         SuppressUnmanagedCodeSecurity]
602        internal interface IDirectSoundBuffer
603        {
604            //    STDMETHOD(GetCaps)              (THIS_ LPDSBCAPS pDSBufferCaps) PURE;
605            void GetCaps([MarshalAs(UnmanagedType.LPStruct)] BufferCaps pBufferCaps);
606            //    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE;
607            void GetCurrentPosition([Out] out uint currentPlayCursor, [Out] out uint currentWriteCursor);
608            //    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;
609            void GetFormat();
610            //    STDMETHOD(GetVolume)            (THIS_ LPLONG plVolume) PURE;
611            [return: MarshalAs(UnmanagedType.I4)]
612            int GetVolume();
613            //    STDMETHOD(GetPan)               (THIS_ LPLONG plPan) PURE;
614            void GetPan([Out] out uint pan);
615            //    STDMETHOD(GetFrequency)         (THIS_ LPDWORD pdwFrequency) PURE;
616            [return: MarshalAs(UnmanagedType.I4)]
617            int GetFrequency();
618            //    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;
619            [return: MarshalAs(UnmanagedType.U4)]
620            DirectSoundBufferStatus GetStatus();
621            //    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE;
622            void Initialize([In, MarshalAs(UnmanagedType.Interface)] IDirectSound directSound, [In] BufferDescription desc);
623            //    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,
624            //                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;
625            void Lock(int dwOffset, uint dwBytes, [Out] out IntPtr audioPtr1, [Out] out int audioBytes1, [Out] out IntPtr audioPtr2, [Out] out int audioBytes2, [MarshalAs(UnmanagedType.U4)] DirectSoundBufferLockFlag dwFlags);
626            //    STDMETHOD(Play)                 (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;
627            void Play(uint dwReserved1, uint dwPriority, [In, MarshalAs(UnmanagedType.U4)] DirectSoundPlayFlags dwFlags);
628            //    STDMETHOD(SetCurrentPosition)   (THIS_ DWORD dwNewPosition) PURE;
629            void SetCurrentPosition(uint dwNewPosition);
630            //    STDMETHOD(SetFormat)            (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE;
631            void SetFormat([In] WaveFormat pcfxFormat);
632            //    STDMETHOD(SetVolume)            (THIS_ LONG lVolume) PURE;
633            void SetVolume(int volume);
634            //    STDMETHOD(SetPan)               (THIS_ LONG lPan) PURE;
635            void SetPan(uint pan);
636            //    STDMETHOD(SetFrequency)         (THIS_ DWORD dwFrequency) PURE;
637            void SetFrequency(uint frequency);
638            //    STDMETHOD(Stop)                 (THIS) PURE;
639            void Stop();
640            //    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;
641            void Unlock(IntPtr pvAudioPtr1, int dwAudioBytes1, IntPtr pvAudioPtr2, int dwAudioBytes2);
642            //    STDMETHOD(Restore)              (THIS) PURE;
643            void Restore();
644        }
645
646        /// <summary>
647        /// IDirectSoundNotify interface
648        /// </summary>
649        [ComImport,
650         Guid("b0210783-89cd-11d0-af08-00a0c925cd16"),
651         InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
652         SuppressUnmanagedCodeSecurity]
653        internal interface IDirectSoundNotify
654        {
655            void SetNotificationPositions(UInt32 dwPositionNotifies, [In, MarshalAs(UnmanagedType.LPArray)] DirectSoundBufferPositionNotify[] pcPositionNotifies);
656        }
657
658        /// <summary>
659        /// Instanciate DirectSound from the DLL
660        /// </summary>
661        /// <param name="GUID">The GUID.</param>
662        /// <param name="directSound">The direct sound.</param>
663        /// <param name="pUnkOuter">The p unk outer.</param>
664        [DllImport("dsound.dll", EntryPoint = "DirectSoundCreate", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
665        static extern void DirectSoundCreate(IntPtr GUID, [Out, MarshalAs(UnmanagedType.Interface)] out IDirectSound directSound, IntPtr pUnkOuter);
666
667        /// <summary>
668        /// Gets the HANDLE of the desktop window.
669        /// </summary>
670        /// <returns>HANDLE of the Desktop window</returns>
671        [DllImport("user32.dll")]
672        private static extern IntPtr GetDesktopWindow();
673        #endregion
674    }
675}
Note: See TracBrowser for help on using the repository browser.