Example #1
0
        /// <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));
        }
Example #2
0
        /// <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 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>
        /// Removes all changes of tempo that occured between the specified times.
        /// </summary>
        /// <param name="startTime">Start of time range to remove changes of tempo in.</param>
        /// <param name="endTime">End of time range to remove changes of tempo in.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="startTime"/> is negative.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="endTime"/> is negative.</description>
        /// </item>
        /// </list>
        /// </exception>
        public void ClearTempo(long startTime, long endTime)
        {
            ThrowIfTimeArgument.StartIsNegative(nameof(startTime), startTime);
            ThrowIfTimeArgument.EndIsNegative(nameof(endTime), endTime);

            TempoMap.TempoLine.DeleteValues(startTime, endTime);
        }
        /// <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);
        }
Example #6
0
        /// <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>
        /// 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));
        }
Example #9
0
        /// <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));
        }
Example #10
0
        /// <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));
        }
Example #11
0
        /// <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));
        }
Example #12
0
        /// <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;
        }
Example #13
0
        /// <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);
        }
Example #14
0
        /// <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));
        }
Example #16
0
        /// <summary>
        /// Deletes all parameter's value changes in the specified time range.
        /// </summary>
        /// <param name="startTime">Start time of the time range where value changes should be deleted.</param>
        /// <param name="endTime">End time of the time range where value changes should be deleted.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="startTime"/> is negative.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="endTime"/> is negative.</description>
        /// </item>
        /// </list>
        /// </exception>
        internal void DeleteValues(long startTime, long endTime)
        {
            ThrowIfTimeArgument.StartIsNegative(nameof(startTime), startTime);
            ThrowIfTimeArgument.EndIsNegative(nameof(endTime), endTime);

            _values.RemoveAll(v => v.Time >= startTime && v.Time <= endTime);

            OnValuesChanged();
        }
Example #17
0
        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();
        }
Example #18
0
        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);
        }
Example #19
0
        /// <summary>
        /// Removes all changes of tempo that occured since the specified time.
        /// </summary>
        /// <param name="startTime">Time to remove changes of tempo since.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="startTime"/> is negative.</exception>
        public void ClearTempo(long startTime)
        {
            ThrowIfTimeArgument.StartIsNegative(nameof(startTime), startTime);

            TempoMap.Tempo.DeleteValues(startTime);
        }
Example #20
0
        public TValue AtTime(long time)
        {
            ThrowIfTimeArgument.IsNegative(nameof(time), time);

            return(GetValueAtTime(time));
        }
        /// <summary>
        /// Removes all changes of time signature that occured since the specified time.
        /// </summary>
        /// <param name="startTime">Time to remove changes of time signature since.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="startTime"/> is negative.</exception>
        public void ClearTimeSignature(long startTime)
        {
            ThrowIfTimeArgument.StartIsNegative(nameof(startTime), startTime);

            TempoMap.TimeSignatureLine.DeleteValues(startTime);
        }