コード例 #1
0
ファイル: DirectSoundOut.cs プロジェクト: aljordan/NAJAudio
        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);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Processes the samples in a separate thread.
        /// </summary>
        private void PlaybackThreadFunc()
        {
            // Used to determine if playback is halted
            bool lPlaybackHalted = false;

            Exception exception = null;

            // Incase the thread is killed
            try
            {
                InitializeDirectSound();
                int lResult = 1;

                if (PlaybackState == PlaybackState.Stopped)
                {
                    secondaryBuffer.SetCurrentPosition(0);
                    nextSamplesWriteIndex = 0;
                    lResult = Feed(samplesTotalSize);
                }

                // Incase the previous Feed method returns 0
                if (lResult > 0)
                {
                    lock (m_LockObject)
                    {
                        playbackState = PlaybackState.Playing;
                    }

                    secondaryBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING);

                    WaitHandle[] waitHandles = new WaitHandle[] { frameEventWaitHandle1, frameEventWaitHandle2, endEventWaitHandle };

                    bool lContinuePlayback = true;
                    while (PlaybackState != PlaybackState.Stopped && lContinuePlayback)
                    {
                        // Wait for signals on frameEventWaitHandle1 (Position 0), frameEventWaitHandle2 (Position 1/2)
                        int indexHandle = WaitHandle.WaitAny(waitHandles, 3 * desiredLatency, false);

                        // TimeOut is ok
                        if (indexHandle != WaitHandle.WaitTimeout)
                        {
                            // Buffer is Stopped
                            if (indexHandle == 2)
                            {
                                // (Gee) - Not sure whether to stop playback in this case or not!
                                StopPlayback();
                                lPlaybackHalted   = true;
                                lContinuePlayback = false;
                            }
                            else
                            {
                                indexHandle           = (indexHandle == 0) ? 1 : 0;
                                nextSamplesWriteIndex = indexHandle * samplesFrameSize;

                                // Only carry on playing if we can!
                                if (Feed(samplesFrameSize) == 0)
                                {
                                    StopPlayback();
                                    lPlaybackHalted   = true;
                                    lContinuePlayback = false;
                                }
                            }
                        }
                        else
                        {
                            // Timed out!
                            StopPlayback();
                            lPlaybackHalted   = true;
                            lContinuePlayback = false;
                            // report this as an error in the Playback Stopped
                            // seems to happen when device is unplugged
                            throw new Exception("DirectSound buffer timeout");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Do nothing (except report error)
                Debug.WriteLine(e.ToString());
                exception = e;
            }
            finally
            {
                if (!lPlaybackHalted)
                {
                    StopPlayback();
                }

                lock (m_LockObject)
                {
                    playbackState = PlaybackState.Stopped;
                }

                // Fire playback stopped event
                RaisePlaybackStopped(exception);
            }
        }
コード例 #3
0
ファイル: DirectSoundOut.cs プロジェクト: hainam2101/karaoke
        /// <summary>
        /// Processes the samples in a separate thread.
        /// </summary>
        private void processSamples()
        {
            // Used to determine if playback is halted
            bool lPlaybackHalted = false;

            // Incase the thread is killed
            try
            {
                InitialiseDirectSound();
                int lResult = 1;

                if (PlaybackState == PlaybackState.Stopped)
                {
                    secondaryBuffer.SetCurrentPosition(0);
                    nextSamplesWriteIndex = 0;
                    lResult = Feed(samplesTotalSize);
                }

                // Incase the previous Feed method returns 0
                if (lResult > 0)
                {
                    lock (m_LockObject)
                    {
                        playbackState = PlaybackState.Playing;
                    }

                    secondaryBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING);

                    WaitHandle[] waitHandles = new WaitHandle[] { frameEventWaitHandle1, frameEventWaitHandle2, endEventWaitHandle };

                    bool lContinuePlayback = true;
                    while (PlaybackState != PlaybackState.Stopped && lContinuePlayback)
                    {
                        // Wait for signals on frameEventWaitHandle1 (Position 0), frameEventWaitHandle2 (Position 1/2)
                        int indexHandle = WaitHandle.WaitAny(waitHandles, 3 * desiredLatency, false);

                        // TimeOut is ok
                        if (indexHandle != WaitHandle.WaitTimeout)
                        {
                            // Buffer is Stopped
                            if (indexHandle == 2)
                            {
                                // (Gee) - Not sure whether to stop playback in this case or not!
                                StopPlayback();
                                lPlaybackHalted   = true;
                                lContinuePlayback = false;
                            }
                            else
                            {
                                indexHandle           = (indexHandle == 0) ? 1 : 0;
                                nextSamplesWriteIndex = indexHandle * samplesFrameSize;

                                // Only carry on playing if we can!
                                if (Feed(samplesFrameSize) == 0)
                                {
                                    StopPlayback();
                                    lPlaybackHalted   = true;
                                    lContinuePlayback = false;
                                }
                            }
                        }
                        else
                        {
                            // Timed out!
                            StopPlayback();
                            lPlaybackHalted   = true;
                            lContinuePlayback = false;
                        }
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing!
            }
            finally
            {
                if (!lPlaybackHalted)
                {
                    StopPlayback();
                }

                lock (m_LockObject)
                {
                    playbackState = PlaybackState.Stopped;
                }

                // Fire playback stopped event
                if (PlaybackStopped != null)
                {
                    PlaybackStopped(this, EventArgs.Empty);
                }
            }
        }
コード例 #4
0
        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);
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Processes the samples in a separate thread.
        /// </summary>
        private void PlaybackThreadFunc()
        {
            // Used to determine if playback is halted
            bool lPlaybackHalted    = false;
            bool firstBufferStarted = false;

            bytesPlayed = 0;

            Exception exception = null;

            // Incase the thread is killed
            try
            {
                InitializeDirectSound();
                int lResult = 1;

                if (PlaybackState == PlaybackState.Stopped)
                {
                    secondaryBuffer.SetCurrentPosition(0);
                    nextSamplesWriteIndex = 0;
                    lResult = Feed(samplesTotalSize);
                }

                // Incase the previous Feed method returns 0
                if (lResult > 0)
                {
                    lock (m_LockObject)
                    {
                        playbackState = PlaybackState.Playing;
                    }

                    secondaryBuffer.Play(0, 0, DirectSoundPlayFlags.DSBPLAY_LOOPING);

                    var waitHandles = new WaitHandle[] { frameEventWaitHandle1, frameEventWaitHandle2, endEventWaitHandle };

                    bool lContinuePlayback = true;
                    while (PlaybackState != PlaybackState.Stopped && lContinuePlayback)
                    {
                        // Wait for signals on frameEventWaitHandle1 (Position 0), frameEventWaitHandle2 (Position 1/2)
                        int indexHandle = WaitHandle.WaitAny(waitHandles, 3 * desiredLatency, false);

                        // TimeOut is ok
                        if (indexHandle != WaitHandle.WaitTimeout)
                        {
                            // Buffer is Stopped
                            if (indexHandle == 2)
                            {
                                // (Gee) - Not sure whether to stop playback in this case or not!
                                StopPlayback();
                                lPlaybackHalted   = true;
                                lContinuePlayback = false;
                            }
                            else
                            {
                                if (indexHandle == 0)
                                {
                                    // we're at the beginning of the buffer...
                                    if (firstBufferStarted)
                                    {
                                        // because this notification is based on the *playback" cursor, this should be reasonably accurate
                                        bytesPlayed += samplesFrameSize * 2;
                                    }
                                }
                                else
                                {
                                    firstBufferStarted = true;
                                }

                                indexHandle           = (indexHandle == 0) ? 1 : 0;
                                nextSamplesWriteIndex = indexHandle * samplesFrameSize;

                                // Only carry on playing if we can!
                                if (Feed(samplesFrameSize) == 0)
                                {
                                    StopPlayback();
                                    lPlaybackHalted   = true;
                                    lContinuePlayback = false;
                                }
                            }
                        }
                        else
                        {
                            // Timed out!
                            StopPlayback();
                            lPlaybackHalted   = true;
                            lContinuePlayback = false;
                            // report this as an error in the Playback Stopped
                            // seems to happen when device is unplugged
                            throw new Exception("DirectSound buffer timeout");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Do nothing (except report error)
                NAudioLogger.Instance.LogError(e.Message);
                exception = e;
            }
            finally
            {
                if (!lPlaybackHalted)
                {
                    try
                    {
                        StopPlayback();
                    }
                    catch (Exception e)
                    {
                        NAudioLogger.Instance.LogError(e.Message);
                        // don't overwrite the original reason we exited the playback loop
                        if (exception == null)
                        {
                            exception = e;
                        }
                    }
                }

                lock (m_LockObject)
                {
                    playbackState = PlaybackState.Stopped;
                }

                bytesPlayed = 0;

                // Fire playback stopped event
                RaisePlaybackStopped(exception);
            }
        }