/// <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); }
/// <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); }
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 }))); }
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); } }
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)); } }
/// <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); } } }