/// <summary> /// Initializes a new instance of the <see cref="Chord"/> with the specified /// collection of notes and chord time. /// </summary> /// <param name="notes">Notes to combine into a chord.</param> /// <param name="time">Time of the chord which is time of the earliest note of the <paramref name="notes"/>.</param> /// <exception cref="ArgumentNullException"><paramref name="notes"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public Chord(IEnumerable <Note> notes, long time) : this(notes) { ThrowIfTimeArgument.IsNegative(nameof(time), time); Time = time; }
/// <summary> /// Splits the current <see cref="Note"/> by the specified time. /// </summary> /// <remarks> /// If <paramref name="time"/> is less than time of the note, the left part will be <c>null</c>. /// If <paramref name="time"/> is greater than end time of the note, the right part /// will be <c>null</c>. /// </remarks> /// <param name="time">Time to split the note by.</param> /// <returns>An object containing left and right parts of the split <see cref="Note"/>. /// Both parts are instances of <see cref="Note"/> too.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public SplitLengthedObject <Note> Split(long time) { ThrowIfTimeArgument.IsNegative(nameof(time), time); // var startTime = Time; var endTime = startTime + Length; if (time <= startTime) { return(new SplitLengthedObject <Note>(null, Clone())); } if (time >= endTime) { return(new SplitLengthedObject <Note>(Clone(), null)); } // var leftPart = Clone(); leftPart.Length = time - startTime; var rightPart = Clone(); rightPart.Time = time; rightPart.Length = endTime - time; return(new SplitLengthedObject <Note>(leftPart, rightPart)); }
/// <summary> /// Sets new tempo that will last from the specified time until next change of tempo. /// </summary> /// <param name="time">Time to set the new tempo at.</param> /// <param name="tempo">New tempo that will last from the specified time until next change /// of tempo.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="tempo"/> is <c>null</c>.</exception> public void SetTempo(long time, Tempo tempo) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempo), tempo); TempoMap.TempoLine.SetValue(time, tempo); }
/// <summary> /// Splits the current <see cref="Chord"/> by the specified time. /// </summary> /// <remarks> /// If <paramref name="time"/> is less than time of the chord, the left part will be null. /// If <paramref name="time"/> is greater than end time of the chord, the right part /// will be null. /// </remarks> /// <param name="time">Time to split the chord by.</param> /// <returns>An object containing left and right parts of the splitted <see cref="Chord"/>. /// Both parts are instances of <see cref="Chord"/> too.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public SplittedLengthedObject <Chord> Split(long time) { ThrowIfTimeArgument.IsNegative(nameof(time), time); // var startTime = Time; var endTime = startTime + Length; if (time <= startTime) { return(new SplittedLengthedObject <Chord>(null, Clone())); } if (time >= endTime) { return(new SplittedLengthedObject <Chord>(Clone(), null)); } // var parts = Notes.Select(n => n.Split(time)).ToArray(); var leftPart = new Chord(parts.Select(p => p.LeftPart).Where(p => p != null)); var rightPart = new Chord(parts.Select(p => p.RightPart).Where(p => p != null)); return(new SplittedLengthedObject <Chord>(leftPart, rightPart)); }
/// <summary> /// Sets new time signature that will last from the specified time until next change of /// time signature. /// </summary> /// <param name="time">Time to set the new time signature at.</param> /// <param name="timeSignature">New time signature that will last from the specified /// time until next change of time signature.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="timeSignature"/> is <c>null</c>.</exception> public void SetTimeSignature(long time, TimeSignature timeSignature) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(timeSignature), timeSignature); TempoMap.TimeSignatureLine.SetValue(time, timeSignature); }
/// <summary> /// Adds a <see cref="MidiEvent"/> into a <see cref="TimedEventsCollection"/> with the specified /// absolute time. /// </summary> /// <param name="eventsCollection"><see cref="TimedEventsCollection"/> to add an event into.</param> /// <param name="midiEvent">Event to add into the <paramref name="eventsCollection"/>.</param> /// <param name="time">Absolute time that will be assigned to the <paramref name="midiEvent"/> /// when it will be placed into the <paramref name="eventsCollection"/>.</param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="eventsCollection"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="midiEvent"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public static void AddEvent(this TimedEventsCollection eventsCollection, MidiEvent midiEvent, long time) { ThrowIfArgument.IsNull(nameof(eventsCollection), eventsCollection); ThrowIfArgument.IsNull(nameof(midiEvent), midiEvent); ThrowIfTimeArgument.IsNegative(nameof(time), time); eventsCollection.Add(new TimedEvent(midiEvent, time)); }
/// <summary> /// Filters collection of <see cref="ITimedObject"/> to return objects at the specified time. /// </summary> /// <typeparam name="TObject">The type of the elements of <paramref name="objects"/>.</typeparam> /// <param name="objects">A collection to filter.</param> /// <param name="time">Time to filter objects by.</param> /// <returns>A collection that contains objects from the input sequence that are at the specified time.</returns> /// <remarks> /// Note that changes made on the objects returned by this method will not be saved to an underlying /// data source (events collection, track chunk, file). To change properties of timed objects and /// save them you need to use a manager appropriate for an object's type. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="objects"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public static IEnumerable <TObject> AtTime <TObject>(this IEnumerable <TObject> objects, long time) where TObject : ITimedObject { ThrowIfArgument.IsNull(nameof(objects), objects); ThrowIfTimeArgument.IsNegative(nameof(time), time); return(objects.Where(o => o.Time == time)); }
/// <summary> /// Converts length from the specified length type to <see cref="long"/>. /// </summary> /// <param name="length">Length to convert.</param> /// <param name="time">Start time of an object to convert length of.</param> /// <param name="tempoMap">Tempo map used to convert <paramref name="length"/>.</param> /// <returns>Length as <see cref="long"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="length"/> is null. -or- /// <paramref name="tempoMap"/> is null.</exception> public static long ConvertFrom(ITimeSpan length, long time, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(TimeSpanConverter.ConvertFrom(length, time, tempoMap)); }
/// <summary> /// Converts time from <see cref="long"/> to the specified time type. /// </summary> /// <param name="time">Time to convert.</param> /// <param name="timeType">Type that will represent the time of an object.</param> /// <param name="tempoMap">Tempo map used to convert <paramref name="time"/>.</param> /// <returns>Time as an instance of time span defined by <paramref name="timeType"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="timeType"/> specified an invalid value.</exception> public static ITimeSpan ConvertTo(long time, TimeSpanType timeType, TempoMap tempoMap) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsInvalidEnumValue(nameof(timeType), timeType); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(TimeSpanConverter.ConvertTo(time, timeType, 0, tempoMap)); }
/// <summary> /// Converts time from <see cref="long"/> to the specified time type. /// </summary> /// <typeparam name="TTimeSpan">Type that will represent the time of an object.</typeparam> /// <param name="time">Time to convert.</param> /// <param name="tempoMap">Tempo map used to convert <paramref name="time"/>.</param> /// <returns>Time as an instance of <typeparamref name="TTimeSpan"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception> /// <exception cref="NotSupportedException"><typeparamref name="TTimeSpan"/> is not supported.</exception> public static TTimeSpan ConvertTo <TTimeSpan>(long time, TempoMap tempoMap) where TTimeSpan : ITimeSpan { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(TimeSpanConverter.ConvertTo <TTimeSpan>(time, 0, tempoMap)); }
/// <summary> /// Initializes a new instance of the <see cref="ValueChange{T}"/> with the specified /// time of change and new value. /// </summary> /// <param name="time">MIDI time when value is changed.</param> /// <param name="value">New value that will last until next value change.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception> internal ValueChange(long time, TValue value) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(value), value); _time = time; Value = value; }
/// <summary> /// Gets value at specified time. /// </summary> /// <param name="time">Time to get a value at.</param> /// <returns>Parameter's value at the <paramref name="time"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public TValue AtTime(long time) { ThrowIfTimeArgument.IsNegative(nameof(time), time); return(this.TakeWhile(p => p.Time <= time) .LastOrDefault() ?.Value ?? _defaultValue); }
/// <summary> /// Filters collection of <see cref="ILengthedObject"/> to return objects at the specified time. /// </summary> /// <typeparam name="TObject">The type of the elements of <paramref name="objects"/>.</typeparam> /// <param name="objects">A collection to filter.</param> /// <param name="time">Time to filter objects by.</param> /// <param name="matchBy">Part of an object which have to be at <paramref name="time"/>.</param> /// <returns>A collection that contains objects from the input sequence that are at the specified time.</returns> /// <remarks> /// Note that changes made on the objects returned by this method will not be saved to an underlying /// data source (events collection, track chunk, file). To change properties of lengthed objects and /// save them you need to use a manager appropriate for an object's type. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="objects"/> is null. -or- One of the objects is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="matchBy"/> specified an invalid value.</exception> public static IEnumerable <TObject> AtTime <TObject>(this IEnumerable <TObject> objects, long time, LengthedObjectPart matchBy) where TObject : ILengthedObject { ThrowIfArgument.IsNull(nameof(objects), objects); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsInvalidEnumValue(nameof(matchBy), matchBy); return(objects.Where(o => o != null && IsObjectAtTime(o, time, matchBy))); }
/// <summary> /// Adds a <see cref="MidiEvent"/> into a <see cref="TimedEventsCollection"/> with the specified /// absolute time. /// </summary> /// <param name="eventsCollection"><see cref="TimedEventsCollection"/> to add an event into.</param> /// <param name="midiEvent">Event to add into the <paramref name="eventsCollection"/>.</param> /// <param name="time">Absolute time that will be assigned to the <paramref name="midiEvent"/> /// when it will be placed into the <paramref name="eventsCollection"/>.</param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="eventsCollection"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="midiEvent"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentException"><paramref name="midiEvent"/> is either system real-time or /// system common one.</exception> public static void AddEvent(this TimedEventsCollection eventsCollection, MidiEvent midiEvent, long time) { ThrowIfArgument.IsNull(nameof(eventsCollection), eventsCollection); ThrowIfArgument.IsNull(nameof(midiEvent), midiEvent); ThrowIfArgument.IsOfInvalidType <SystemRealTimeEvent, SystemCommonEvent>(nameof(midiEvent), midiEvent, "Event is either system real-time or system common one."); ThrowIfTimeArgument.IsNegative(nameof(time), time); eventsCollection.Add(new TimedEvent(midiEvent, time)); }
internal void SetValue(long time, TValue value) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(value), value); var currentValue = GetValueAtTime(time); if (currentValue.Equals(value)) { return; } _values.RemoveAll(v => v.Time == time); _values.Add(new ValueChange <TValue>(time, value)); OnValuesChanged(); }
internal void SetValue(long time, TValue value) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(value), value); var currentValue = GetValueAtTime(time); if (currentValue.Equals(value)) { return; } var indexToRemove = -1; for (var i = _valueChanges.Count - 1; i >= 0; i--) { if (_valueChanges[i].Time != time) { continue; } indexToRemove = i; break; } if (indexToRemove >= 0) { _valueChanges.RemoveAt(indexToRemove); } _valueChanges.Add(new ValueChange <TValue>(time, value)); var forceSort = time < _maxTime; if (time > _maxTime) { _maxTime = time; } OnValuesChanged(forceSort); }
public TValue AtTime(long time) { ThrowIfTimeArgument.IsNegative(nameof(time), time); return(GetValueAtTime(time)); }