/// <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>
        /// Sets time and length of the specified chord.
        /// </summary>
        /// <param name="chord">Chord to set time and length to.</param>
        /// <param name="time">Time to set to <paramref name="chord"/>.</param>
        /// <param name="length">Length to set to <paramref name="chord"/>.</param>
        /// <param name="tempoMap">Tempo map that will be used for time and length conversion.</param>
        /// <returns>An input <paramref name="chord"/> with new time and length.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="chord"/> is null. -or-
        /// <paramref name="time"/> is null. -or- <paramref name="length"/> is null. -or-
        /// <paramref name="tempoMap"/> is null.</exception>
        public static Chord SetTimeAndLength(this Chord chord, ITimeSpan time, ITimeSpan length, TempoMap tempoMap)
        {
            ThrowIfArgument.IsNull(nameof(chord), chord);
            ThrowIfArgument.IsNull(nameof(time), time);
            ThrowIfArgument.IsNull(nameof(length), length);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            chord.Time   = TimeConverter.ConvertFrom(time, tempoMap);
            chord.Length = LengthConverter.ConvertFrom(length, chord.Time, tempoMap);
            return(chord);
        }
示例#3
0
        /// <summary>
        /// Sets time and length of the specified note.
        /// </summary>
        /// <param name="note">Note to set time and length to.</param>
        /// <param name="time">Time to set to <paramref name="note"/>.</param>
        /// <param name="length">Length to set to <paramref name="note"/>.</param>
        /// <param name="tempoMap">Tempo map that will be used for time and length conversion.</param>
        /// <returns>An input <paramref name="note"/> with new time and length.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="note"/> is null. -or-
        /// <paramref name="time"/> is null. -or- <paramref name="length"/> is null. -or-
        /// <paramref name="tempoMap"/> is null.</exception>
        public static Note SetTimeAndLength(this Note note, ITimeSpan time, ITimeSpan length, TempoMap tempoMap)
        {
            ThrowIfArgument.IsNull(nameof(note), note);
            ThrowIfArgument.IsNull(nameof(time), time);
            ThrowIfArgument.IsNull(nameof(length), length);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            note.Time   = TimeConverter.ConvertFrom(time, tempoMap);
            note.Length = LengthConverter.ConvertFrom(length, note.Time, tempoMap);
            return(note);
        }
示例#4
0
        public PatternActionResult Invoke(long time, PatternContext context)
        {
            context.SaveTime(time);

            var chordLength = LengthConverter.ConvertFrom(Length, time, context.TempoMap);

            return(new PatternActionResult(time + chordLength,
                                           NoteDefinitions.Select(d => new Note(d.NoteNumber, chordLength, time)
            {
                Channel = context.Channel,
                Velocity = Velocity
            })));
        }
示例#5
0
        public PatternActionResult Invoke(long time, PatternContext context)
        {
            context.SaveTime(time);

            var noteLength = LengthConverter.ConvertFrom(Length, time, context.TempoMap);

            var note = new Note(Note.NoteNumber, noteLength, time)
            {
                Channel  = context.Channel,
                Velocity = Velocity
            };

            return(new PatternActionResult(time + noteLength, new[] { note }));
        }
        private static void ResizeNotesByRatio(IEnumerable <Note> notes,
                                               double ratio,
                                               TimeSpanType distanceCalculationType,
                                               TempoMap tempoMap,
                                               ITimeSpan startTime)
        {
            foreach (var note in notes)
            {
                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);
            }
        }
示例#7
0
        private static long ConvertFromTimeLength(MathTimeSpan mathTimeSpan, long time, TempoMap tempoMap)
        {
            var convertedTimeSpan1 = TimeConverter.ConvertFrom(mathTimeSpan.TimeSpan1, tempoMap);

            switch (mathTimeSpan.Operation)
            {
            case MathOperation.Add:
                return(convertedTimeSpan1 + LengthConverter.ConvertFrom(mathTimeSpan.TimeSpan2,
                                                                        convertedTimeSpan1,
                                                                        tempoMap));

            case MathOperation.Subtract:
                return(convertedTimeSpan1 - LengthConverter.ConvertFrom(mathTimeSpan.TimeSpan2,
                                                                        convertedTimeSpan1,
                                                                        tempoMap.Flip(convertedTimeSpan1)));

            default:
                throw new ArgumentException($"{mathTimeSpan.Operation} is not supported by the converter.", nameof(mathTimeSpan));
            }
        }
示例#8
0
        /// <summary>
        /// Gets points in time of the current grid.
        /// </summary>
        /// <param name="tempoMap">Tempo map used to get grid's times.</param>
        /// <returns>Collection of points in time of the current grid.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception>
        public IEnumerable <long> GetTimes(TempoMap tempoMap)
        {
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            if (!Steps.Any())
            {
                yield break;
            }

            var time = TimeConverter.ConvertFrom(Start, tempoMap);

            yield return(time);

            while (true)
            {
                foreach (var step in Steps)
                {
                    time += LengthConverter.ConvertFrom(step, time, tempoMap);
                    yield return(time);
                }
            }
        }