Пример #1
0
        //private long m_CircularBufferFlushTolerance;
        //private int m_CircularBufferPreviousBytesAvailableForWriting;



        private bool circularBufferRefreshThreadMethod()
        {
            //m_CircularBufferRefreshThreadIsAlive = true;

            //float previousFastPlayFactor = m_FastPlayFactor;

            //long predictedByteIncrement = -1;


            //int circularBufferTotalBytesPlayed = -1;
            //int previousCircularBufferPlayPosition = -1;


            Stopwatch transferBytesStopWatch = new Stopwatch();

            transferBytesStopWatch.Stop();


            int totalWriteSkips = 0;

            uint adjustedFastPlaySampleRate =
                (uint)Math.Round(m_CurrentAudioPCMFormat.SampleRate * m_FastPlayFactor);

            long pcmDataTotalPlayableFromStream            = m_PlaybackEndPositionInCurrentAudioStream - m_PlaybackStartPositionInCurrentAudioStream;
            long pcmDataTotalPlayableFromStream_DurationMS =
                (
                    NotNormalPlayFactor()
                    ?
                    AudioLibPCMFormat.ConvertBytesToTime(
                        pcmDataTotalPlayableFromStream,
                        adjustedFastPlaySampleRate,
                        m_CurrentAudioPCMFormat.BlockAlign
#if DEBUG
                        , true
#endif
                        )
                    :
                    m_CurrentAudioPCMFormat.ConvertBytesToTime(pcmDataTotalPlayableFromStream)
                )
                / AudioLibPCMFormat.TIME_UNIT;

            int slowLoop = 0;

            int sleepTime = REFRESH_INTERVAL_MS;

            //bool endOfAudioStream = false;
            while (true)
            {
#if USE_SHARPDX
                DebugFix.Assert(
                    m_CircularBuffer.Status == (int)BufferStatus.BufferLost ||
                    m_CircularBuffer.Status == (int)BufferStatus.Hardware ||
                    m_CircularBuffer.Status == (int)BufferStatus.Looping ||
                    m_CircularBuffer.Status == (int)BufferStatus.None ||
                    m_CircularBuffer.Status == (int)BufferStatus.Playing ||
                    m_CircularBuffer.Status == (int)BufferStatus.Software ||
                    m_CircularBuffer.Status == (int)BufferStatus.Terminated ||
                    m_CircularBuffer.Status == 5    //?!
                    );

                if (m_CircularBuffer.Status == (int)BufferStatus.BufferLost)
                {
                    m_CircularBuffer.Restore();
                }
#else
                if (m_CircularBuffer.Status.BufferLost)
                {
                    m_CircularBuffer.Restore();
                }
#endif

#if USE_SHARPDX
                if (m_CircularBuffer.Status == (int)BufferStatus.Terminated ||
                    (m_CircularBuffer.Status != 5 && //?!
                     m_CircularBuffer.Status != (int)BufferStatus.Playing &&
                     m_CircularBuffer.Status != (int)BufferStatus.Looping)
                    )
                {
                    return(false);
                }
#else
                if (m_CircularBuffer.Status.Terminated ||
                    (!m_CircularBuffer.Status.Playing &&
                     !m_CircularBuffer.Status.Looping)
                    )
                {
                    return(false);
                }
#endif

                Thread.Sleep(sleepTime);
                sleepTime = REFRESH_INTERVAL_MS; // reset after each loop


                //                if (predictedByteIncrement < 0
                //                    || true //m_FastPlayFactor != previousFastPlayFactor
                //                    )
                //                {
                //                    //previousFastPlayFactor = m_FastPlayFactor;


                //                    int fastPlaySamplesPerSecond = (int)Math.Round(m_CurrentAudioPCMFormat.SampleRate * m_FastPlayFactor);
                //#if DEBUG
                //                    DebugFix.Assert(m_CurrentAudioPCMFormat.SampleRate == m_CircularBuffer.Format.SamplesPerSecond);

                //                    if (
                //#if USE_SOUNDTOUCH
                //!UseSoundTouch &&
                //#endif //USE_SOUNDTOUCH
                //#if USE_SHARPDX
                // m_CircularBuffer.Capabilities.ControlFrequency
                //#else
                // m_CircularBuffer.Caps.ControlFrequency
                //#endif
                //)
                //                    {
                //                        DebugFix.Assert(m_CircularBuffer.Frequency == fastPlaySamplesPerSecond);

                //                    }
                //#endif //DEBUG
                //                    int byteRate = fastPlaySamplesPerSecond * m_CurrentAudioPCMFormat.BlockAlign; // (m_CurrentAudioPCMFormat.BitDepth / 8) * m_CurrentAudioPCMFormat.NumberOfChannels;


                //                    predictedByteIncrement = (long)(byteRate * (REFRESH_INTERVAL_MS + 15) / 1000.0);
                //                    predictedByteIncrement -= predictedByteIncrement % m_CurrentAudioPCMFormat.BlockAlign;
                //                }

#if USE_SHARPDX
                int circularBufferPlayPosition;
                int circularBufferWritePosition;
                m_CircularBuffer.GetCurrentPosition(out circularBufferPlayPosition, out circularBufferWritePosition);
#else
                int circularBufferPlayPosition = m_CircularBuffer.PlayPosition;
#endif

                int circularBufferLength = m_CircularBuffer.
#if USE_SHARPDX
                                           Capabilities
#else
                                           Caps
#endif
                                           .BufferBytes
                ;
                //if (circularBufferTotalBytesPlayed < 0)
                //{
                //    circularBufferTotalBytesPlayed = circularBufferPlayPosition;
                //}
                //else
                //{
                //    if (circularBufferPlayPosition >= previousCircularBufferPlayPosition)
                //    {
                //        circularBufferTotalBytesPlayed += circularBufferPlayPosition - previousCircularBufferPlayPosition;
                //    }
                //    else
                //    {
                //        circularBufferTotalBytesPlayed += (circularBufferLength - previousCircularBufferPlayPosition) + circularBufferPlayPosition;
                //    }
                //}

                //previousCircularBufferPlayPosition = circularBufferPlayPosition;


                //                int totalBytesPlayed_AdjustedPlaybackRate = circularBufferTotalBytesPlayed;

                //#if USE_SOUNDTOUCH
                //                if (UseSoundTouch && NotNormalPlayFactor())
                //                {
                //                    //m_CurrentAudioPCMFormat
                //                    totalBytesPlayed_AdjustedPlaybackRate = (int)Math.Round(totalBytesPlayed_AdjustedPlaybackRate * m_FastPlayFactor);
                //                    totalBytesPlayed_AdjustedPlaybackRate -= totalBytesPlayed_AdjustedPlaybackRate % m_CurrentAudioPCMFormat.BlockAlign;
                //                }
                //#endif //USE_SOUNDTOUCH



                int circularBufferBytesAvailableForWriting = (circularBufferPlayPosition == m_CircularBufferWritePosition ? 0
                                        : (circularBufferPlayPosition < m_CircularBufferWritePosition
                                  ? circularBufferPlayPosition + (circularBufferLength - m_CircularBufferWritePosition)
                                  : circularBufferPlayPosition - m_CircularBufferWritePosition));

                //int circularBufferBytesAvailableForPlaying = circularBufferLength - circularBufferBytesAvailableForWriting;



                //realTimePlaybackPosition -= realTimePlaybackPosition % m_CurrentAudioPCMFormat.BlockAlign;

                //Console.WriteLine(String.Format("bytesAvailableForWriting: [{0} / {1}]", bytesAvailableForWriting, m_CircularBuffer.Caps.BufferBytes));

                //Console.WriteLine("dataAvailableFromStream: " + dataAvailableFromStream);

                //                int circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate = circularBufferBytesAvailableForPlaying;

                //#if USE_SOUNDTOUCH
                //                if (UseSoundTouch && NotNormalPlayFactor())
                //                {
                //                    circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate = (int)Math.Round(circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate * m_FastPlayFactor);
                //                    circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate -= circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate % m_CurrentAudioPCMFormat.BlockAlign;
                //                }
                //#endif //USE_SOUNDTOUCH

                long totalPlayedMS    = m_PlaybackStopWatch.ElapsedMilliseconds;
                long totalPlayedBytes =
                    (
                        NotNormalPlayFactor()
                    ?
                        AudioLibPCMFormat.ConvertTimeToBytes(
                            totalPlayedMS * AudioLibPCMFormat.TIME_UNIT,
                            (uint)adjustedFastPlaySampleRate,
                            (ushort)m_CurrentAudioPCMFormat.BlockAlign
#if DEBUG
                            , true
#endif
                            )
                    :
                        m_CurrentAudioPCMFormat.ConvertTimeToBytes(totalPlayedMS * AudioLibPCMFormat.TIME_UNIT)
                    );


                m_CurrentBytePosition = m_PlaybackStartPositionInCurrentAudioStream + totalPlayedBytes;

                //safeguard
                if (m_CurrentBytePosition < m_PlaybackStartPositionInCurrentAudioStream)
                {
                    m_CurrentBytePosition = m_PlaybackStartPositionInCurrentAudioStream;
                }
                else if (m_CurrentBytePosition > m_PlaybackEndPositionInCurrentAudioStream)
                {
                    m_CurrentBytePosition = m_PlaybackEndPositionInCurrentAudioStream;
                }

                //#if DEBUG
                //                DebugFix.Assert(m_CurrentBytePosition >= m_PlaybackStartPositionInCurrentAudioStream);
                //                DebugFix.Assert(m_CurrentBytePosition <= m_PlaybackEndPositionInCurrentAudioStream);
                //#endif // DEBUG



                //long remainingBytesToPlay = pcmDataTotalPlayableFromStream - totalBytesPlayed_AdjustedPlaybackRate;

                //long realTimePlaybackPosition = Math.Max(m_PlaybackStartPositionInCurrentAudioStream,
                //    m_CurrentAudioStream.Position - Math.Min(
                //    circularBufferBytesAvailableForPlaying_AdjustedPlaybackRate, remainingBytesToPlay));

                //realTimePlaybackPosition = Math.Min(realTimePlaybackPosition,
                //    m_PlaybackStartPositionInCurrentAudioStream + totalBytesPlayed_AdjustedPlaybackRate);

                //if (m_CurrentBytePosition == m_PlaybackStartPositionInCurrentAudioStream)
                //{
                //    //Console.WriteLine(string.Format("m_CurrentBytePosition ASSIGNED: realTimePlaybackPosition [{0}]", realTimePlaybackPosition));

                //    m_CurrentBytePosition += totalBytesPlayed_AdjustedPlaybackRate;
                //}
                ////else if (realTimePlaybackPosition < m_CurrentBytePosition)
                ////{
                ////    Console.WriteLine(string.Format("realTimePlaybackPosition [{0}] < m_CurrentBytePosition [{1}]", realTimePlaybackPosition, m_CurrentBytePosition));

                ////    m_CurrentBytePosition = Math.Min(m_PlaybackEndPositionInCurrentAudioStream, m_CurrentBytePosition + predictedByteIncrement);
                ////}
                ////else if (realTimePlaybackPosition > m_CurrentBytePosition + predictedByteIncrement)
                ////{
                ////    Console.WriteLine(string.Format("realTimePlaybackPosition [{0}] > m_CurrentBytePosition [{1}] + m_PredictedByteIncrement: [{2}] (diff: [{3}])",
                ////        realTimePlaybackPosition, m_CurrentBytePosition, predictedByteIncrement, realTimePlaybackPosition - m_CurrentBytePosition));

                ////    m_CurrentBytePosition = Math.Min(m_PlaybackEndPositionInCurrentAudioStream, m_CurrentBytePosition + predictedByteIncrement);
                ////}
                //else
                //{
                //    //Console.WriteLine(string.Format("m_CurrentBytePosition OK: realTimePlaybackPosition [{0}]", realTimePlaybackPosition));

                //    m_CurrentBytePosition = m_PlaybackStartPositionInCurrentAudioStream + totalBytesPlayed_AdjustedPlaybackRate;
                //}


                PcmDataBufferAvailableHandler del = PcmDataBufferAvailable;
                if (del != null)
                {
                    int min = Math.Min(m_PcmDataBufferLength,
#if FETCH_PCM_FROM_CIRCULAR_BUFFER
                                       circularBufferBytesAvailableForPlaying
#else
                                           (int)(m_PlaybackEndPositionInCurrentAudioStream - m_CurrentBytePosition)
#endif // FETCH_PCM_FROM_CIRCULAR_BUFFER
                                       );

#if DEBUG
                    DebugFix.Assert(min <= m_PcmDataBufferLength);
                    DebugFix.Assert(min <= m_PcmDataBuffer.Length);
#endif //DEBUG
                    if (min >= m_CurrentAudioPCMFormat.BlockAlign)
                    {
#if FETCH_PCM_FROM_CIRCULAR_BUFFER
#if USE_SHARPDX
                        if (SharpDX_IntermediaryTransferBuffer != null)
                        {
                            Array.Copy(SharpDX_IntermediaryTransferBuffer, m_PcmDataBuffer, Math.Min(m_PcmDataBuffer.Length, SharpDX_IntermediaryTransferBuffer.Length));
                        }
#else
                        byte[] array = (byte[])m_CircularBuffer.Read(
                            circularBufferPlayPosition, typeof(byte), LockFlag.None, min);
                        //Array.Copy(array, m_PcmDataBuffer, min);
                        Buffer.BlockCopy(array, 0,
                                         m_PcmDataBuffer, 0,
                                         min);
#endif
#else // !FETCH_PCM_FROM_CIRCULAR_BUFFER
                        long pos = m_CurrentAudioStream.Position;

                        m_CurrentAudioStream.Position = m_CurrentBytePosition;

                        m_CurrentAudioStream.Read(m_PcmDataBuffer, 0, min);

                        m_CurrentAudioStream.Position = pos;
#endif


                        m_PcmDataBufferAvailableEventArgs.PcmDataBuffer       = m_PcmDataBuffer;
                        m_PcmDataBufferAvailableEventArgs.PcmDataBufferLength = min;
                        del(this, m_PcmDataBufferAvailableEventArgs);
                    }
                }

                //var del_ = PcmDataBufferAvailable;
                //if (del_ != null
                //&& m_PcmDataBuffer.Length <= circularBufferBytesAvailableForPlaying)
                //{
                //#if USE_SHARPDX
                //if (SharpDX_IntermediaryTransferBuffer != null)
                //{
                //Array.Copy(SharpDX_IntermediaryTransferBuffer, m_PcmDataBuffer, Math.Min(m_PcmDataBuffer.Length, SharpDX_IntermediaryTransferBuffer.Length));
                //m_PcmDataBufferAvailableEventArgs.PcmDataBuffer = m_PcmDataBuffer;
                //PcmDataBufferAvailable(this, m_PcmDataBufferAvailableEventArgs);
                //}
                //#else
                //Array array = m_CircularBuffer.Read(circularBufferPlayPosition, typeof(byte), LockFlag.None, m_PcmDataBuffer.Length);
                //Array.Copy(array, m_PcmDataBuffer, m_PcmDataBuffer.Length);
                //m_PcmDataBufferAvailableEventArgs.PcmDataBuffer = m_PcmDataBuffer;
                //del_(this, m_PcmDataBufferAvailableEventArgs);
                //#endif
                //}

                long pcmDataRemainingPlayableFromStream = m_PlaybackEndPositionInCurrentAudioStream - m_CurrentAudioStream.Position;
                //long pcmDataAlreadyReadFromStream = pcmDataTotalPlayableFromStream - pcmDataAvailableFromStream;

                if (circularBufferBytesAvailableForWriting <= 0)
                {
                    if (pcmDataRemainingPlayableFromStream > 0)
                    {
                        //Console.WriteLine("circularBufferBytesAvailableForWriting <= 0, pcmDataAvailableFromStream > 0 ... continue...");
                        continue;
                    }
                    else
                    {
                        Console.WriteLine("circularBufferBytesAvailableForWriting <= 0, pcmDataAvailableFromStream <= 0 ... BREAK...");
                        break;
                    }
                }

                //m_CircularBufferPreviousBytesAvailableForWriting = circularBufferBytesAvailableForWriting;

                // We have fed all of the available bytes from the audio stream to the circular secondary buffer.
                // Now we have to wait until the playback ends.
                if (pcmDataRemainingPlayableFromStream <= 0)
                {
                    if ((m_PlaybackStopWatch.ElapsedMilliseconds + REFRESH_INTERVAL_MS) >= pcmDataTotalPlayableFromStream_DurationMS)
                    {
                        m_CircularBuffer.Stop();
                        return(true);
                    }
                    else
                    {
                        int newInterval = (int)Math.Round(REFRESH_INTERVAL_MS / 2.0);
                        sleepTime = newInterval;
                        continue;
                    }

                    //if (remainingBytesToPlay > predictedByteIncrement)
                    //{
                    //    Console.WriteLine(string.Format("remainingBytesToPlay [{0}] [{1}] [{2}] [{3}]",
                    //        pcmDataTotalPlayableFromStream, totalBytesPlayed_AdjustedPlaybackRate, remainingBytesToPlay, predictedByteIncrement));
                    //    continue;
                    //}
                    //else
                    //{
                    //    m_CircularBuffer.Stop();

                    //    //Console.WriteLine("Time to break, all bytes gone.");
                    //    //break;

                    //    return true;
                    //}


                    //if (m_CircularBufferFlushTolerance < 0)
                    //{
                    //    m_CircularBufferFlushTolerance = m_CurrentAudioPCMFormat.ConvertTimeToBytes(REFRESH_INTERVAL_MS*1.5);
                    //}

                    //Console.WriteLine(string.Format("pcmDataTotalPlayableFromStream [{0}]", pcmDataTotalPlayableFromStream));

                    //Console.WriteLine(String.Format("pcmDataAvailableFromStream <= 0 // circularBufferBytesAvailableForWriting [{0}], m_CircularBufferFlushTolerance [{1}], m_CircularBuffer.Caps.BufferBytes [{2}], m_CircularBufferPreviousBytesAvailableForWriting [{3}]",
                    //    circularBufferBytesAvailableForWriting, m_CircularBufferFlushTolerance, m_CircularBuffer.Caps.BufferBytes, m_CircularBufferPreviousBytesAvailableForWriting));

                    //if ((circularBufferBytesAvailableForWriting + m_CircularBufferFlushTolerance) >= m_CircularBuffer.Caps.BufferBytes
                    //    || m_CircularBufferPreviousBytesAvailableForWriting > circularBufferBytesAvailableForWriting)
                    //{
                    //    m_CircularBuffer.Stop(); // the earlier the better ?

                    //    Console.WriteLine("Forcing closing-up.");

                    //    circularBufferBytesAvailableForWriting = 0; // will enter the IF test below
                    //}
                }
                else
                {
                    // 2 thirds minimum of the circular buffer must be available,
                    //otherwise skip until next sleep loop
                    double ratio = 2 / 3.0;

#if USE_SOUNDTOUCH
                    if (UseSoundTouch && NotNormalPlayFactor())
                    {
                        ratio /= m_FastPlayFactor;
                    }
#endif // USE_SOUNDTOUCH

                    bool skip = circularBufferBytesAvailableForWriting <
                                (int)Math.Round(circularBufferLength * ratio);

                    if (false && skip)
                    {
                        totalWriteSkips++;
                    }
                    else
                    {
                        //                        int circularBufferBytesAvailableForWriting_AdjustedPlaybackRate =
                        //                            circularBufferBytesAvailableForWriting;

                        //#if USE_SOUNDTOUCH
                        //                        if (UseSoundTouch && NotNormalPlayFactor())
                        //                        {
                        //                            int bytesPerSample = (int)Math.Round(m_CurrentAudioPCMFormat.BitDepth / 8.0);
                        //                            int bytesPerFrame = bytesPerSample * m_CurrentAudioPCMFormat.NumberOfChannels;
                        //                            DebugFix.Assert(m_CurrentAudioPCMFormat.BlockAlign == bytesPerFrame);



                        //                            circularBufferBytesAvailableForWriting_AdjustedPlaybackRate =
                        //                                (int)
                        //                                Math.Round(circularBufferBytesAvailableForWriting_AdjustedPlaybackRate
                        //                                * m_FastPlayFactor
                        //                                * m_CurrentAudioPCMFormat.NumberOfChannels);

                        //                            circularBufferBytesAvailableForWriting_AdjustedPlaybackRate -=
                        //                                circularBufferBytesAvailableForWriting_AdjustedPlaybackRate %
                        //                                m_CurrentAudioPCMFormat.BlockAlign;
                        //                        }
                        //#endif //USE_SOUNDTOUCH


                        //Console.WriteLine("totalWriteSkips: " + totalWriteSkips + " ms: " + totalWriteSkips*REFRESH_INTERVAL_MS);
                        totalWriteSkips = 0;

#if NET4
                        transferBytesStopWatch.Restart();
#else
                        transferBytesStopWatch.Stop();
                        transferBytesStopWatch.Reset();
                        transferBytesStopWatch.Start();
#endif //NET4

                        int bytesWrittenToCirularBuffer =
                            transferBytesFromWavStreamToCircularBuffer(circularBufferBytesAvailableForWriting);

                        long timeMS = transferBytesStopWatch.ElapsedMilliseconds;
                        transferBytesStopWatch.Stop();

                        //Console.WriteLine("transferBytesStopWatch: " + timeMS);

                        sleepTime = Math.Max(10, REFRESH_INTERVAL_MS - (int)timeMS);
#if USE_SOUNDTOUCH
                        if (UseSoundTouch && NotNormalPlayFactor())
                        {
                            if (timeMS >= REFRESH_INTERVAL_MS)
                            {
                                slowLoop++;
                            }
                            if (slowLoop > 2)
                            {
                                slowLoop = 0;
                                Console.WriteLine("SOUNDTOUCH Enable SettingId.UseQuickseek");
                                m_SoundTouch.SetSetting(SettingId.UseQuickseek, 1);
                            }
                        }
#endif //USE_SOUNDTOUCH

                        //#if USE_SOUNDTOUCH
                        //                        if (UseSoundTouch && NotNormalPlayFactor())
                        //                        {
                        //                            int newInterval = (int)Math.Round(REFRESH_INTERVAL_MS / m_FastPlayFactor);
                        //                            //sleepTime = newInterval;
                        //                        }
                        //#endif // USE_SOUNDTOUCH
                    }
                }
            } // WHILE LOOP

            return(true);

            //CurrentState = State.Stopped;
            //AudioPlaybackFinishHandler delFinished = AudioPlaybackFinished;
            //if (delFinished != null && !mPreviewTimer.Enabled)
            //    delFinished(this, new AudioPlaybackFinishEventArgs());

            //if (!m_AllowBackToBackPlayback)
            //{
            //    AudioPlaybackFinishHandler delFinished = AudioPlaybackFinished;
            //    if (delFinished != null && mEventsEnabled)
            //        delFinished(this, new AudioPlaybackFinishEventArgs());
            //}
            //else
            //{
            //    m_FinishedPlayingCurrentStream = true;
            //}
        }