AudioPlayerApp.AudioPlayer.PlayAsync C# (CSharp) Method

PlayAsync() private method

Internal method to play the sound.
private PlayAsync ( ) : void
return void
        private void PlayAsync()
        {
            int currentPlayCounter = 0;
            int nextBuffer = 0;

            try
            {
                while (true)
                {
                    // Check that this instanced is not disposed
                    while (!IsDisposed)
                    {
                        if (playEvent.WaitOne(WaitPrecision))
                            break;
                    }

                    if (IsDisposed)
                        break;

                    clock.Restart();
                    playPositionStart = nextPlayPosition;
                    playPosition = playPositionStart;
                    currentPlayCounter = playCounter;

                    // Get the decoded samples from the specified starting position.
                    var sampleIterator = audioDecoder.GetSamples(playPositionStart).GetEnumerator();

                    bool isFirstTime = true;

                    bool endOfSong = false;
                    crossfadeActive = false;

                    // Playing all the samples
                    while (true)
                    {
                        // If the player is stopped or disposed, then break of this loop
                        while (!IsDisposed && State != AudioPlayerState.Stopped)
                        {
                            if (playEvent.WaitOne(WaitPrecision))
                                break;
                        }

                        // If the player is stopped or disposed, then break of this loop
                        if (IsDisposed || State == AudioPlayerState.Stopped)
                        {
                            nextPlayPosition = TimeSpan.Zero;
                            break;
                        }

                        // If there was a change in the play position, restart the sample iterator.
                        if (currentPlayCounter != playCounter)
                            break;

                        // If ring buffer queued is full, wait for the end of a buffer.
                        while (sourceVoice.State.BuffersQueued == audioBuffersRing.Length && !IsDisposed && State != AudioPlayerState.Stopped)
                            bufferEndEvent.WaitOne(WaitPrecision);

                        // If the player is stopped or disposed, then break of this loop
                        if (IsDisposed || State == AudioPlayerState.Stopped)
                        {
                            nextPlayPosition = TimeSpan.Zero;
                            break;
                        }

                        // Check that there is a next sample
                        if (!sampleIterator.MoveNext())
                        {
                            endOfSong = true;
                            break;
                        }

                        // Retrieve a pointer to the sample data
                        var bufferPointer = sampleIterator.Current;

                        // If there was a change in the play position, restart the sample iterator.
                        if (currentPlayCounter != playCounter)
                            break;

                        // Check that our ring buffer has enough space to store the audio buffer.
                        if (bufferPointer.Size > memBuffers[nextBuffer].Size)
                        {
                            if (memBuffers[nextBuffer].Pointer != IntPtr.Zero)
                                Utilities.FreeMemory(memBuffers[nextBuffer].Pointer);

                            memBuffers[nextBuffer].Pointer = Utilities.AllocateMemory(bufferPointer.Size);
                            memBuffers[nextBuffer].Size = bufferPointer.Size;
                        }

                        // Copy the memory from MediaFoundation AudioDecoder to the buffer that is going to be played.
                        Utilities.CopyMemory(memBuffers[nextBuffer].Pointer, bufferPointer.Pointer, bufferPointer.Size);

                        // Set the pointer to the data.
                        audioBuffersRing[nextBuffer].AudioDataPointer = memBuffers[nextBuffer].Pointer;
                        audioBuffersRing[nextBuffer].AudioBytes = bufferPointer.Size;

                        // If this is a first play, restart the clock and notify play method.
                        if (isFirstTime)
                        {
                            clock.Restart();
                            isFirstTime = false;

                            waitForPlayToOutput.Set();
                        }

                        // Update the current position used for sync
                        playPosition = new TimeSpan(playPositionStart.Ticks + clock.Elapsed.Ticks);

                        // Submit the audio buffer to xaudio2
                        sourceVoice.SubmitSourceBuffer(audioBuffersRing[nextBuffer], null);

                        // Go to next entry in the ring audio buffer
                        nextBuffer = ++nextBuffer%audioBuffersRing.Length;

                        var crossFadePosition = CrossFadePosition;
                        if (crossFadePosition.HasValue)
                        {
                            // Fade down volume?
                        }
                    }

                    // If the song is not looping (by default), then stop the audio player.
                    if (endOfSong && !IsRepeating && State == AudioPlayerState.Playing)
                    {
                        if (AutoCloseAtEndOfSong)
                        {
                            Stop();
                            Dispose();
                            State = AudioPlayerState.Closed;
                        }
                        else
                            Stop();
                    }
                }
            } finally
            {
                DisposePlayer();
            }
        }