/// <summary> /// Gets length of an <see cref="ILengthedObject"/> as an instance of type that /// implements the <see cref="ITimeSpan"/> interface. /// </summary> /// <typeparam name="TLength">Type that will represent the length of the <paramref name="obj"/>.</typeparam> /// <param name="obj">Object to get length of.</param> /// <param name="tempoMap">Tempo map to calculate length of the <paramref name="obj"/>.</param> /// <returns>Length of the specified object as an instance of <typeparamref name="TLength"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="obj"/> is null. -or- /// <paramref name="tempoMap"/> is null.</exception> /// <exception cref="NotSupportedException"><typeparamref name="TLength"/> is not supported.</exception> public static TLength LengthAs <TLength>(this ILengthedObject obj, TempoMap tempoMap) where TLength : ITimeSpan { ThrowIfArgument.IsNull(nameof(obj), obj); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(LengthConverter.ConvertTo <TLength>(obj.Length, obj.Time, tempoMap)); }
/// <summary> /// Gets length of an <see cref="ILengthedObject"/> as an instance of type defined by the /// specified time span type. /// </summary> /// <param name="obj">Object to get length of.</param> /// <param name="lengthType">The type of time span to convert the length of <paramref name="obj"/> to.</param> /// <param name="tempoMap">Tempo map to calculate length of the <paramref name="obj"/>.</param> /// <returns>Time of the specified object as an instance of time span defined by the /// <paramref name="lengthType"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="obj"/> is null. -or- /// <paramref name="tempoMap"/> is null.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="lengthType"/> specified an invalid value.</exception> public static ITimeSpan LengthAs(this ILengthedObject obj, TimeSpanType lengthType, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(obj), obj); ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(LengthConverter.ConvertTo(obj.Length, lengthType, obj.Time, tempoMap)); }
/// <summary> /// Resizes group of notes to the specified length treating all notes as single object. /// </summary> /// <param name="notes">Notes to resize.</param> /// <param name="length">New length of the notes collection.</param> /// <param name="distanceCalculationType">Type of distance calculations.</param> /// <param name="tempoMap"></param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="notes"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="length"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="tempoMap"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> /// <exception cref="ArgumentException"><see cref="TimeSpanType.BarBeatTicks"/> or <see cref="TimeSpanType.BarBeatFraction"/> /// is used for <paramref name="distanceCalculationType"/> which is unsupported.</exception> /// <exception cref="InvalidEnumArgumentException"><paramref name="distanceCalculationType"/> specified an /// invalid value.</exception> public static void ResizeNotes(this IEnumerable <Note> notes, ITimeSpan length, TimeSpanType distanceCalculationType, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(notes), notes); ThrowIfArgument.IsNull(nameof(length), length); ThrowIfArgument.IsInvalidEnumValue(nameof(distanceCalculationType), distanceCalculationType); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); // Unable to calculate ratio between two bar/beat time spans if (distanceCalculationType == TimeSpanType.BarBeatTicks || distanceCalculationType == TimeSpanType.BarBeatFraction) { throw new ArgumentException("Bar/beat distance calculation type is not supported.", nameof(distanceCalculationType)); } var notNullNotes = notes.Where(n => n != null); if (!notNullNotes.Any()) { return; } // var minStartTime = long.MaxValue; var maxEndTime = 0L; foreach (var note in notNullNotes) { var noteStartTime = note.Time; var noteEndTime = noteStartTime + note.Length; minStartTime = Math.Min(minStartTime, noteStartTime); maxEndTime = Math.Max(maxEndTime, noteEndTime); } var totalLength = maxEndTime - minStartTime; // var oldLength = LengthConverter.ConvertTo(totalLength, distanceCalculationType, minStartTime, tempoMap); var newLength = LengthConverter.ConvertTo(length, distanceCalculationType, minStartTime, tempoMap); var ratio = TimeSpanUtilities.Divide(newLength, oldLength); var startTime = TimeConverter.ConvertTo(minStartTime, distanceCalculationType, tempoMap); ResizeNotesByRatio(notNullNotes, ratio, distanceCalculationType, tempoMap, startTime); }