예제 #1
0
        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));
        }
예제 #2
0
        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);
        }
예제 #3
0
 public void FromTimeSpan_Time()
 {
     foreach (var timeSpan in _timeSpanTimes)
     {
         var midiTime = TimeConverter.ConvertFrom(timeSpan, TempoMap);
     }
 }
예제 #4
0
        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);
        }
예제 #5
0
        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}");
            }
        }
예제 #6
0
 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);
     }
 }
예제 #7
0
 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.");
            }
        }
예제 #9
0
        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}.");
        }
예제 #10
0
        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;
 }
예제 #13
0
        public IEnumerable <MidiEvent> GetEventsAtTime(TimeSpan time)
        {
            var convertedTime = TimeConverter.ConvertFrom((MetricTimeSpan)time, _tempoMap);

            return(GetControlChangeEventsAtTime(convertedTime)
                   .Concat(GetProgramChangeEventsAtTime(convertedTime))
                   .Concat(GetPitchBendEventsAtTime(convertedTime)));
        }
예제 #14
0
        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)));
        }
예제 #15
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.");
                    }
                }
            }
        }
예제 #17
0
        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));
        }
예제 #18
0
 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)
     });
 }
예제 #19
0
        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));
        }
예제 #20
0
        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()));
        }
예제 #22
0
        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);
                }
        }
예제 #24
0
        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));
        }
예제 #25
0
        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);
        }
예제 #26
0
        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);
        }
예제 #28
0
        /// <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();
            }
        }
예제 #29
0
        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));
        }
예제 #30
0
        /// <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();
            }
        }