public long ConvertFrom(ILength length, long time, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var mathLength = length as MathLength; if (mathLength == null) { throw new ArgumentException($"Length is not an instance of the {nameof(MathLength)}.", nameof(length)); } var convertedLength1 = LengthConverter.ConvertFrom(mathLength.Length1, time, tempoMap); var endTime1 = time + convertedLength1; switch (mathLength.Operation) { case MathOperation.Sum: return(convertedLength1 + LengthConverter.ConvertFrom(mathLength.Length2, endTime1, tempoMap)); case MathOperation.Subtract: return(convertedLength1 - LengthConverter.ConvertFrom(mathLength.Length2, endTime1, tempoMap.Flip(endTime1))); } throw new NotImplementedException($"Conversion from the {nameof(MathLength)} with {mathLength.Operation} operation is not implemented."); }
/// <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 null.</exception> public void SetTimeSignature(long time, TimeSignature timeSignature) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(timeSignature), timeSignature); TempoMap.TimeSignature.SetValue(time, timeSignature); }
private static MetricTime ConvertToByTicksPerQuarterNote(long time, short ticksPerQuarterNote, TempoMap tempoMap) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); // var tempoLine = tempoMap.Tempo; var tempoChanges = tempoLine.Values.Where(v => v.Time < time); if (!tempoChanges.Any()) { return(new MetricTime(RoundMicroseconds(GetMicroseconds(time, Tempo.Default, ticksPerQuarterNote)))); } // var accumulatedMicroseconds = 0d; var lastTime = 0L; var lastTempo = Tempo.Default; foreach (var tempoChange in tempoChanges.Concat(new[] { new ValueChange <Tempo>(time, tempoLine.AtTime(time)) })) { var tempoChangeTime = tempoChange.Time; accumulatedMicroseconds += GetMicroseconds(tempoChangeTime - lastTime, lastTempo, ticksPerQuarterNote); lastTempo = tempoChange.Value; lastTime = tempoChangeTime; } return(new MetricTime(RoundMicroseconds(accumulatedMicroseconds))); }
/// <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"> /// <paramref name="startTime" /> is negative. -or- /// <paramref name="endTime" /> is negative. /// </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); }
/// <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"><paramref name="startTime"/> is negative. -or- /// <paramref name="endTime"/> is negative.</exception> public void ClearTempo(long startTime, long endTime) { ThrowIfTimeArgument.StartIsNegative(nameof(startTime), startTime); ThrowIfTimeArgument.EndIsNegative(nameof(endTime), endTime); TempoMap.Tempo.DeleteValues(startTime, endTime); }
/// <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> /// Initializes a new instance of the <see cref="MathTime"/> with the specified /// time, offset and mathematical operation. /// </summary> /// <param name="time">The MIDI time to add <paramref name="offset"/> to or /// subtract <paramref name="offset"/> from.</param> /// <param name="offset"><see cref="ILength"/> that should be added to or subtracted /// from <paramref name="time"/>.</param> /// <param name="operation">Mathematical operation to perform on <paramref name="time"/>.</param> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="offset"/> is null.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="operation"/> specified /// an invalid value.</exception> public MathTime(long time, ILength offset, MathOperation operation = MathOperation.Sum) : this(offset, operation) { ThrowIfTimeArgument.IsNegative(nameof(time), time); MidiTime = time; }
/// <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 null. /// If <paramref name="time"/> is greater than end time of the note, the right part /// will be null. /// </remarks> /// <param name="time">Time to split the note by.</param> /// <returns>An object containing left and right parts of the splitted <see cref="Note"/>. /// Both parts are instances of <see cref="Note"/> too.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> public SplittedLengthedObject<Note> Split(long time) { ThrowIfTimeArgument.IsNegative(nameof(time), time); // var startTime = Time; var endTime = startTime + Length; if (time <= startTime) return new SplittedLengthedObject<Note>(null, Clone()); if (time >= endTime) return new SplittedLengthedObject<Note>(Clone(), null); // var leftPart = Clone(); leftPart.Length = time - startTime; var rightPart = Clone(); rightPart.Time = time; rightPart.Length = endTime - time; return new SplittedLengthedObject<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 null.</exception> public void SetTempo(long time, Tempo tempo) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempo), tempo); TempoMap.Tempo.SetValue(time, tempo); }
/// <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> /// 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 null.</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 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 null.</exception> internal ValueChange(long time, TValue value) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(value), value); Time = time; Value = value; }
/// <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"><paramref name="eventsCollection"/> is null. -or- /// <paramref name="midiEvent"/> is null.</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> /// Converts time from <see cref="long"/> to the specified time type. /// </summary> /// <typeparam name="TTime">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="TTime"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception> /// <exception cref="NotSupportedException"><typeparamref name="TTime"/> is not supported.</exception> public static TTime ConvertTo <TTime>(long time, TempoMap tempoMap) where TTime : ITime { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return((TTime)GetConverter <TTime>().ConvertTo(time, tempoMap)); }
/// <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> /// 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(ILength length, long time, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(LengthConverterFactory.GetConverter(length.GetType()) .ConvertFrom(length, time, tempoMap)); }
/// <summary> /// Converts length from <see cref="long"/> to the specified length type. /// </summary> /// <typeparam name="TLength">Type that will represent the length of an object.</typeparam> /// <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 an instance of <typeparamref name="TLength"/>.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is negative. -or- /// <paramref name="time"/> is negative.</exception> /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception> /// <exception cref="NotSupportedException"><typeparamref name="TLength"/> is not supported.</exception> public static TLength ConvertTo <TLength>(long length, long time, TempoMap tempoMap) where TLength : ILength { ThrowIfLengthArgument.IsNegative(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return((TLength)GetConverter <TLength>().ConvertTo(length, time, tempoMap)); }
/// <summary> /// Converts length from one length type to another one. /// </summary> /// <typeparam name="TLength">Type that will represent the length of an object.</typeparam> /// <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 an instance of <typeparamref name="TLength"/>.</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> /// <exception cref="NotSupportedException"><typeparamref name="TLength"/> is not supported.</exception> public static TLength ConvertTo <TLength>(ILength length, long time, TempoMap tempoMap) where TLength : ILength { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(ConvertTo <TLength>(ConvertFrom(length, time, tempoMap), time, tempoMap)); }
/// <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(_values.Where(p => p.Time <= time) .OrderBy(p => p.Time) .LastOrDefault() ?.Value ?? _defaultValue); }
public ILength ConvertTo(long length, long time, TempoMap tempoMap) { ThrowIfLengthArgument.IsNegative(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); // var startTime = TimeConverter.ConvertTo <MetricTime>(time, tempoMap); var endTime = TimeConverter.ConvertTo <MetricTime>(time + length, tempoMap); return(new MetricLength(endTime - startTime)); }
public ITime ConvertTo(long time, TempoMap tempoMap) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var ticksPerQuarterNoteTimeDivision = tempoMap.TimeDivision as TicksPerQuarterNoteTimeDivision; if (ticksPerQuarterNoteTimeDivision != null) { return(ConvertToByTicksPerQuarterNote(time, ticksPerQuarterNoteTimeDivision.TicksPerQuarterNote, tempoMap)); } ThrowIfTimeDivision.IsNotSupportedForTimeConversion(tempoMap.TimeDivision); return(null); }
/// <summary> /// Sets new value at specified time that will last until next value change. /// </summary> /// <param name="time">Time parameter's value should be changed at.</param> /// <param name="value">New parameter's 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 null.</exception> internal void SetValue(long time, TValue value) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(value), value); var currentValue = AtTime(time); if (currentValue.Equals(value)) { return; } _values.RemoveAll(v => v.Time == time); _values.Add(new ValueChange <TValue>(time, value)); }
public ILength ConvertTo(long length, long time, TempoMap tempoMap) { ThrowIfLengthArgument.IsNegative(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var ticksPerQuarterNoteTimeDivision = tempoMap.TimeDivision as TicksPerQuarterNoteTimeDivision; if (ticksPerQuarterNoteTimeDivision != null) { return(new MusicalLength(FractionUtilities.FromTicks(length, ticksPerQuarterNoteTimeDivision.TicksPerQuarterNote))); } ThrowIfTimeDivision.IsNotSupportedForLengthConversion(tempoMap.TimeDivision); return(null); }
public long ConvertFrom(ILength length, long time, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var metricLength = length as MetricLength; if (metricLength == null) { throw new ArgumentException($"Length is not an instance of the {nameof(MetricLength)}.", nameof(length)); } var startTime = TimeConverter.ConvertTo <MetricTime>(time, tempoMap); var endTime = new MetricTime(startTime.TotalMicroseconds + metricLength.TotalMicroseconds); return(TimeConverter.ConvertFrom(endTime, tempoMap) - time); }
private static MusicalTime ConvertToByTicksPerQuarterNote(long time, short ticksPerQuarterNote, TempoMap tempoMap) { ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); // var bars = 0; var lastTime = 0L; var lastTimeSignature = TimeSignature.Default; foreach (var timeSignatureChange in tempoMap.TimeSignature.Values.Where(v => v.Time <= time)) { var timeSignatureChangeTime = timeSignatureChange.Time; bars += GetBarsCount(timeSignatureChangeTime - lastTime, lastTimeSignature, ticksPerQuarterNote); lastTimeSignature = timeSignatureChange.Value; lastTime = timeSignatureChangeTime; } // var deltaTime = time - lastTime; var lastBars = GetBarsCount(deltaTime, lastTimeSignature, ticksPerQuarterNote); bars += lastBars; // deltaTime = deltaTime % GetBarLength(lastTimeSignature, ticksPerQuarterNote); var beatLength = GetBeatLength(lastTimeSignature, ticksPerQuarterNote); var beats = deltaTime / beatLength; // var fraction = FractionUtilities.FromTicks(deltaTime % beatLength, ticksPerQuarterNote); // return(new MusicalTime(bars, (int)beats, fraction)); }
public long ConvertFrom(ILength length, long time, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(length), length); ThrowIfTimeArgument.IsNegative(nameof(time), time); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var musicalLength = length as MusicalLength; if (musicalLength == null) { throw new ArgumentException($"Length is not an instance of the {nameof(MusicalLength)}.", nameof(length)); } var ticksPerQuarterNoteTimeDivision = tempoMap.TimeDivision as TicksPerQuarterNoteTimeDivision; if (ticksPerQuarterNoteTimeDivision != null) { return(musicalLength.Fraction.ToTicks(ticksPerQuarterNoteTimeDivision.TicksPerQuarterNote)); } ThrowIfTimeDivision.IsNotSupportedForLengthConversion(tempoMap.TimeDivision); return(0); }