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 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); }
public void FromTimeSpan_Time() { foreach (var timeSpan in _timeSpanTimes) { var midiTime = TimeConverter.ConvertFrom(timeSpan, TempoMap); } }
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}"); } }
private async void StartPlayingMidi() { if (playback != null) { if (playback.IsRunning) { return; } } if (midiChannels == null) { MessageBox.Show("MIDI file was not splitted by channels."); return; } try { if (!playback.IsRunning && currentlyPlayingDevice != null) { playback.InterruptNotesOnStop = true; playback.Start(); PlaybackCurrentTimeWatcher.Instance.Start(); while (playback.IsRunning) { Thread.Sleep(1000); songPercentPlayed = (float)Convert.ToSingle(TimeConverter.ConvertFrom(playback.GetCurrentTime(TimeSpanType.Midi), playback.TempoMap)) / (float)Convert.ToSingle(TimeConverter.ConvertFrom(playback.GetDuration(TimeSpanType.Midi), playback.TempoMap) / 100f); OnPropertyChange("SongPercentPlayed"); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
public PatternActionResult Invoke(long time, PatternContext context) { context.SaveTime(time); return(new PatternActionResult(Time != null ? TimeConverter.ConvertFrom(Time, context.TempoMap) : context.RestoreTime())); }
private void Randomize(LengthedObjectTarget target, IEnumerable <TObject> actualObjects, IBounds bounds, IEnumerable <TimeBounds> expectedBounds, TempoMap tempoMap) { Randomizer.Randomize(actualObjects, bounds, tempoMap, new TSettings { RandomizingTarget = target }); var objectsBounds = actualObjects.Zip(expectedBounds, (o, b) => new { Object = o, Bounds = b }); foreach (var objectBounds in objectsBounds) { var time = objectBounds.Object?.Time; var timeBounds = objectBounds.Bounds; if (time == null) { Assert.IsNull(timeBounds.MinTime, "Min time is not null for null object."); Assert.IsNull(timeBounds.MaxTime, "Max time is not null for null object."); continue; } var minTime = TimeConverter.ConvertFrom(timeBounds.MinTime, tempoMap); var maxTime = TimeConverter.ConvertFrom(timeBounds.MaxTime, tempoMap); Assert.IsTrue(time >= minTime && time <= maxTime, $"Object's time {time} is not in {timeBounds}/[{minTime}; {maxTime}] range."); } }
private void SplitByGrid_OneStep_SinglePart(ITimeSpan gridStart, ITimeSpan step, TempoMap tempoMap) { var gridSteps = new[] { step }; var firstTime = TimeConverter.ConvertFrom(gridStart, tempoMap); long secondTime = firstTime; for (int i = 0; i < 5; i++) { secondTime += LengthConverter.ConvertFrom(step, secondTime, tempoMap); } var inputObjects = new[] { ObjectMethods.Create(firstTime, LengthConverter.ConvertFrom(step, firstTime, tempoMap)), ObjectMethods.Create(secondTime, LengthConverter.ConvertFrom(step, secondTime, tempoMap)) }; var data = SplitByGrid_ClonesExpected(inputObjects, gridStart, gridSteps, tempoMap); var stepType = TimeSpanTypes[step.GetType()]; var partLength = data.ActualObjects.First().LengthAs(stepType, tempoMap); Assert.IsTrue(data.ActualObjects.All(o => o.LengthAs(stepType, tempoMap).Equals(partLength)), $"Objects have different length measured as {stepType}."); }
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."); }
private SplittedLengthedObject <TObject> SplitObjectAtDistance(TObject obj, ITimeSpan distance, LengthedObjectTarget from, TempoMap tempoMap) { var time = from == LengthedObjectTarget.Start ? ((MidiTimeSpan)obj.Time).Add(distance, TimeSpanMode.TimeLength) : ((MidiTimeSpan)(obj.Time + obj.Length)).Subtract(distance, TimeSpanMode.TimeLength); return(SplitObject(obj, TimeConverter.ConvertFrom(time, tempoMap))); }
public void CopyChannelSelection(OnMidiLoadedMessage msg) { ChannelTitles = new ObservableCollection <string>(msg.midiChannelsTitles); ChannelTitles.RemoveAt(0); SelectedChannel = ChannelTitles[0]; EndGenerationTime = TimeConverter.ConvertFrom(msg.playback.GetDuration(TimeSpanType.Midi), msg.playback.TempoMap); IsEditingActive = true; }
public IEnumerable <MidiEvent> GetEventsAtTime(TimeSpan time) { var convertedTime = TimeConverter.ConvertFrom((MetricTimeSpan)time, _tempoMap); return(GetControlChangeEventsAtTime(convertedTime) .Concat(GetProgramChangeEventsAtTime(convertedTime)) .Concat(GetPitchBendEventsAtTime(convertedTime))); }
public override PatternActionResult Invoke(long time, PatternContext context) { var tempoMap = context.TempoMap; context.SaveTime(time); var convertedTime = TimeConverter.ConvertFrom(((MidiTimeSpan)time).Subtract(Step, TimeSpanMode.TimeLength), tempoMap); return(new PatternActionResult(Math.Max(convertedTime, 0))); }
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."); }
public void SaveRecordingToFile() { var tempoMap = TempoMap.Default; var eventsToSend = new[] { new EventToSend(new NoteOnEvent(), TimeSpan.Zero), new EventToSend(new NoteOffEvent(), TimeSpan.FromMilliseconds(500)), new EventToSend(new ProgramChangeEvent((SevenBitNumber)40), TimeSpan.FromSeconds(5)), new EventToSend(new ActiveSensingEvent(), TimeSpan.FromMilliseconds(100)), new EventToSend(new ProgramChangeEvent((SevenBitNumber)50), TimeSpan.FromMilliseconds(500)), }; using (var outputDevice = OutputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)) { SendReceiveUtilities.WarmUpDevice(outputDevice); using (var inputDevice = InputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)) { var receivedEventsNumber = 0; inputDevice.StartEventsListening(); inputDevice.EventReceived += (_, __) => receivedEventsNumber++; using (var recording = new Recording(tempoMap, inputDevice)) { var sendingThread = new Thread(() => { SendReceiveUtilities.SendEvents(eventsToSend, outputDevice); }); recording.Start(); sendingThread.Start(); SpinWait.SpinUntil(() => !sendingThread.IsAlive && receivedEventsNumber == eventsToSend.Length); recording.Stop(); var midiFile = recording.ToFile(); var timedEvents = midiFile.GetTimedEvents(); var expectedEvents = new[] { new TimedEvent(new NoteOnEvent(), TimeConverter.ConvertFrom((MetricTimeSpan)TimeSpan.Zero, tempoMap)), new TimedEvent(new NoteOffEvent(), TimeConverter.ConvertFrom((MetricTimeSpan)TimeSpan.FromMilliseconds(500), tempoMap)), new TimedEvent(new ProgramChangeEvent((SevenBitNumber)40), TimeConverter.ConvertFrom((MetricTimeSpan)TimeSpan.FromSeconds(5.5), tempoMap)), new TimedEvent(new ProgramChangeEvent((SevenBitNumber)50), TimeConverter.ConvertFrom((MetricTimeSpan)TimeSpan.FromSeconds(6.1), tempoMap)) }; Assert.IsTrue( TimedEventEquality.AreEqual(expectedEvents, timedEvents, false, 10), "Timed events saved incorrectly."); } } } }
public void Conversion_Musical_Musical_Subtract() { var tempoMap = TempoMap.Default; var mathTime = new MathTime(new MusicalTime(2, 0), new MusicalLength(MusicalFraction.Quarter), MathOperation.Subtract); Assert.AreEqual(TimeConverter.ConvertFrom(new MusicalTime(7 * MusicalFraction.Quarter), tempoMap), TimeConverter.ConvertFrom(mathTime, tempoMap)); }
public Note GetNote(TempoMap tempoMap) { return(new Note(NoteNumber) { Channel = Channel, Velocity = Velocity, OffVelocity = OffVelocity, Time = TimeConverter.ConvertFrom(Time, tempoMap), Length = LengthConverter.ConvertFrom(Length, Time, tempoMap) }); }
public void Conversion_Metric_Metric_Subtract() { var tempoMap = TempoMap.Default; 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 TimeProcessingInstruction CorrectObjectOnEndQuantizing(TObject obj, long time, TempoMap tempoMap, TSettings settings) { if (settings.FixOppositeEnd) { var startTime = obj.Time; if (time < startTime) { var result = ProcessQuantizingBeyondFixedEnd(ref time, ref startTime, settings.QuantizingBeyondFixedEndPolicy, "End time is going to be beyond the start one."); if (result != null) { return(result); } } LengthSetter.SetObjectLength(obj, time - startTime); } else { var length = obj.LengthAs(settings.LengthType, tempoMap); var newStartTime = settings.LengthType == TimeSpanType.Midi ? time - obj.Length : TimeConverter.ConvertFrom(((MidiTimeSpan)time).Subtract(length, TimeSpanMode.TimeLength), tempoMap); if (newStartTime < 0) { switch (settings.QuantizingBeyondZeroPolicy) { case QuantizingBeyondZeroPolicy.Skip: return(TimeProcessingInstruction.Skip); case QuantizingBeyondZeroPolicy.Abort: throw new InvalidOperationException("Object is going to be moved beyond zero."); case QuantizingBeyondZeroPolicy.FixAtZero: LengthSetter.SetObjectLength(obj, time); break; } } else { LengthSetter.SetObjectLength(obj, LengthConverter.ConvertFrom(length, newStartTime, tempoMap)); } } return(new TimeProcessingInstruction(time)); }
public override PatternActionResult Invoke(long time, PatternContext context) { if (State != PatternActionState.Enabled) { return(PatternActionResult.DoNothing); } if (Time != null) { context.SaveTime(time); } return(new PatternActionResult(Time != null ? TimeConverter.ConvertFrom(Time, context.TempoMap) : context.RestoreTime())); }
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); }
private void CheckPlaybackEvents( int expectedStartedRaised, int expectedStoppedRaised, int expectedFinishedRaised, int expectedRepeatStartedRaised, PlaybackAction setupPlayback, PlaybackAction beforeChecks, PlaybackAction afterChecks) { var started = 0; var stopped = 0; var finished = 0; var repeatStarted = 0; var playbackEvents = new MidiEvent[] { new NoteOnEvent(), new NoteOffEvent { DeltaTime = TimeConverter.ConvertFrom(new MetricTimeSpan(0, 0, 1), TempoMap.Default) } }; using (var outputDevice = OutputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)) using (var playback = new Playback(playbackEvents, TempoMap.Default, outputDevice)) { setupPlayback(null, playback); playback.Started += (sender, args) => started++; playback.Stopped += (sender, args) => stopped++; playback.Finished += (sender, args) => finished++; playback.RepeatStarted += (sender, args) => repeatStarted++; playback.Start(); playback.Stop(); playback.Start(); beforeChecks(null, playback); Assert.IsTrue( SpinWait.SpinUntil(() => started == expectedStartedRaised && stopped == expectedStoppedRaised && finished == expectedFinishedRaised && repeatStarted == expectedRepeatStartedRaised, TimeSpan.FromSeconds(2)), "Playback events are raised invalid number of times."); afterChecks(null, playback); } }
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 void SplitByGrid_MultipleSteps(IEnumerable <TObject> inputObjects, ITimeSpan gridStart, IEnumerable <ITimeSpan> gridSteps, Dictionary <TObject, IEnumerable <TimeAndLength> > expectedParts, TempoMap tempoMap) { var expectedObjects = expectedParts .SelectMany(p => p.Value.Select(tl => CloneAndChangeTimeAndLength( p.Key, TimeConverter.ConvertFrom(tl.Time, tempoMap), LengthConverter.ConvertFrom(tl.Length, tl.Time, tempoMap)))) .ToArray(); var actualObjects = Splitter.SplitByGrid(inputObjects, new SteppedGrid(gridStart, gridSteps), tempoMap).ToArray(); ObjectMethods.AssertCollectionsAreEqual(expectedObjects, actualObjects); }
private static QuantizedTime FindNearestTime(IReadOnlyList <long> grid, long time, TimeSpanType distanceCalculationType, double quantizingLevel, TempoMap tempoMap) { var distanceToGridTime = -1L; var convertedDistanceToGridTime = TimeSpanUtilities.GetMaxTimeSpan(distanceCalculationType); var gridTime = -1L; for (int i = 0; i < grid.Count; i++) { var currentGridTime = grid[i]; var distance = Math.Abs(time - currentGridTime); var convertedDistance = LengthConverter.ConvertTo(distance, distanceCalculationType, Math.Min(time, currentGridTime), tempoMap); if (convertedDistance.CompareTo(convertedDistanceToGridTime) >= 0) { break; } distanceToGridTime = distance; convertedDistanceToGridTime = convertedDistance; gridTime = currentGridTime; } // var shift = convertedDistanceToGridTime.Multiply(quantizingLevel); var convertedTime = TimeConverter.ConvertTo(time, distanceCalculationType, tempoMap); var newTime = TimeConverter.ConvertFrom( gridTime > time ? convertedTime.Add(shift, TimeSpanMode.TimeLength) : convertedTime.Subtract(shift, TimeSpanMode.TimeLength), tempoMap); // return(new QuantizedTime(newTime, gridTime, shift, distanceToGridTime, convertedDistanceToGridTime)); }
private static void CheckWatchCurrentTime( ITimeSpan playbackLength, ITimeSpan pollingInterval, TimeSpanType timeType, ICollection <ITimeSpan> expectedTimes) { var tempoMap = TempoMap.Default; var length = TimeConverter.ConvertFrom(playbackLength, tempoMap); var events = new MidiEvent[] { new NoteOnEvent(), new NoteOffEvent { DeltaTime = length } }; var times = new List <ITimeSpan>(); using (var playback = new Playback(events, tempoMap)) { PlaybackCurrentTimeWatcher.Instance.PollingInterval = TimeConverter.ConvertTo <MetricTimeSpan>(pollingInterval, tempoMap); PlaybackCurrentTimeWatcher.Instance.AddPlayback(playback, timeType); EventHandler <PlaybackCurrentTimeChangedEventArgs> currentTimeChangedHandler = (_, e) => times.Add(e.Times.First().Time); PlaybackCurrentTimeWatcher.Instance.CurrentTimeChanged += currentTimeChangedHandler; playback.Start(); PlaybackCurrentTimeWatcher.Instance.Start(); var timeout = TimeSpan.FromSeconds(30); var playbackFinished = SpinWait.SpinUntil(() => !playback.IsRunning, timeout); Assert.IsTrue(playbackFinished, $"Playback is not finished for {timeout}."); WaitExpectedTimes(expectedTimes, times); PlaybackCurrentTimeWatcher.Instance.Stop(); PlaybackCurrentTimeWatcher.Instance.CurrentTimeChanged -= currentTimeChangedHandler; PlaybackCurrentTimeWatcher.Instance.RemovePlayback(playback); } CheckTimes(expectedTimes, times); }
/// <summary> /// Sets playback position to the specified time from the beginning of the MIDI data. /// </summary> /// <param name="time">Time from the beginning of the MIDI data to set playback position to.</param> /// <exception cref="ArgumentNullException"><paramref name="time"/> is null.</exception> /// <exception cref="ObjectDisposedException">The current <see cref="Playback"/> is disposed.</exception> /// <exception cref="MidiDeviceException">An error occurred on device.</exception> public void MoveToTime(ITimeSpan time) { ThrowIfArgument.IsNull(nameof(time), time); EnsureIsNotDisposed(); if (TimeConverter.ConvertFrom(time, TempoMap) > _durationInTicks) { time = (MetricTimeSpan)_duration; } var isRunning = IsRunning; SetStartTime(time); if (isRunning) { StopStartNotes(); _clock.Start(); } }
private static long CalculateBoundaryTime(long time, ITimeSpan size, MathOperation operation, TempoMap tempoMap) { ITimeSpan boundaryTime = (MidiTimeSpan)time; switch (operation) { case MathOperation.Add: boundaryTime = boundaryTime.Add(size, TimeSpanMode.TimeLength); break; case MathOperation.Subtract: var convertedSize = TimeConverter.ConvertFrom(size, tempoMap); boundaryTime = convertedSize > time ? (MidiTimeSpan)0 : boundaryTime.Subtract(size, TimeSpanMode.TimeLength); break; } return(TimeConverter.ConvertFrom(boundaryTime, tempoMap)); }
/// <summary> /// Sets playback position to the specified time from the beginning of the MIDI data. /// </summary> /// <param name="time">Time from the beginning of the MIDI data to set playback position to.</param> /// <exception cref="ArgumentNullException"><paramref name="time"/> is null.</exception> /// <exception cref="ObjectDisposedException">The current <see cref="Playback"/> is disposed.</exception> /// <exception cref="MidiDeviceException">An error occurred on device.</exception> public void MoveToTime(ITimeSpan time) { ThrowIfArgument.IsNull(nameof(time), time); EnsureIsNotDisposed(); if (TimeConverter.ConvertFrom(time, TempoMap) > _durationInTicks) { time = (MetricTimeSpan)_duration; } var needStart = IsRunning; _clock.ResetInternalTimer(); SetStartTime(time); if (needStart) { _clock.StartInternalTimer(); } }