Ejemplo n.º 1
0
        /// <summary>
        /// Runs the timer cycle.
        /// </summary>
        /// <param name="state">The state.</param>
        private void RunTimerCycle(object state)
        {
            // Skip running this cycle if we are already in the middle of one
            if (IsCycleDone.IsInProgress)
            {
                return;
            }

            try
            {
                // Start a cycle by signaling it
                IsCycleDone.Begin();

                // Call the configured timer callback
                TimerCallback();
            }
            finally
            {
                if (HasRequestedStop == false)
                {
                    // Finalize the cycle
                    IsCycleDone.Complete();
                }
                else
                {
                    // Prevent a new cycle from being queued
                    ThreadingTimer?.Change(Timeout.Infinite, Timeout.Infinite);
                    FormsTimer?.Stop();
                    DispatcherTimer?.Stop();

                    // Handle the dispose process.
                    ThreadingTimer?.Dispose();
                    FormsTimer?.Dispose();

                    // Remove references
                    ThreadingTimer  = null;
                    FormsTimer      = null;
                    DispatcherTimer = null;

                    // Complete the cycle and dispose of it
                    IsCycleDone.Complete();
                    IsCycleDone.Dispose();
                }
            }
        }
        /// <summary>
        /// Implementation using the ThreadPool with a wait event.
        /// </summary>
        private void DelayThreadPool()
        {
            lock (SyncRoot)
            {
                if (DelayEvent == null)
                {
                    DelayEvent = WaitEventFactory.Create(isCompleted: true, useSlim: true);
                }
            }

            DelayEvent.Begin();
            ThreadPool.QueueUserWorkItem(s =>
            {
                DelaySleep();
                DelayEvent.Complete();
            });

            DelayEvent.Wait();
        }
Ejemplo n.º 3
0
 static void Callback(IWaitEvent waitEvent)
 {
     try
     {
         waitEvent.Complete();
         waitEvent.Begin();
     }
     catch
     {
         // ignore
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Runs the timer cycle.
        /// </summary>
        /// <param name="state">The state.</param>
        private void RunTimerCycle(object state)
        {
            // Handle the dispose process.
            if (IsDisposing)
            {
                if (ThreadingTimer != null)
                {
                    ThreadingTimer.Dispose();
                    ThreadingTimer = null;
                }

                if (FormsTimer != null)
                {
                    FormsTimer.Dispose();
                    FormsTimer = null;
                }

                if (DispatcherTimer != null)
                {
                    DispatcherTimer.Stop();
                    DispatcherTimer = null;
                }

                DisposeCallback?.Invoke();
                return;
            }

            // Skip running this cycle if we are already in the middle of one
            if (IsCycleDone.IsInProgress)
            {
                return;
            }

            // Start a cycle by signaling it
            IsCycleDone.Begin();

            try
            {
                // Call the configured timer callback
                TimerCallback();
            }
            catch
            {
                throw;
            }
            finally
            {
                // Finalize the cycle
                IsCycleDone.Complete();
            }
        }
Ejemplo n.º 5
0
        private void DelayThreadPool()
        {
            if (_delayEvent == null)
            {
                _delayEvent = WaitEventFactory.Create(isCompleted: true, useSlim: true);
            }

            _delayEvent.Begin();
            ThreadPool.QueueUserWorkItem((s) =>
            {
                DelaySleep();
                _delayEvent.Complete();
            });

            _delayEvent.Wait();
        }
        /// <inheritdoc />
        public int Read(byte[] targetBuffer, int targetBufferOffset, int requestedBytes)
        {
            // We sync-lock the reads to avoid null reference exceptions as destroy might have been called
            var lockTaken = false;

            Monitor.TryEnter(SyncLock, SyncLockTimeout, ref lockTaken);

            if (lockTaken == false || HasFiredAudioDeviceStopped)
            {
                Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                return(requestedBytes);
            }

            try
            {
                WaitForReadyEvent.Complete();
                var speedRatio = MediaCore.State.SpeedRatio;

                // Render silence if we don't need to output samples
                if (MediaCore.State.IsPlaying == false || speedRatio <= 0d || MediaCore.State.HasAudio == false || AudioBuffer.ReadableCount <= 0)
                {
                    Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                    return(requestedBytes);
                }

                // Ensure a pre-allocated ReadBuffer
                if (ReadBuffer == null || ReadBuffer.Length < Convert.ToInt32(requestedBytes * Constants.Controller.MaxSpeedRatio))
                {
                    ReadBuffer = new byte[Convert.ToInt32(requestedBytes * Constants.Controller.MaxSpeedRatio)];
                }

                // First part of DSP: Perform AV Synchronization if needed
                if (MediaCore.State.HasVideo && Synchronize(targetBuffer, targetBufferOffset, requestedBytes, speedRatio) == false)
                {
                    return(requestedBytes);
                }

                var startPosition = Position;

                // Perform DSP
                if (speedRatio < 1.0)
                {
                    if (AudioProcessor != null)
                    {
                        ReadAndUseAudioProcessor(requestedBytes, speedRatio);
                    }
                    else
                    {
                        ReadAndSlowDown(requestedBytes, speedRatio);
                    }
                }
                else if (speedRatio > 1.0)
                {
                    if (AudioProcessor != null)
                    {
                        ReadAndUseAudioProcessor(requestedBytes, speedRatio);
                    }
                    else
                    {
                        ReadAndSpeedUp(requestedBytes, true, speedRatio);
                    }
                }
                else
                {
                    if (requestedBytes > AudioBuffer.ReadableCount)
                    {
                        Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                        return(requestedBytes);
                    }

                    AudioBuffer.Read(requestedBytes, ReadBuffer, 0);
                }

                ApplyVolumeAndBalance(targetBuffer, targetBufferOffset, requestedBytes);
                MediaElement.RaiseRenderingAudioEvent(
                    targetBuffer, requestedBytes, startPosition, WaveFormat.ConvertByteSizeToDuration(requestedBytes));
            }
            catch (Exception ex)
            {
                this.LogError(Aspects.AudioRenderer, $"{nameof(AudioRenderer)}.{nameof(Read)} has faulted.", ex);
                Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
            }
            finally
            {
                Monitor.Exit(SyncLock);
            }

            return(requestedBytes);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Performs the continuous playback.
        /// </summary>
        private void PerformContinuousPlayback()
        {
            var queued = 0;

            PlaybackState = PlaybackState.Playing;

            try
            {
                while (IsCancellationPending == false)
                {
                    if (DriverCallbackEvent.WaitOne(DesiredLatency) == false)
                    {
                        if (IsCancellationPending == true)
                        {
                            break;
                        }

                        Renderer?.MediaCore?.Log(MediaLogMessageType.Warning,
                                                 $"{nameof(AudioPlaybackThread)}:{nameof(DriverCallbackEvent)} timed out. Desired Latency: {DesiredLatency}ms");
                        continue;
                    }

                    // Reset the queue count
                    queued = 0;
                    if (IsCancellationPending == true)
                    {
                        break;
                    }

                    foreach (var buffer in Buffers)
                    {
                        if (buffer.IsQueued || buffer.ReadWaveStream())
                        {
                            queued++;
                        }
                    }

                    // Detect an end of playback
                    if (queued <= 0)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Renderer?.MediaCore?.Log(MediaLogMessageType.Error,
                                         $"{nameof(LegacyAudioPlayer)} faulted. {ex.GetType().Name}: {ex.Message}");
                throw;
            }
            finally
            {
                // Update the state
                PlaybackState = PlaybackState.Stopped;

                // Immediately stop the audio driver. Pause it first to
                // avoid quirky repetitive samples
                try { WaveInterop.PauseAudioDevice(DeviceHandle); } catch { }
                try { WaveInterop.ResetAudioDevice(DeviceHandle); } catch { }

                // Dispose of buffers
                foreach (var buffer in Buffers)
                {
                    try { buffer.Dispose(); } catch { }
                }

                // Close the device
                try { WaveInterop.CloseAudioDevice(DeviceHandle); } catch { }

                // Dispose of managed state
                DeviceHandle = IntPtr.Zero;
                PlaybackFinished.Complete();
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Called whenever the audio driver requests samples.
        /// Do not call this method directly.
        /// </summary>
        /// <param name="targetBuffer">The render buffer.</param>
        /// <param name="targetBufferOffset">The render buffer offset.</param>
        /// <param name="requestedBytes">The requested bytes.</param>
        /// <returns>The number of bytes that were read.</returns>
        public int Read(byte[] targetBuffer, int targetBufferOffset, int requestedBytes)
        {
            // We sync-lock the reads to avoid null reference exceptions as detaroy might have been called
            lock (SyncLock)
            {
                try
                {
                    WaitForReadyEvent.Complete();
                    var speedRatio = MediaCore?.State.SpeedRatio ?? 0;

                    // Render silence if we don't need to output samples
                    if (MediaCore.State.IsPlaying == false || speedRatio <= 0d || MediaCore.State.HasAudio == false || AudioBuffer.ReadableCount <= 0)
                    {
                        Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                        return(requestedBytes);
                    }

                    // Ensure a preallocated ReadBuffer
                    if (ReadBuffer == null || ReadBuffer.Length < Convert.ToInt32(requestedBytes * Constants.Controller.MaxSpeedRatio))
                    {
                        ReadBuffer = new byte[Convert.ToInt32(requestedBytes * Constants.Controller.MaxSpeedRatio)];
                    }

                    // First part of DSP: Perform AV Synchronization if needed
                    if (MediaCore.State.HasVideo && Synchronize(targetBuffer, targetBufferOffset, requestedBytes, speedRatio) == false)
                    {
                        return(requestedBytes);
                    }

                    // Perform DSP
                    if (speedRatio < 1.0)
                    {
                        if (AudioProcessor != null)
                        {
                            ReadAndUseAudioProcessor(requestedBytes, speedRatio);
                        }
                        else
                        {
                            ReadAndSlowDown(requestedBytes, speedRatio);
                        }
                    }
                    else if (speedRatio > 1.0)
                    {
                        if (AudioProcessor != null)
                        {
                            ReadAndUseAudioProcessor(requestedBytes, speedRatio);
                        }
                        else
                        {
                            ReadAndSpeedUp(requestedBytes, true, speedRatio);
                        }
                    }
                    else
                    {
                        if (requestedBytes > AudioBuffer.ReadableCount)
                        {
                            Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                            return(requestedBytes);
                        }

                        AudioBuffer.Read(requestedBytes, ReadBuffer, 0);
                    }

                    ApplyVolumeAndBalance(targetBuffer, targetBufferOffset, requestedBytes);
                }
                catch (Exception ex)
                {
                    MediaCore?.Log(MediaLogMessageType.Error, $"{ex.GetType()} in {nameof(AudioRenderer)}.{nameof(Read)}: {ex.Message}. Stack Trace:\r\n{ex.StackTrace}");
                    Array.Clear(targetBuffer, targetBufferOffset, requestedBytes);
                }

                return(requestedBytes);
            }
        }