Пример #1
0
        /// <summary>
        /// Gets length of an <see cref="ILengthedObject"/> as an instance of type that
        /// implements the <see cref="ILength"/> 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 : ILength
        {
            ThrowIfArgument.IsNull(nameof(obj), obj);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            return(LengthConverter.ConvertTo <TLength>(obj.Length, obj.Time, tempoMap));
        }
Пример #2
0
        /// <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"><paramref name="notes"/> is null. -or-
        /// <paramref name="length"/> is null. -or- <paramref name="tempoMap"/> is null.</exception>
        /// <exception cref="ArgumentException"><see cref="TimeSpanType.BarBeat"/> used for <paramref name="distanceCalculationType"/>
        /// with relative resizing.</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);

            if (distanceCalculationType == TimeSpanType.BarBeat)
            {
                throw new ArgumentException("BarBeat length type is not supported for relative resizing.", nameof(distanceCalculationType));
            }

            if (!notes.Any())
            {
                return;
            }

            //

            var minStartTime = long.MaxValue;
            var maxEndTime   = 0L;

            foreach (var note in notes.Where(n => n != null))
            {
                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);

            foreach (var note in notes.Where(n => n != null))
            {
                var noteLength = note.LengthAs(distanceCalculationType, tempoMap);
                var noteTime   = note.TimeAs(distanceCalculationType, tempoMap);

                var scaledShiftFromStart = noteTime.Subtract(startTime, TimeSpanMode.TimeTime).Multiply(ratio);
                note.Time = TimeConverter.ConvertFrom(startTime.Add(scaledShiftFromStart, TimeSpanMode.TimeLength), tempoMap);

                var scaledLength = noteLength.Multiply(ratio);
                note.Length = LengthConverter.ConvertFrom(scaledLength, note.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"><paramref name="notes"/> is null. -or-
        /// <paramref name="length"/> is null. -or- <paramref name="tempoMap"/> is null.</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);
        }