using QuikDawEditor.SampleProviders; using System.Text.Json.Serialization; using System.Windows.Media.Imaging; namespace QuikDawEditor.EditingClasses; public partial class Clip : INotifyPropertyChanged { public string RelRes() { ReleaseResources(); return "Resources released"; } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public string UndoClipID { get; set; } public delegate void ClipSizeChangedHandler(); public event ClipSizeChangedHandler clipSizeChanged; public delegate void ClipSourceSizeChangedHandler(); public event ClipSourceSizeChangedHandler clipSourceSizeChanged; public void UpdateClipSizeChanged() { if (clipSizeChanged != null) clipSizeChanged(); } public void UpdateClipSourceSizeChanged() { if (clipSourceSizeChanged != null) clipSourceSizeChanged(); } internal Track myTrack; public float premoveLeftEdgeGainVal; public float premoveRightEdgeGainVal; public double premoveClipWidthms; public double premoveClipRelStartms; public double premoveClipRightms; public double ClipRightMs { get { return ClipVirtualStartMs + ClipRelativeLoopStartMs + ClipWidthMs; } } public double ClipWidthPixels { get { return ClipWidthMs / 1000 * PixelsPerSecond; } } public double ClipLeftMs { get { return ClipVirtualStartMs + ClipRelativeLoopStartMs; } } public string ClipIndexInTrackString { get { return "IndexInTrack=" + GetIndexInTrack.ToString(); } } private float _ClipGainFactor = 0.5f; public float ClipGainFactor { get { return _ClipGainFactor; } set { _ClipGainFactor = value; NotifyPropertyChanged(nameof(ClipBackgroundTransformY)); NotifyPropertyChanged(nameof(ClipBackgroundTranslateY)); } } public void UpdateClipHeightY() { NotifyPropertyChanged(nameof(ClipBackgroundTranslateY)); } public void AddMidiEventHandlers() { ClipMidiNotes.CollectionChanged += ClipMidiEventsSubCollection_CollectionChanged; ClipSustainEvents.CollectionChanged += ClipMidiEventsSubCollection_CollectionChanged; ClipPitchChangeEvents.CollectionChanged += ClipMidiEventsSubCollection_CollectionChanged; ClipModulationEvents.CollectionChanged += ClipMidiEventsSubCollection_CollectionChanged; } public ClipSampleProvider myClipSampleProvider; [JsonConstructor] public Clip(string ClipSourceFileName, string UndoClipID, ClipType clipType) { this.clipType = clipType; this.ClipSourceFileName = ClipSourceFileName; if (string.IsNullOrEmpty(UndoClipID)) this.UndoClipID = Guid.NewGuid().ToString(); else this.UndoClipID = UndoClipID; if (this.clipType == ClipType.Midi) { ClipBackgroundSources.Add(new ClipBackgroundSource(null)); AddMidiEventHandlers(); } } public Clip(string clipSourceFileName, ClipType addingClipType) { UndoClipID = Guid.NewGuid().ToString(); this.ClipSourceFileName = clipSourceFileName; this.clipType = addingClipType; //Debug.WriteLine("added events CollectionChanged - added clip"); if (addingClipType == ClipType.Midi) { ClipBackgroundSources.Add(new ClipBackgroundSource(null)); AddMidiEventHandlers(); } } public bool IsMidiClip { get { return clipType == ClipType.Midi; } } public bool IsAudioClip { get { return clipType == ClipType.Audio; } } private ClipType _clipType; public ClipType clipType { get { return _clipType; } set { _clipType = value; NotifyPropertyChanged(nameof(clipType)); } } private string _ClipName = ""; public string ClipName { get { return _ClipName == "" ? ClipFormatInfo : _ClipName; } set { _ClipName = value; NotifyPropertyChanged(nameof(_ClipName)); NotifyPropertyChanged(nameof(ClipName)); } } public string ClipNameFull { get { return ClipName + " (Time: " + ClipWidthInfo + ")"; } } private string _ClipSourceFileName; public string ClipSourceFileName { get { return _ClipSourceFileName; } set { _ClipSourceFileName = value; NotifyPropertyChanged(nameof(ClipFormatInfo)); NotifyPropertyChanged(nameof(ClipName)); } } internal double _ClipSourceLenMilliseconds = 100; public double ClipSourceLenMilliseconds { //get { return _ClipSourceLenMilliseconds; } get { return Math.Truncate(_ClipSourceLenMilliseconds); } set { //_ClipSourceLenMilliseconds = value; _ClipSourceLenMilliseconds = Math.Truncate(value); clipSourceLenMs60BPM = TranslateMsTo60BPM(_ClipSourceLenMilliseconds); RecreateClipUnitBackgrounds(); } } public double ClipRelativeLoopEndMs { get { return Math.Truncate(ClipRelativeLoopStartMs + ClipWidthMs); } } internal double _ClipVirtualStartMs = 0; public double ClipVirtualStartMs { get { return Math.Truncate(_ClipVirtualStartMs); } //get { return Math.Round(_ClipVirtualStartMs); } set { _ClipVirtualStartMs = Math.Truncate(value); // _ClipVirtualStartMs = Math.Round(value); clipVirtualStartMs60BPM = TranslateMsTo60BPM(_ClipVirtualStartMs); NotifyPropertyChanged(nameof(ClipLeftMs)); } } public void NotifyClipPropertyChanged() { NotifyPropertyChanged(nameof(ClipLeftMs)); NotifyPropertyChanged(nameof(ClipWidthMs)); NotifyPropertyChanged(nameof(zoomedWidth)); NotifyPropertyChanged(nameof(ClipWidthInfo)); NotifyPropertyChanged(nameof(ClipRelativeLoopStartMs)); NotifyPropertyChanged(nameof(ClipRelativeLoopEndMs)); NotifyPropertyChanged(nameof(ClipVirtualStartMs)); NotifyPropertyChanged(nameof(GainPoints)); NotifyGainPointsChanged(); RecreateClipUnitBackgrounds(); UpdateClipSizeChanged(); } public double clipWidthMs60BPM; public double clipVirtualStartMs60BPM; public double clipSourceLenMs60BPM; public double clipRelativeLoopStartMs60BPM; internal double _ClipRelativeLoopStartMs = 0; public double ClipRelativeLoopStartMs { get { return Math.Truncate(_ClipRelativeLoopStartMs); } //get { return Math.Round(_ClipRelativeLoopStartMs); } set { double newClipRelativeLoopStartMs = Math.Truncate(value); //double newClipRelativeLoopStartMs = Math.Round(value); double diffMs = _ClipRelativeLoopStartMs - newClipRelativeLoopStartMs; if (newClipRelativeLoopStartMs != _ClipRelativeLoopStartMs) { if (GainPoints.Count > 0) { float newLeftEdgeGainVal = 1; GainPoint checkGainPoint = null; if (newClipRelativeLoopStartMs > _ClipRelativeLoopStartMs) { checkGainPoint = GainPoints.FirstOrDefault(gp => gp.sourcePointms > newClipRelativeLoopStartMs); newLeftEdgeGainVal = ClipStartGainPoint.GainValue == 0 ? 0 : GetGainValBetweenGainPoints(newClipRelativeLoopStartMs, ClipStartGainPoint, checkGainPoint); } else { checkGainPoint = GainPoints.LastOrDefault(gp => gp.sourcePointms < newClipRelativeLoopStartMs); newLeftEdgeGainVal = (checkGainPoint == null || ClipStartGainPoint.GainValue == 0) ? ClipStartGainPoint.GainValue : GetGainValBetweenGainPoints(newClipRelativeLoopStartMs, checkGainPoint, ClipStartGainPoint); } ClipStartGainPoint.GainValue = newLeftEdgeGainVal; ClipStartGainPoint.sourcePointms = newClipRelativeLoopStartMs; if (GainPoints.FirstOrDefault(gp => gp.sourcePointms >= newClipRelativeLoopStartMs) != ClipStartGainPoint) SortGainPoints(); //This may be slowing audio } } _ClipRelativeLoopStartMs = newClipRelativeLoopStartMs; clipRelativeLoopStartMs60BPM = TranslateMsTo60BPM(_ClipRelativeLoopStartMs); SetClipWidthWithoutGainPointChanges(ClipWidthMs + diffMs); NotifyPropertyChanged(nameof(ClipRelativeLoopStartMs)); NotifyPropertyChanged(nameof(ClipLeftMs)); NotifyPropertyChanged(nameof(ClipRelativeLoopEndMs)); NotifyGainPointsChanged(); UpdateClipSizeChanged(); } } internal double _ClipWidthMs = 100; public double ClipWidthMs { //get { return Math.Round(_ClipWidthMs); } get { return Math.Truncate(_ClipWidthMs); } set { //double newClipWidthMs = Math.Round(value); double newClipWidthMs = Math.Truncate(value); if (newClipWidthMs != _ClipWidthMs) //if was changed { double newClipRelativeLoopEndMs = Math.Truncate(ClipRelativeLoopStartMs + newClipWidthMs); if (GainPoints.Count > 0) { float newRightEdgeGainVal = ClipEndGainPoint == null ? 1 : ClipEndGainPoint.GainValue; GainPoint checkGainPoint = null; if (newClipWidthMs < _ClipWidthMs) { checkGainPoint = GainPoints.LastOrDefault(gp => gp.sourcePointms < newClipRelativeLoopEndMs); if (checkGainPoint != null) newRightEdgeGainVal = GetGainValBetweenGainPoints(newClipRelativeLoopEndMs, checkGainPoint, ClipEndGainPoint); } else { checkGainPoint = GainPoints.FirstOrDefault(gp => gp.sourcePointms > newClipRelativeLoopEndMs); if (checkGainPoint != null) newRightEdgeGainVal = GetGainValBetweenGainPoints(newClipRelativeLoopEndMs, ClipEndGainPoint, checkGainPoint); } ClipEndGainPoint.GainValue = newRightEdgeGainVal; int clipendGPIdx = GainPoints.IndexOf(ClipEndGainPoint); ClipEndGainPoint.sourcePointms = newClipRelativeLoopEndMs; if (GainPoints.LastOrDefault(gp => gp.sourcePointms <= newClipRelativeLoopEndMs) != ClipEndGainPoint) SortGainPoints(); //This may be slowing audio } } bool wasIncreased = newClipWidthMs > _ClipWidthMs; _ClipWidthMs = newClipWidthMs; clipWidthMs60BPM = TranslateMsTo60BPM(_ClipWidthMs); NotifyPropertyChanged(nameof(ClipWidthMs)); NotifyPropertyChanged(nameof(zoomedWidth)); NotifyPropertyChanged(nameof(ClipWidthInfo)); NotifyGainPointsChanged(); UpdateClipSizeChanged(); if (wasIncreased) RecreateClipUnitBackgrounds(); } } public void SetClipWidthWithoutGainPointChanges(double newClipWidthMs) { _ClipWidthMs = Math.Truncate(newClipWidthMs); NotifyPropertyChanged(nameof(ClipWidthMs)); NotifyPropertyChanged(nameof(zoomedWidth)); NotifyPropertyChanged(nameof(ClipWidthInfo)); NotifyGainPointsChanged(); } [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public ObservableCollection ClipBackgroundSources { get; set; } = new ObservableCollection(); [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public ObservableCollection clipUnitBackgrounds { get; set; } = new ObservableCollection(); public double ClipBackgroundTransformX { get { return clipType == ClipType.Midi ? 1 : (IsReversed ? -1 : 1); } } public double ClipBackgroundTransformY { get { return (double)ClipGainFactor; } } public double ClipBackgroundTranslateX { get { return ClipBackgroundTransformX == 1 ? 0 : ClipUnitBackgroundWidth; } } public double ClipBackgroundTranslateY { get { double areaHeight = (myTrack.TrackHeight - 20); return (double)(areaHeight - ClipGainFactor * areaHeight) / 2D; } } public double ClipUnitBackgroundWidth { get { return MsecToPixelsZoomed(ClipSourceLenMilliseconds); } } internal void RecreateClipUnitBackgrounds() { clipUnitBackgrounds.Clear(); clipUnitBackgrounds.Add(new ClipUnitBackground()); double lastBorderMs = ClipRelativeLoopStartMs + ClipWidthMs; if (this.IsLooped | this.IsMidiClip) { if (ClipWidthMs + ClipRelativeLoopStartMs >= ClipSourceLenMilliseconds) { double covlen = 0; while (covlen <= ClipWidthMs + ClipRelativeLoopStartMs) { clipUnitBackgrounds.Add(new ClipUnitBackground()); covlen += ClipSourceLenMilliseconds; } } } } public double zoomedWidth { get { return MsecToPixelsZoomed(ClipWidthMs); } } private bool _IsSelected; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsSelected { get { return _IsSelected; } set { _IsSelected = value; NotifyPropertyChanged(nameof(IsSelected)); NotifyPropertyChanged(nameof(ClipBackgroundBrush)); } } private bool _IsEnabled = true; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsEnabled { get { return _IsEnabled; } set { _IsEnabled = value; NotifyPropertyChanged(nameof(IsEnabled)); } } private bool _IsOrphanClip = false; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsOrphanClip { get { return _IsOrphanClip; } set { _IsOrphanClip = value; NotifyPropertyChanged(nameof(IsClipAreaEnabled)); NotifyPropertyChanged(nameof(ClipBackgroundBrush)); } } private bool _IsVisible = true; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsVisible { get { return _IsVisible; } set { _IsVisible = value; NotifyPropertyChanged(nameof(ClipVisibility)); } } public Visibility ClipVisibility { get { return IsVisible ? Visibility.Visible : Visibility.Hidden; } } public bool IsClipAreaEnabled { get { return !IsOrphanClip; } } private string _LoadingImageBrush = "/EDITING/images/ClipBackgroundBrushLoading.png"; private string _ClipLoopedBrush = "/EDITING/images/ClipBackgroundBrushLooped.png"; public string loopedImageSource { get { return IsLooped ? "/EDITING/images/clipLoopOn.png" : "/EDITING/images/clipLoopOff.png"; } } private bool _IsWaveformLoaded = false; public bool IsWaveformLoaded { get { return _IsWaveformLoaded; } set { _IsWaveformLoaded = value; NotifyPropertyChanged(nameof(ClipAreaGridBackgroundBrush)); } } public string ClipAreaGridBackgroundBrush { get { return clipType == ClipType.Midi ? null : (IsWaveformLoaded ? (IsLooped ? _ClipLoopedBrush : null) : _LoadingImageBrush); } } private bool _IsMuted = false; public bool IsMuted { get { return _IsMuted; } set { _IsMuted = value; NotifyPropertyChanged(nameof(IsMuted)); NotifyPropertyChanged(nameof(mutedImageSource)); } } public string mutedImageSource { get { return _IsMuted ? "/EDITING/images/MuteButOn.png" : "/EDITING/images/MuteButOff.png"; } } private bool _IsLooped = false; public bool IsLooped { get { return _IsLooped; } set { _IsLooped = value; NotifyPropertyChanged(nameof(loopedImageSource)); NotifyPropertyChanged(nameof(ClipAreaGridBackgroundBrush)); } } private bool _IsReversed = false; public bool IsReversed { get { return _IsReversed; } set { _IsReversed = value; switch (clipType) { case ClipType.Audio: if (myClipSampleProvider != null) { myClipSampleProvider.AssignSampleProvider(_IsReversed); ResetMe(projPlayer.CurrentPlayingPosMS); WaveMidiTransformFactorX = _IsReversed ? -1 : 1; } break; case ClipType.Midi: ReverseMidiNotes(); break; } NotifyPropertyChanged(nameof(IsReversed)); NotifyPropertyChanged(nameof(ClipBackgroundTransformX)); NotifyPropertyChanged(nameof(ClipBackgroundTranslateX)); } } public void Dispose() { try { if (this.clipType == ClipType.Audio) { myClipSampleProvider?.Dispose(); myClipSampleProvider = null; } if (this.clipType == ClipType.Midi) { ClipMidiNotes.CollectionChanged -= ClipMidiEventsSubCollection_CollectionChanged; ClipSustainEvents.CollectionChanged -= ClipMidiEventsSubCollection_CollectionChanged; ClipPitchChangeEvents.CollectionChanged -= ClipMidiEventsSubCollection_CollectionChanged; ClipModulationEvents.CollectionChanged -= ClipMidiEventsSubCollection_CollectionChanged; } } catch (Exception ex) { MessageBox.Show("error disposing of clip\n" + ex.Message); } } private bool _IsSplitLineVisible = false; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsSplitLineVisible { get { return _IsSplitLineVisible; } set { _IsSplitLineVisible = value; NotifyPropertyChanged(nameof(IsSplitLineVisible)); } } private bool _IsClipInfoVisible = true; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public bool IsClipInfoVisible { get { return _IsClipInfoVisible; } set { _IsClipInfoVisible = value; NotifyPropertyChanged(nameof(IsClipInfoVisible)); } } private double _SplitButLineX; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public double SplitButLineX { get { return _SplitButLineX; } set { _SplitButLineX = value; NotifyPropertyChanged(nameof(SplitButLineX)); } } private int _MovingZIndex; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public int MovingZIndex { get { return _MovingZIndex; } set { _MovingZIndex = value; NotifyPropertyChanged(nameof(MovingZIndex)); } } public double NormalTransformFactorX { get { return editingProject.ViewXZoomFac; } } public double ReverseTransformFactorX { get { return 1 / editingProject.ViewXZoomFac; } } public void UpdateClipZoom() { NotifyPropertyChanged(nameof(ClipTopLabelReverseTransformFactorX)); NotifyPropertyChanged(nameof(zoomedWidth)); NotifyPropertyChanged(nameof(NormalTransformFactorX)); NotifyPropertyChanged(nameof(ReverseTransformFactorX)); NotifyPropertyChanged(nameof(ClipRelativeLoopStartMs)); NotifyPropertyChanged(nameof(ClipUnitBackgroundWidth)); NotifyPropertyChanged(nameof(ClipBackgroundTranslateX)); } public Thickness BackgroundBorderThickness { get { return new Thickness(0.5 * ReverseTransformFactorX, 0, 1 * ReverseTransformFactorX, 0.5); } } private double _WaveMidiTransformFactorX = 1; public double WaveMidiTransformFactorX { get { return _WaveMidiTransformFactorX; } set{ _WaveMidiTransformFactorX = value; } } private double myTrackYScale = 1; public void UpdateClipTopLabelX(double trackYScale) { myTrackYScale = trackYScale; NotifyPropertyChanged(nameof(ClipTopLabelReverseTransformFactorX)); } public double ClipTopLabelReverseTransformFactorX { get { return 1 / editingProject.ViewXZoomFac * myTrackYScale; } } public string ClipInfo { get { return ClipFormatInfo + "\n\n" + "Audio file source: " + ClipSourceFileName + "\n" + "IndexInTrack: " + myTrack.Clips.IndexOf(this) + "\n" + "IsOrphanClip?=" + IsOrphanClip + "\n" + "IsReversed?=" + IsReversed + "\n" + "ClipSourceLenMs: " + this.ClipSourceLenMilliseconds + "\n" + "ClipRelativeLoopStartMs: " + this.ClipRelativeLoopStartMs + "\n" + "ClipRelativeLoopEndMs: " + this.ClipRelativeLoopEndMs + "\n" + "ClipLeftMs: " + this.ClipLeftMs + "\n" + "ClipWidthMs: " + this.ClipWidthMs + "\n" + "ClipVirtualStartMs: " + this.ClipVirtualStartMs + "\n" + "ClipRightMs: " + this.ClipRightMs + "\n" + "ClipMidiEventsCount: " + this.ClipMidiEvents.Count + "\n"; } } public bool beingMoved; public bool IsBeingMoved { get { return beingMoved; } } public double Opacity { get { return beingMoved ? 0.7 : 1; } } private double _ClipAreaHeight = 60; [JsonIgnore(Condition = JsonIgnoreCondition.Always)] public double ClipAreaHeight { get { return _ClipAreaHeight; } set { _ClipAreaHeight = value; RedrawGainPoints(); } } public string ClipFormatInfo { get { string returnString = ""; //if (audioSourceFile != null) returnString = ClipSourceFileName + " (" + (this.WaveFormatString == null ? "nullwaveformatstring" : this.WaveFormatString) + ")"; return returnString; } } public string ClipWidthInfo { get { if (projPlayer.IsTimePlayScale) return TimeSpan.FromMilliseconds(ClipWidthMs).ToString("hh\\:mm\\:ss"); else return GetBeatMeasureString(ClipWidthMs); } } public Thickness ClipControlBorderThickness { get { return new Thickness(0); } } public Brush ClipBackgroundBrush { get { if (IsOrphanClip) return new SolidColorBrush(Color.FromArgb(175, 0, 0, 0)); if (IsSelected) return Brushes.SkyBlue; else //return new SolidColorBrush(Color.FromArgb(255, 140, 140, 135)); return new SolidColorBrush(Color.FromArgb(200, 120, 130, 120)); } } public void UpdateClipTopLabelColor() { NotifyPropertyChanged(nameof(ClipTopLabelBackgroundBrush)); } public LinearGradientBrush ClipTopLabelBackgroundBrush { get { if (myTrack == null) return null; else return new LinearGradientBrush() { StartPoint = new Point(0.5, 0), EndPoint = new Point(0.5, 1), GradientStops = new GradientStopCollection() { new GradientStop(myTrack.TrackBackgroundBrush.GradientStops[2].Color, 0.1), new GradientStop(myTrack.TrackBackgroundBrush.GradientStops[1].Color, 1.0), new GradientStop(myTrack.TrackBackgroundBrush.GradientStops[0].Color, 1.0) } }; } } //THIS CODE DETERMINES LOOPING PRECISION... //internal bool IsCurrentClip { get { return (ClipLeftMs <= projPlayer.CurrentPlayingPosMS - projPlayer.ProcessingRateMs) && (ClipRightMs > projPlayer.CurrentPlayingPosMS + projPlayer.ProcessingRateMs); } } //internal bool IsCurrentClip { get { return (ClipLeftMs <= projPlayer.CurrentPlayingPosMS) && (ClipRightMs >= projPlayer.CurrentPlayingPosMS); } } internal bool IsCurrentClip { get { return clipType == ClipType.Audio ? IsCurrentClipAudio : IsCurrentClipMidi; } } internal bool IsCurrentClipAudio { get { return ClipRightMs > projPlayer.CurrentPlayingPosMS; } //get { return (ClipLeftMs <= projPlayer.CurrentPlayingPosMS + projPlayer.ProcessingRateMs) && ClipRightMs > projPlayer.CurrentPlayingPosMS; } } internal bool IsCurrentClipMidi { get { return (ClipLeftMs <= projPlayer.CurrentPlayingPosMS + projPlayer.ProcessingRateMs - 1) && (ClipRightMs > projPlayer.CurrentPlayingPosMS + projPlayer.ProcessingRateMs); } } //internal bool IsNextClip { get { return ClipLeftMs >= projPlayer.CurrentPlayingPosMS; } } public bool OverlapsWithRect(Rect checkRect) { return (this.ClipRightMs > checkRect.Left & this.ClipRightMs < checkRect.Right) || (this.ClipLeftMs > checkRect.Left & this.ClipLeftMs < checkRect.Right) || this.ClipLeftMs < checkRect.Left && this.ClipRightMs > checkRect.Right; } //public bool BeginningClipPlay = false; public void ResetMe(double millisecondpoint) { if (myClipSampleProvider == null) return; ////////////////////////////////////////////////////////////////////// Have to reset the WdlResamplingSampleProvider to prevent glitching between clips myClipSampleProvider.AssignSampleProvider(this.IsReversed); ////////////////////////////////////////////////////////////////////// try { double newbaseStreamMs; if (millisecondpoint <= ClipLeftMs) newbaseStreamMs = ClipRelativeLoopStartMs; else { newbaseStreamMs = (millisecondpoint - ClipVirtualStartMs) % Math.Truncate(myClipSampleProvider.useWaveStream.TotalTime.TotalMilliseconds); } //*************************************************************************** newbaseStreamMs = newbaseStreamMs - (newbaseStreamMs % projPlayer.ProcessingRateMs); //*************************************************************************** try { TimeSpan newTimeSpan = TimeSpan.FromMilliseconds(newbaseStreamMs); if (myClipSampleProvider.useWaveStream.CurrentTime != newTimeSpan) { myClipSampleProvider.useWaveStream.CurrentTime = newTimeSpan; if (myClipSampleProvider.useWaveStream.Position % myClipSampleProvider.WaveFormat.BlockAlign != 0) { int over = (int)(myClipSampleProvider.useWaveStream.Position % myClipSampleProvider.WaveFormat.BlockAlign); myClipSampleProvider.useWaveStream.Position = myClipSampleProvider.useWaveStream.Position - (myClipSampleProvider.WaveFormat.BlockAlign - over); //Debug.WriteLine("%=" + (myClipSampleProvider.useWaveStream.Position % myClipSampleProvider.WaveFormat.BlockAlign).ToString()); } } } catch (Exception ex) { Debug.WriteLine("Error resetting clip:\n" + ex.Message); } } catch (Exception resetEx) { Debug.WriteLine("ERROR in ResetMe: " + "millisecpt=" + millisecondpoint.ToString() + ":::" + resetEx.Message); } } public double CalculateClipTopPix { get { return myTrack.GetActualTrackTop; } } internal int GetIndexInTrack { get{ return myTrack.Clips.IndexOf(this);}} public double GetLeftLimitMs { get { return GetIndexInTrack == 0 ? 0 : myTrack.Clips[GetIndexInTrack - 1].ClipRightMs; } } public double GetRightLimitMs { get { return GetIndexInTrack == myTrack.Clips.Count - 1 ? Double.MaxValue : myTrack.Clips[GetIndexInTrack + 1].ClipLeftMs; } } public double GetDistanceToPreviousClipMs { get { return ClipLeftMs - GetLeftLimitMs ; } } public double GetDistanceToNextClipMs { get { return GetRightLimitMs - ClipRightMs; } } public bool IsSelectedRightMostClipOnTrack { get { return myTrack.Clips.Where(cc=>cc.IsSelected).Max(cc=>cc.GetIndexInTrack) == GetIndexInTrack; } } public bool IsSelectedLeftMostClipOnTrack { get { return myTrack.Clips.Where(cc=>cc.IsSelected).Min(cc=>cc.GetIndexInTrack) == GetIndexInTrack; } } }