/// <summary> /// Inserts an IMidiMessage at the specified position in absolute ticks. /// </summary> /// <param name="position"> /// The position in the Track in absolute ticks in which to insert the /// IMidiMessage. /// </param> /// <param name="message"> /// The IMidiMessage to insert. /// </param> public void Insert(int position, IMidiMessage message) { #region Require if (position < 0) { throw new ArgumentOutOfRangeException("position", position, "IMidiMessage position out of range."); } else if (message == null) { throw new ArgumentNullException("message"); } #endregion MidiEvent newMidiEvent = new MidiEvent(this, position, message); if (head == null) { head = newMidiEvent; tail = newMidiEvent; } else if (position >= tail.AbsoluteTicks) { newMidiEvent.Previous = tail; tail.Next = newMidiEvent; tail = newMidiEvent; endOfTrackMidiEvent.SetAbsoluteTicks(Length); endOfTrackMidiEvent.Previous = tail; } else { MidiEvent current = head; while (current.AbsoluteTicks < position) { current = current.Next; } newMidiEvent.Next = current; newMidiEvent.Previous = current.Previous; if (current.Previous != null) { current.Previous.Next = newMidiEvent; } else { head = newMidiEvent; } current.Previous = newMidiEvent; } count++; #region Invariant AssertValid(); #endregion }
public Track() { endOfTrackMidiEvent = new MidiEvent(this, Length, MetaMessage.EndOfTrackMessage); }
/// <summary> /// Gets the MidiEvent at the specified index. /// </summary> /// <param name="index"> /// The index of the MidiEvent to get. /// </param> /// <returns> /// The MidiEvent at the specified index. /// </returns> public MidiEvent GetMidiEvent(int index) { #region Require if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException("index", index, "Track index out of range."); } #endregion MidiEvent result; if (index == Count - 1) { result = endOfTrackMidiEvent; } else { if (index < Count / 2) { result = head; for (int i = 0; i < index; i++) { result = result.Next; } } else { result = tail; for (int i = Count - 2; i > index; i--) { result = result.Previous; } } } #region Ensure #if (DEBUG) if (index == Count - 1) { Debug.Assert(result.AbsoluteTicks == Length); Debug.Assert(result.MidiMessage == MetaMessage.EndOfTrackMessage); } else { MidiEvent t = head; for (int i = 0; i < index; i++) { t = t.Next; } Debug.Assert(t == result); } #endif #endregion return(result); }
public void Move(MidiEvent e, int newPosition) { #region Require if (e.Owner != this) { throw new ArgumentException("MidiEvent does not belong to this Track."); } else if (newPosition < 0) { throw new ArgumentOutOfRangeException("newPosition"); } else if (e == endOfTrackMidiEvent) { throw new InvalidOperationException( "Cannot move end of track message. Use the EndOfTrackOffset property instead."); } #endregion MidiEvent previous = e.Previous; MidiEvent next = e.Next; if (e.Previous != null && e.Previous.AbsoluteTicks > newPosition) { e.Previous.Next = e.Next; if (e.Next != null) { e.Next.Previous = e.Previous; } while (previous != null && previous.AbsoluteTicks > newPosition) { next = previous; previous = previous.Previous; } } else if (e.Next != null && e.Next.AbsoluteTicks < newPosition) { e.Next.Previous = e.Previous; if (e.Previous != null) { e.Previous.Next = e.Next; } while (next != null && next.AbsoluteTicks < newPosition) { previous = next; next = next.Next; } } if (previous != null) { previous.Next = e; } if (next != null) { next.Previous = e; } e.Previous = previous; e.Next = next; e.SetAbsoluteTicks(newPosition); if (newPosition < head.AbsoluteTicks) { head = e; } if (newPosition > tail.AbsoluteTicks) { tail = e; } endOfTrackMidiEvent.SetAbsoluteTicks(Length); endOfTrackMidiEvent.Previous = tail; #region Invariant AssertValid(); #endregion }
/// <summary> /// Merges the specified Track with the current Track. /// </summary> /// <param name="trk"> /// The Track to merge with. /// </param> public void Merge(Track trk) { #region Require if (trk == null) { throw new ArgumentNullException("trk"); } #endregion #region Guard if (trk == this) { return; } else if (trk.Count == 1) { return; } #endregion #if (DEBUG) int oldCount = Count; #endif count += trk.Count - 1; MidiEvent a = head; MidiEvent b = trk.head; MidiEvent current = null; Debug.Assert(b != null); if (a != null && a.AbsoluteTicks <= b.AbsoluteTicks) { current = new MidiEvent(this, a.AbsoluteTicks, a.MidiMessage); a = a.Next; } else { current = new MidiEvent(this, b.AbsoluteTicks, b.MidiMessage); b = b.Next; } head = current; while (a != null && b != null) { while (a != null && a.AbsoluteTicks <= b.AbsoluteTicks) { current.Next = new MidiEvent(this, a.AbsoluteTicks, a.MidiMessage); current.Next.Previous = current; current = current.Next; a = a.Next; } if (a != null) { while (b != null && b.AbsoluteTicks <= a.AbsoluteTicks) { current.Next = new MidiEvent(this, b.AbsoluteTicks, b.MidiMessage); current.Next.Previous = current; current = current.Next; b = b.Next; } } } while (a != null) { current.Next = new MidiEvent(this, a.AbsoluteTicks, a.MidiMessage); current.Next.Previous = current; current = current.Next; a = a.Next; } while (b != null) { current.Next = new MidiEvent(this, b.AbsoluteTicks, b.MidiMessage); current.Next.Previous = current; current = current.Next; b = b.Next; } tail = current; endOfTrackMidiEvent.SetAbsoluteTicks(Length); endOfTrackMidiEvent.Previous = tail; #region Ensure #if (DEBUG) Debug.Assert(count == oldCount + trk.Count - 1); #endif #endregion #region Invariant AssertValid(); #endregion }