private static TempoMap GenerateComplexTempoMap() { // 4/4 5/8 5/16 5/8 // |----+----+----+----|----+----+----+----|--+--+--+--+--|-+-+-+-+-|-+-+-+-+-|-+-+-+-+-|--+--+--+--+--| // 0 1 2 3 4 5 6 7 var steps = new[] { Tuple.Create(2 * MusicalTimeSpan.Whole, new TimeSignature(5, 8)), Tuple.Create(5 * MusicalTimeSpan.Eighth, new TimeSignature(5, 16)), Tuple.Create(15 * MusicalTimeSpan.Sixteenth, new TimeSignature(5, 8)), }; using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(TicksPerQuarterNote))) { var time = new MusicalTimeSpan(); foreach (var step in steps) { time += step.Item1; tempoMapManager.SetTimeSignature(time, step.Item2); } tempoMapManager.SetTempo(new MetricTimeSpan(0, 0, 10), Tempo.FromMillisecondsPerQuarterNote(300)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 1, 30), Tempo.FromMillisecondsPerQuarterNote(600)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 1, 31), Tempo.FromMillisecondsPerQuarterNote(640)); return(tempoMapManager.TempoMap); } }
private static void TestTimedEventsWithExactOrder( Pattern pattern, ICollection <TimedEventInfo> expectedTimedEventsInfos, params Tuple <long, Tempo>[] tempoChanges) { TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, Channel); var expectedTimedEvents = expectedTimedEventsInfos.Select(i => new TimedEvent(i.Event, TimeConverter.ConvertFrom(i.Time ?? new MidiTimeSpan(), tempoMap))); var actualTimedEvents = midiFile.GetTimedEvents(); Assert.IsTrue(TimedEventEquality.AreEqual(expectedTimedEvents, actualTimedEvents, false), "Events have invalid order."); }
public void GetTimeSignatureChanges_MultipleChanges() { var numerator1 = 2; var denominator1 = 16; var time1 = 1000; var numerator2 = 3; var denominator2 = 8; var time2 = 1500; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTimeSignature(time2, new TimeSignature(numerator2, denominator2)); tempoMapManager.SetTimeSignature(time1, new TimeSignature(numerator1, denominator1)); var tempoMap = tempoMapManager.TempoMap; var changes = tempoMap.GetTimeSignatureChanges(); Assert.AreEqual(2, changes.Count(), "Count of time signature changes is invalid."); var change1 = changes.First(); Assert.AreEqual(time1, change1.Time, "Time of first change is invalid."); Assert.AreEqual(new TimeSignature(numerator1, denominator1), change1.Value, "Time signature of first change is invalid."); var change2 = changes.Last(); Assert.AreEqual(time2, change2.Time, "Time of second change is invalid."); Assert.AreEqual(new TimeSignature(numerator2, denominator2), change2.Value, "Time signature of second change is invalid."); } }
private static MidiFile TestNotes(Pattern pattern, ICollection <NoteInfo> expectedNotesInfos, params Tuple <long, Tempo>[] tempoChanges) { var channel = (FourBitNumber)2; TempoMap tempoMap = null; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, channel); var expectedNotes = expectedNotesInfos.Select(i => { var expectedTime = TimeConverter.ConvertFrom(i.Time ?? new MetricTime(), tempoMap); var expectedLength = LengthConverter.ConvertFrom(i.Length, expectedTime, tempoMap); return(new Note(i.NoteNumber, expectedLength, expectedTime) { Velocity = i.Velocity, Channel = channel }); }); Assert.IsTrue(NoteEquality.Equals(expectedNotes, midiFile.GetNotes())); return(midiFile); }
private static MidiFile TestTimedEvents(Pattern pattern, ICollection <TimedEventInfo> expectedTimedEventsInfos, params Tuple <long, Tempo>[] tempoChanges) { var channel = (FourBitNumber)2; TempoMap tempoMap = null; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, channel); var expectedTimedEvents = expectedTimedEventsInfos.Select(i => new TimedEvent(i.Event, TimeConverter.ConvertFrom(i.Time ?? new MetricTimeSpan(), tempoMap))); var actualTimedEvents = midiFile.GetTimedEvents(); Assert.IsTrue(expectedTimedEvents.All(expected => actualTimedEvents.Any(actual => TimedEventEquality.Equals(expected, actual)))); return(midiFile); }
private static void TestTimedEvents( Pattern pattern, ICollection <TimedEventInfo> expectedTimedEventsInfos, params Tuple <long, Tempo>[] tempoChanges) { TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, Channel); var expectedTimedEvents = expectedTimedEventsInfos.Select(i => new TimedEvent(i.Event, TimeConverter.ConvertFrom(i.Time ?? new MidiTimeSpan(), tempoMap))); var actualTimedEvents = midiFile.GetTimedEvents(); foreach (var expectedEvent in expectedTimedEvents) { Assert.IsTrue(actualTimedEvents.Any(actual => TimedEventEquality.AreEqual(expectedEvent, actual, false)), $"There are no event: {expectedEvent}"); } }
public void Conversion_Musical_Musical_Subtract_TimeSignatureChanged() { // // 4/4 1/2 3/4 // |--------|--------|----|------| // 0 1 2 < 3 < 4 // <-----< // // We are moving from 3 bars and 2 beats by 3 quarter lengths, // target time is 2 bars and 0.5 beats (one quarter) TempoMap tempoMap = null; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTimeSignature(new MusicalTime(2, 0), new TimeSignature(1, 2)); tempoMapManager.SetTimeSignature(new MusicalTime(3, 0), new TimeSignature(3, 4)); tempoMap = tempoMapManager.TempoMap; } var mathTime = new MathTime(new MusicalTime(3, 2), new MusicalLength(3 * MusicalFraction.Quarter), MathOperation.Subtract); Assert.AreEqual(TimeConverter.ConvertFrom(new MusicalTime(2, 0, MusicalFraction.Quarter), tempoMap), TimeConverter.ConvertFrom(mathTime, tempoMap)); }
private static TempoMap GetTempoMap(IEnumerable <TimedMidiEvent> timedMidiEvents, TimeDivision timeDivision) { using (var tempoMapManager = new TempoMapManager(timeDivision)) { var setTempoEvents = timedMidiEvents.Where(e => e.Event is SetTempoEvent) .OrderBy(e => e.Time, new TimeSpanComparer()); foreach (var timedMidiEvent in setTempoEvents) { var setTempoEvent = (SetTempoEvent)timedMidiEvent.Event; tempoMapManager.SetTempo(timedMidiEvent.Time, new Tempo(setTempoEvent.MicrosecondsPerQuarterNote)); } var timeSignatureEvents = timedMidiEvents.Where(e => e.Event is TimeSignatureEvent) .OrderBy(e => e.Time, new TimeSpanComparer()); foreach (var timedMidiEvent in timeSignatureEvents) { var timeSignatureEvent = (TimeSignatureEvent)timedMidiEvent.Event; tempoMapManager.SetTimeSignature(timedMidiEvent.Time, new TimeSignature(timeSignatureEvent.Numerator, timeSignatureEvent.Denominator)); } return(tempoMapManager.TempoMap); } }
public static void TestTimedEvents( Pattern pattern, ICollection <TimedEventInfo> expectedTimedEventsInfos, params Tuple <long, Tempo>[] tempoChanges) { TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, Channel); var expectedTimedEvents = expectedTimedEventsInfos.Select(i => new TimedEvent(i.Event, TimeConverter.ConvertFrom(i.Time ?? new MidiTimeSpan(), tempoMap))); var actualTimedEvents = midiFile.GetTimedEvents(); MidiAsserts.AreEqual( expectedTimedEvents, actualTimedEvents.Where(e => expectedTimedEvents.Any(ee => ee.Event.EventType == e.Event.EventType)), false, 0, "Events are invalid."); }
public void GetTempoChanges_MultipleChanges() { var microsecondsPerQuarterNote1 = 100000; var time1 = 1000; var microsecondsPerQuarterNote2 = 700000; var time2 = 1500; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(time2, new Tempo(microsecondsPerQuarterNote2)); tempoMapManager.SetTempo(time1, new Tempo(microsecondsPerQuarterNote1)); var tempoMap = tempoMapManager.TempoMap; var changes = tempoMap.GetTempoChanges(); Assert.AreEqual(2, changes.Count(), "Count of tempo changes is invalid."); var change1 = changes.First(); Assert.AreEqual(time1, change1.Time, "Time of first change is invalid."); Assert.AreEqual(new Tempo(microsecondsPerQuarterNote1), change1.Value, "Tempo of first change is invalid."); var change2 = changes.Last(); Assert.AreEqual(time2, change2.Time, "Time of second change is invalid."); Assert.AreEqual(new Tempo(microsecondsPerQuarterNote2), change2.Value, "Tempo of second change is invalid."); } }
public void ConvertCsvToMidiFile_SingleTrackChunk_MetricTimes(MidiFileCsvLayout layout, bool orderEvents, string[] csvLines) { if (!orderEvents) { var tmp = csvLines[2]; csvLines[2] = csvLines[5]; csvLines[5] = tmp; } var midiFile = ConvertCsvToMidiFile(layout, TimeSpanType.Metric, csvLines); TempoMap expectedTempoMap; using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(500))) { tempoMapManager.SetTempo(new MetricTimeSpan(0, 1, 3), new Tempo(300000)); expectedTempoMap = tempoMapManager.TempoMap; } var expectedEvents = new[] { new TimeAndMidiEvent(new MetricTimeSpan(), new NoteOnEvent((SevenBitNumber)50, (SevenBitNumber)120) { Channel = (FourBitNumber)10 }), new TimeAndMidiEvent(new MetricTimeSpan(), new TextEvent("Test")), new TimeAndMidiEvent(new MetricTimeSpan(0, 1, 0), new NoteOnEvent((SevenBitNumber)50, (SevenBitNumber)110) { Channel = (FourBitNumber)7 }), new TimeAndMidiEvent(new MetricTimeSpan(0, 1, 3), new SetTempoEvent(300000)), new TimeAndMidiEvent(new MetricTimeSpan(0, 1, 10), new NoteOffEvent((SevenBitNumber)50, (SevenBitNumber)70) { Channel = (FourBitNumber)10 }), new TimeAndMidiEvent(new MetricTimeSpan(0, 10, 3), new NoteOffEvent((SevenBitNumber)50, (SevenBitNumber)80) { Channel = (FourBitNumber)7 }) } .Select(te => new TimedEvent(te.Event, TimeConverter.ConvertFrom(te.Time, expectedTempoMap))) .ToArray(); Assert.AreEqual(1, midiFile.GetTrackChunks().Count(), "Track chunks count is invalid."); CollectionAssert.AreEqual(midiFile.GetTempoMap().GetTempoChanges(), expectedTempoMap.GetTempoChanges(), "Invalid tempo map."); Assert.AreEqual(new TicksPerQuarterNoteTimeDivision(500), midiFile.TimeDivision, "Invalid time division."); Assert.IsTrue(TimedEventEquality.AreEqual(expectedEvents, midiFile.GetTimedEvents(), false), "Invalid events."); }
private static TempoMap GetTempoMap() { using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(new MetricTimeSpan(0, 0, 1), Tempo.FromBeatsPerMinute(60)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 0, 10), Tempo.FromBeatsPerMinute(150)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 0, 50), Tempo.FromBeatsPerMinute(100)); return(tempoMapManager.TempoMap); } }
private static TempoMap GenerateDefaultTempoMap() { // 4/4 // |----+----+----+----|----+----+----+----|----+----+----+----| // 0 1 2 3 using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(TicksPerQuarterNote))) { return(tempoMapManager.TempoMap); } }
public void Manage_New_WithTimeDivision() { using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(100))) { var tempoMap = tempoMapManager.TempoMap; Assert.AreEqual(100, ((TicksPerQuarterNoteTimeDivision)tempoMap.TimeDivision).TicksPerQuarterNote); Assert.IsFalse(tempoMap.GetTempoChanges().Any()); Assert.IsFalse(tempoMap.GetTimeSignatureChanges().Any()); } }
public void Manage_New_WithoutTimeDivision() { using (var tempoMapManager = new TempoMapManager()) { var tempoMap = tempoMapManager.TempoMap; Assert.AreEqual(TicksPerQuarterNoteTimeDivision.DefaultTicksPerQuarterNote, ((TicksPerQuarterNoteTimeDivision)tempoMap.TimeDivision).TicksPerQuarterNote); Assert.IsFalse(tempoMap.Tempo.Values.Any()); Assert.IsFalse(tempoMap.TimeSignature.Values.Any()); } }
public void GetTempoAtTime_NonDefaultTempoMap_SingleChangeAtMiddle_GetAfterChange() { var microsecondsPerQuarterNote = 100000; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(1000, new Tempo(microsecondsPerQuarterNote)); var tempoMap = tempoMapManager.TempoMap; var tempo = tempoMap.GetTempoAtTime(new MidiTimeSpan(1500)); Assert.AreEqual(new Tempo(microsecondsPerQuarterNote), tempo, "Tempo is invalid."); } }
public void SpawnNotes() { if (midiFile == null) { throw new Exception("No midifile loaded, use LoadMidiFile() to load"); } tempoMapManager = midiFile.ManageTempoMap(); var tempomap = tempoMapManager.TempoMap; Debug.Log(tempomap.TimeDivision); tempomap.TimeSignature.AtTime(0); Debug.Log(tempomap.Tempo.AtTime(0)); SpawnNotesDropDown(midiFile.GetNotes().ToList()); }
public void GetTimeSignatureAtTime_NonDefaultTempoMap_SingleChangeAtMiddle_GetAfterChange() { var numerator = 1; var denominator = 16; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTimeSignature(1000, new TimeSignature(numerator, denominator)); var tempoMap = tempoMapManager.TempoMap; var timeSignature = tempoMap.GetTimeSignatureAtTime(new MidiTimeSpan(1500)); Assert.AreEqual(new TimeSignature(numerator, denominator), timeSignature, "Time signature is invalid."); } }
public void GetTempoAtTime_NonDefaultTempoMap_MultipleChangesAtMiddle_GetAtSecondChange() { var microsecondsPerQuarterNote1 = 100000; var microsecondsPerQuarterNote2 = 700000; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(100, new Tempo(microsecondsPerQuarterNote1)); tempoMapManager.SetTempo(1000, new Tempo(microsecondsPerQuarterNote2)); var tempoMap = tempoMapManager.TempoMap; var tempo = tempoMap.GetTempoAtTime(new MidiTimeSpan(1000)); Assert.AreEqual(new Tempo(microsecondsPerQuarterNote2), tempo, "Tempo is invalid."); } }
public void GetBeatLength_ChangedTimeSignature(long bars, int timeSignatureNumerator, int timeSignatureDenominator, bool changeOnEdge) { const short ticksPerQuarterNote = 100; TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(ticksPerQuarterNote))) { tempoMapManager.SetTimeSignature(new BarBeatTicksTimeSpan(changeOnEdge ? bars : bars - 1), new TimeSignature(timeSignatureNumerator, timeSignatureDenominator)); tempoMap = tempoMapManager.TempoMap; } var length = BarBeatUtilities.GetBeatLength(bars, tempoMap); Assert.AreEqual(ticksPerQuarterNote * 4 / timeSignatureDenominator, length, "Beat length is invalid."); }
public static MidiFile TestNotes(Pattern pattern, ICollection <NoteInfo> expectedNotesInfos, params Tuple <long, Tempo>[] tempoChanges) { TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, Channel); var expectedNotes = expectedNotesInfos.Select(i => { var expectedTime = TimeConverter.ConvertFrom(i.Time ?? new MetricTimeSpan(), tempoMap); var expectedLength = LengthConverter.ConvertFrom(i.Length, expectedTime, tempoMap); return(new DryWetMidi.Interaction.Note(i.NoteNumber, expectedLength, expectedTime) { Velocity = i.Velocity, Channel = Channel }); }) .OrderBy(n => n.Time) .ToArray(); var actualNotes = midiFile.GetNotes().ToArray(); Assert.AreEqual(expectedNotes.Length, actualNotes.Length, "Notes count is invalid."); var j = 0; foreach (var expectedActual in expectedNotes.Zip(actualNotes, (e, a) => new { Expected = e, Actual = a })) { var expectedNote = expectedActual.Expected; var actualNote = expectedActual.Actual; Assert.IsTrue(NoteEquality.AreEqual(expectedNote, actualNote), $"Note {j} is invalid. Expected: {expectedNote}; actual: {actualNote}."); j++; } return(midiFile); }
public void ReplaceTempoMap_ByDefault() { using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(100, new Tempo(10)); tempoMapManager.SetTempo(300, new Tempo(100)); tempoMapManager.ReplaceTempoMap(TempoMap.Default); var tempoMap = tempoMapManager.TempoMap; Assert.AreEqual(TicksPerQuarterNoteTimeDivision.DefaultTicksPerQuarterNote, ((TicksPerQuarterNoteTimeDivision)tempoMap.TimeDivision).TicksPerQuarterNote); Assert.IsFalse(tempoMap.Tempo.Values.Any()); Assert.IsFalse(tempoMap.TimeSignature.Values.Any()); } }
public void Conversion_Metric_Metric_Subtract_TempoChanged() { TempoMap tempoMap = null; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(new MetricTime(0, 1, 20), new Tempo(20000)); tempoMap = tempoMapManager.TempoMap; } var mathTime = new MathTime(new MetricTime(0, 1, 30), new MetricLength(0, 1, 0), MathOperation.Subtract); Assert.AreEqual(TimeConverter.ConvertFrom(new MetricTime(0, 0, 30), tempoMap), TimeConverter.ConvertFrom(mathTime, tempoMap)); }
private static TempoMap GenerateSimpleTempoMap() { // 4/4 5/8 5/16 // |----+----+----+----|--+--+--+--+--|-+-+-+-+-| // 0 1 2 3 using (var tempoMapManager = new TempoMapManager(new TicksPerQuarterNoteTimeDivision(TicksPerQuarterNote))) { tempoMapManager.SetTimeSignature(MusicalTimeSpan.Whole, new TimeSignature(5, 8)); tempoMapManager.SetTimeSignature(MusicalTimeSpan.Whole + 5 * MusicalTimeSpan.Eighth, new TimeSignature(5, 16)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 0, 10), Tempo.FromMillisecondsPerQuarterNote(300)); tempoMapManager.SetTempo(new MetricTimeSpan(0, 1, 30), Tempo.FromMillisecondsPerQuarterNote(600)); return(tempoMapManager.TempoMap); } }
public void GetTimeSignatureAtTime_NonDefaultTempoMap_MultipleChangesAtMiddle_GetAfterSecondChange() { var numerator1 = 1; var denominator1 = 16; var numerator2 = 3; var denominator2 = 8; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTimeSignature(100, new TimeSignature(numerator1, denominator1)); tempoMapManager.SetTimeSignature(1000, new TimeSignature(numerator2, denominator2)); var tempoMap = tempoMapManager.TempoMap; var timeSignature = tempoMap.GetTimeSignatureAtTime(new MidiTimeSpan(5000)); Assert.AreEqual(new TimeSignature(numerator2, denominator2), timeSignature, "Time signature is invalid."); } }
public void GetTempoChanges_SingleChange_AtMiddle() { var microsecondsPerQuarterNote = 100000; var time = 1000; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTempo(time, new Tempo(microsecondsPerQuarterNote)); var tempoMap = tempoMapManager.TempoMap; var changes = tempoMap.GetTempoChanges(); Assert.AreEqual(1, changes.Count(), "Count of tempo changes is invalid."); var change = changes.First(); Assert.AreEqual(time, change.Time, "Time of change is invalid."); Assert.AreEqual(new Tempo(microsecondsPerQuarterNote), change.Value, "Tempo of change is invalid."); } }
public void GetTimeSignatureChanges_SingleChange_AtMiddle() { var numerator = 2; var denominator = 16; var time = 1000; using (var tempoMapManager = new TempoMapManager()) { tempoMapManager.SetTimeSignature(time, new TimeSignature(numerator, denominator)); var tempoMap = tempoMapManager.TempoMap; var changes = tempoMap.GetTimeSignatureChanges(); Assert.AreEqual(1, changes.Count(), "Count of time signature changes is invalid."); var change = changes.First(); Assert.AreEqual(time, change.Time, "Time of change is invalid."); Assert.AreEqual(new TimeSignature(numerator, denominator), change.Value, "Time signature of change is invalid."); } }
private static TempoMap GetTempoMap() { var timeSignatureChangeOffset = 5 * TimeOffset - 1; var maxTime = Math.Max((TimesCount - 1) * TimeOffset, (TimesCount - 1) * TimeOffset + Length); bool firstTimeSignature = true; using (var tempoMapManager = new TempoMapManager()) { var time = 0L; while (time < maxTime) { tempoMapManager.SetTimeSignature(time, firstTimeSignature ? FirstTimeSignature : SecondTimeSignature); firstTimeSignature = !firstTimeSignature; time += timeSignatureChangeOffset; } return(tempoMapManager.TempoMap); } }
private static TempoMap GetTempoMap() { var changeTempoOffset = 5 * TimeOffset - 1; var maxTime = Math.Max((TimesCount - 1) * TimeOffset, (TimesCount - 1) * TimeOffset + Length); bool firstTempo = true; using (var tempoMapManager = new TempoMapManager()) { var time = 0L; while (time < maxTime) { tempoMapManager.SetTempo(time, firstTempo ? FirstTempo : SecondTempo); firstTempo = !firstTempo; time += changeTempoOffset; } return(tempoMapManager.TempoMap); } }
public static MidiFile TestNotes(Pattern pattern, ICollection <NoteInfo> expectedNotesInfos, params Tuple <long, Tempo>[] tempoChanges) { TempoMap tempoMap; using (var tempoMapManager = new TempoMapManager()) { foreach (var tempoChange in tempoChanges) { tempoMapManager.SetTempo(tempoChange.Item1, tempoChange.Item2); } tempoMap = tempoMapManager.TempoMap; } var midiFile = pattern.ToFile(tempoMap, Channel); var expectedNotes = expectedNotesInfos.Select(i => { var expectedTime = TimeConverter.ConvertFrom(i.Time ?? new MetricTimeSpan(), tempoMap); var expectedLength = LengthConverter.ConvertFrom(i.Length, expectedTime, tempoMap); return(new DryWetMidi.Interaction.Note(i.NoteNumber, expectedLength, expectedTime) { Velocity = i.Velocity, Channel = Channel }); }) .OrderBy(n => n.Time) .ToArray(); var actualNotes = midiFile.GetNotes().ToArray(); MidiAsserts.AreEqual(expectedNotes, actualNotes, "Notes are invalid."); return(midiFile); }