예제 #1
0
        private void PlaybackProc(object playbackStartedEventWaithandle)
        {
            try
            {
                int          bufferSize;
                int          frameSize;
                byte[]       buffer;
                int          eventWaitHandleIndex;
                WaitHandle[] eventWaitHandleArray;

                bufferSize = _audioClient.BufferSize;
                frameSize  = _outputFormat.Channels * _outputFormat.BytesPerSample;

                buffer = new byte[bufferSize * frameSize];

                eventWaitHandleIndex = WaitHandle.WaitTimeout;
                eventWaitHandleArray = new WaitHandle[] { _eventWaitHandle };

                //001

                /*if (!FeedBuffer(_renderClient, buffer, bufferSize, frameSize)) //todo: might cause a deadlock: play() is waiting on eventhandle but FeedBuffer got already called
                 * {
                 *      _playbackState = PlaybackState.Stopped;
                 *      if (playbackStartedEventWaithandle is EventWaitHandle)
                 *      {
                 *              ((EventWaitHandle)playbackStartedEventWaithandle).Set();
                 *              playbackStartedEventWaithandle = null;
                 *      }
                 * }
                 * else
                 * {*/
                _audioClient.Start();
                _playbackState = SoundOut.PlaybackState.Playing;

                if (playbackStartedEventWaithandle is EventWaitHandle)
                {
                    ((EventWaitHandle)playbackStartedEventWaithandle).Set();
                    playbackStartedEventWaithandle = null;
                }

                while (PlaybackState != PlaybackState.Stopped)
                {
                    if (_eventSync)                             //based on the "RenderSharedEventDriven"-Sample: http://msdn.microsoft.com/en-us/library/dd940520(v=vs.85).aspx
                    {
                        eventWaitHandleIndex = WaitHandle.WaitAny(eventWaitHandleArray, 3 * _latency, false);
                        //3 * latency = see msdn: recommended timeout
                        if (eventWaitHandleIndex == WaitHandle.WaitTimeout)
                        {
                            continue;
                        }
                    }
                    else                             //based on the "RenderSharedTimerDriven"-Sample: http://msdn.microsoft.com/en-us/library/dd940521(v=vs.85).aspx
                    {
                        Thread.Sleep(_latency / 8);
                    }

                    if (PlaybackState == PlaybackState.Playing)
                    {
                        int padding;
                        if (_eventSync && _shareMode == AudioClientShareMode.Exclusive)
                        {
                            padding = 0;
                        }
                        else
                        {
                            padding = _audioClient.GetCurrentPadding();
                        }

                        int framesReadyToFill = bufferSize - padding;
                        if (framesReadyToFill > 5 &&
                            !(_source is DmoResampler &&
                              ((DmoResampler)_source).OutputToInput(framesReadyToFill * frameSize) <= 0))                                           //avoid conversion errors
                        {
                            if (!FeedBuffer(_renderClient, buffer, framesReadyToFill, frameSize))
                            {
                                _playbackState = PlaybackState.Stopped;                                         //TODO: Fire Stopped-event here?
                            }
                        }
                    }
                }

                Thread.Sleep(_latency / 2);

                _audioClient.Stop();
                _audioClient.Reset();
                //}
            }
            finally
            {
                //CleanupResources();
                if (playbackStartedEventWaithandle is EventWaitHandle)
                {
                    ((EventWaitHandle)playbackStartedEventWaithandle).Set();
                }
                RaiseStopped();
            }
        }