private void ProcessChords_DetectionSettings_EventsCollection_WithoutPredicate(
            ContainerType containerType,
            ChordDetectionSettings settings,
            ICollection <MidiEvent> midiEvents,
            Action <Chord> action,
            ICollection <MidiEvent> expectedMidiEvents)
        {
            var chordsCount = midiEvents.GetChords(settings).Count;

            switch (containerType)
            {
            case ContainerType.EventsCollection:
            {
                var eventsCollection = new EventsCollection();
                eventsCollection.AddRange(midiEvents);

                Assert.AreEqual(
                    chordsCount,
                    eventsCollection.ProcessChords(action, settings),
                    "Invalid count of processed chords.");

                var expectedEventsCollection = new EventsCollection();
                expectedEventsCollection.AddRange(expectedMidiEvents);
                MidiAsserts.AreEqual(expectedEventsCollection, eventsCollection, true, "Events are invalid.");
                Assert.IsTrue(
                    eventsCollection.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            break;

            case ContainerType.TrackChunk:
            {
                var trackChunk = new TrackChunk(midiEvents);

                Assert.AreEqual(
                    chordsCount,
                    trackChunk.ProcessChords(action, settings),
                    "Invalid count of processed chords.");

                var expectedTrackChunk = new TrackChunk(expectedMidiEvents);
                MidiAsserts.AreEqual(expectedTrackChunk, trackChunk, true, "Events are invalid.");
                Assert.IsTrue(
                    trackChunk.Events.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            break;

            case ContainerType.TrackChunks:
            case ContainerType.File:
            {
                ProcessChords_DetectionSettings_TrackChunks_WithoutPredicate(
                    containerType == ContainerType.File,
                    settings,
                    new[] { midiEvents },
                    action,
                    new[] { expectedMidiEvents });
            }
            break;
            }
        }
Example #2
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="MidiFile"/> by the specified grid.
        /// </summary>
        /// <param name="midiFile"><see cref="MidiFile"/> to split chords in.</param>
        /// <param name="grid">Grid to split chords by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException"><paramref name="grid"/> is <c>null</c>.</exception>
        public static void SplitChordsByGrid(this MidiFile midiFile, IGrid grid, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsNull(nameof(grid), grid);

            var tempoMap = midiFile.GetTempoMap();

            midiFile.GetTrackChunks().SplitChordsByGrid(grid, tempoMap, settings);
        }
Example #3
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="MidiFile"/> by the specified
        /// step so every chord will be split at points equally distanced from each other
        /// starting from the chord's start time.
        /// </summary>
        /// <remarks>
        /// Chords with zero length and chords with length smaller than <paramref name="step"/>
        /// will not be split.
        /// </remarks>
        /// <param name="midiFile"><see cref="MidiFile"/> to split chords in.</param>
        /// <param name="step">Step to split chords by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="midiFile"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="step"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsByStep(this MidiFile midiFile, ITimeSpan step, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsNull(nameof(step), step);

            var tempoMap = midiFile.GetTempoMap();

            midiFile.GetTrackChunks().SplitChordsByStep(step, tempoMap, settings);
        }
        private void GetChords_DetectionSettings_EventsCollection(
            ContainerType containerType,
            ChordDetectionSettings settings,
            ICollection <MidiEvent> midiEvents,
            ICollection <Chord> expectedChords)
        {
            switch (containerType)
            {
            case ContainerType.EventsCollection:
            {
                var eventsCollection = new EventsCollection();
                eventsCollection.AddRange(midiEvents);

                var chords = eventsCollection.GetChords(settings);
                MidiAsserts.AreEqual(expectedChords, chords, "Chords are invalid.");

                var timedObjets = eventsCollection.GetObjects(ObjectType.Chord, new ObjectDetectionSettings {
                        ChordDetectionSettings = settings
                    });
                MidiAsserts.AreEqual(expectedChords, timedObjets, "Chords are invalid from GetObjects.");
            }
            break;

            case ContainerType.TrackChunk:
            {
                var trackChunk = new TrackChunk(midiEvents);

                var chords = trackChunk.GetChords(settings);
                MidiAsserts.AreEqual(expectedChords, chords, "Chords are invalid.");

                var timedObjets = trackChunk.GetObjects(ObjectType.Chord, new ObjectDetectionSettings {
                        ChordDetectionSettings = settings
                    });
                MidiAsserts.AreEqual(expectedChords, timedObjets, "Chords are invalid from GetObjects.");
            }
            break;

            case ContainerType.TrackChunks:
            case ContainerType.File:
            {
                GetChords_DetectionSettings_TrackChunks(
                    containerType == ContainerType.File,
                    settings,
                    new[] { midiEvents },
                    expectedChords);
            }
            break;
            }
        }
        private void GetChords_DetectionSettings_TrackChunks(
            bool wrapToFile,
            ChordDetectionSettings settings,
            ICollection <ICollection <MidiEvent> > midiEvents,
            IEnumerable <Chord> expectedChords)
        {
            IEnumerable <Chord> chords;

            var trackChunks = midiEvents.Select(e => new TrackChunk(e)).ToArray();

            if (wrapToFile)
            {
                chords = new MidiFile(trackChunks).GetChords(settings);
            }
            else
            {
                chords = trackChunks.GetChords(settings);
            }

            MidiAsserts.AreEqual(expectedChords, chords, "Chords are invalid.");

            //

            // TODO: Support events collection indicies in GetObjects
            if (settings.ChordSearchContext == ChordSearchContext.AllEventsCollections)
            {
                IEnumerable <ITimedObject> timedObjects;

                if (wrapToFile)
                {
                    timedObjects = new MidiFile(trackChunks).GetObjects(ObjectType.Chord, new ObjectDetectionSettings {
                        ChordDetectionSettings = settings
                    });
                }
                else
                {
                    timedObjects = trackChunks.GetObjects(ObjectType.Chord, new ObjectDetectionSettings {
                        ChordDetectionSettings = settings
                    });
                }

                MidiAsserts.AreEqual(expectedChords, timedObjects, "Chords are invalid from GetObjects.");
            }
        }
        private void ProcessChords_DetectionSettings_TrackChunks_WithPredicate(
            bool wrapToFile,
            ChordDetectionSettings settings,
            ICollection <ICollection <MidiEvent> > midiEvents,
            Action <Chord> action,
            Predicate <Chord> match,
            ICollection <ICollection <MidiEvent> > expectedMidiEvents,
            int expectedProcessedCount)
        {
            var trackChunks = midiEvents.Select(e => new TrackChunk(e)).ToList();

            if (wrapToFile)
            {
                var midiFile = new MidiFile(trackChunks);

                Assert.AreEqual(
                    expectedProcessedCount,
                    midiFile.ProcessChords(action, match, settings),
                    "Invalid count of processed chords.");

                MidiAsserts.AreEqual(new MidiFile(expectedMidiEvents.Select(e => new TrackChunk(e))), midiFile, false, "Events are invalid.");
                Assert.IsTrue(
                    midiFile.GetTrackChunks().SelectMany(c => c.Events).All(e => midiEvents.SelectMany(ee => ee).Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            else
            {
                Assert.AreEqual(
                    expectedProcessedCount,
                    trackChunks.ProcessChords(action, match, settings),
                    "Invalid count of processed chords.");

                MidiAsserts.AreEqual(expectedMidiEvents.Select(e => new TrackChunk(e)), trackChunks, true, "Events are invalid.");
                Assert.IsTrue(
                    trackChunks.SelectMany(c => c.Events).All(e => midiEvents.SelectMany(ee => ee).Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
        }
Example #7
0
        private void RemoveChords_DetectionSettings_TrackChunks_WithoutPredicate(
            bool wrapToFile,
            ChordDetectionSettings settings,
            ICollection <ICollection <MidiEvent> > midiEvents,
            ICollection <ICollection <MidiEvent> > expectedMidiEvents)
        {
            var trackChunks = midiEvents.Select(e => new TrackChunk(e)).ToList();
            var chordsCount = trackChunks.GetChords(settings).Count;

            if (wrapToFile)
            {
                var midiFile = new MidiFile(trackChunks);

                Assert.AreEqual(
                    chordsCount,
                    midiFile.RemoveChords(settings),
                    "Invalid count of removed chords.");

                MidiAsserts.AreEqual(new MidiFile(expectedMidiEvents.Select(e => new TrackChunk(e))), midiFile, false, "Events are invalid.");
                Assert.IsTrue(
                    midiFile.GetTrackChunks().SelectMany(c => c.Events).All(e => midiEvents.SelectMany(ee => ee).Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            else
            {
                Assert.AreEqual(
                    chordsCount,
                    trackChunks.RemoveChords(settings),
                    "Invalid count of removed chords.");

                MidiAsserts.AreEqual(expectedMidiEvents.Select(e => new TrackChunk(e)), trackChunks, true, "Events are invalid.");
                Assert.IsTrue(
                    trackChunks.SelectMany(c => c.Events).All(e => midiEvents.SelectMany(ee => ee).Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
        }
Example #8
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="TrackChunk"/> by the specified ratio of a
        /// chord's length measuring it from the chord's start or end. For example, 0.5 means splitting
        /// at the center of a chord.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="ratio">Ratio of a chord's length to split by. Valid values are from 0 to 1.</param>
        /// <param name="lengthType">The type a chord's length should be processed according to.</param>
        /// <param name="from">Point of a chord distance should be measured from.</param>
        /// <param name="tempoMap">Tempo map used for distances calculations.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunk"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ratio"/> is out of valid range.</exception>
        /// <exception cref="InvalidEnumArgumentException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="lengthType"/> specified an invalid value.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="from"/> specified an invalid value.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsAtDistance(this TrackChunk trackChunk, double ratio, TimeSpanType lengthType, LengthedObjectTarget from, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsOutOfRange(nameof(ratio),
                                         ratio,
                                         LengthedObjectsSplitter <Chord> .ZeroRatio,
                                         LengthedObjectsSplitter <Chord> .FullLengthRatio,
                                         $"Ratio is out of [{LengthedObjectsSplitter<Chord>.ZeroRatio}; {LengthedObjectsSplitter<Chord>.FullLengthRatio}] range.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            SplitTrackChunkChords(trackChunk, (splitter, chords) => splitter.SplitAtDistance(chords, ratio, lengthType, from, tempoMap), settings);
        }
Example #9
0
        /// <summary>
        /// Splits chords contained in the specified collection of <see cref="TrackChunk"/> into the
        /// specified number of parts of the equal length.
        /// </summary>
        /// <remarks>
        /// If a chord has zero length, it will be split into the specified number of parts of zero length.
        /// </remarks>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="partsNumber">The number of parts to split chords into.</param>
        /// <param name="lengthType">Type of a part's length.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunks"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="partsNumber"/> is zero or negative.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="lengthType"/> specified an invalid value.</exception>
        public static void SplitChordsByPartsNumber(this IEnumerable <TrackChunk> trackChunks, int partsNumber, TimeSpanType lengthType, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsNonpositive(nameof(partsNumber), partsNumber, "Parts number is zero or negative.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            foreach (var trackChunk in trackChunks)
            {
                trackChunk.SplitChordsByPartsNumber(partsNumber, lengthType, tempoMap, settings);
            }
        }
Example #10
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="MidiFile"/> into the specified number of
        /// parts of the equal length.
        /// </summary>
        /// <remarks>
        /// If a chord has zero length, it will be split into the specified number of parts of zero length.
        /// </remarks>
        /// <param name="midiFile"><see cref="MidiFile"/> to split chords in.</param>
        /// <param name="partsNumber">The number of parts to split chords into.</param>
        /// <param name="lengthType">Type of a part's length.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException"><paramref name="midiFile"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="partsNumber"/> is zero or negative.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="lengthType"/> specified an invalid value.</exception>
        public static void SplitChordsByPartsNumber(this MidiFile midiFile, int partsNumber, TimeSpanType lengthType, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsNonpositive(nameof(partsNumber), partsNumber, "Parts number is zero or negative.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);

            var tempoMap = midiFile.GetTempoMap();

            midiFile.GetTrackChunks().SplitChordsByPartsNumber(partsNumber, lengthType, tempoMap, settings);
        }
Example #11
0
        private void RemoveChords_DetectionSettings_EventsCollection_WithPredicate(
            ContainerType containerType,
            ChordDetectionSettings settings,
            ICollection <MidiEvent> midiEvents,
            Predicate <Chord> match,
            ICollection <MidiEvent> expectedMidiEvents,
            int expectedRemovedCount)
        {
            var eventsCollection = new EventsCollection();

            eventsCollection.AddRange(midiEvents);

            switch (containerType)
            {
            case ContainerType.EventsCollection:
            {
                Assert.AreEqual(
                    expectedRemovedCount,
                    eventsCollection.RemoveChords(match, settings),
                    "Invalid count of removed chords.");

                var expectedEventsCollection = new EventsCollection();
                expectedEventsCollection.AddRange(expectedMidiEvents);
                MidiAsserts.AreEqual(expectedEventsCollection, eventsCollection, true, "Events are invalid.");
                Assert.IsTrue(
                    eventsCollection.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            break;

            case ContainerType.TrackChunk:
            {
                var trackChunk = new TrackChunk(eventsCollection);

                Assert.AreEqual(
                    expectedRemovedCount,
                    trackChunk.RemoveChords(match, settings),
                    "Invalid count of removed chords.");

                var expectedTrackChunk = new TrackChunk(expectedMidiEvents);
                MidiAsserts.AreEqual(expectedTrackChunk, trackChunk, true, "Events are invalid.");
                Assert.IsTrue(
                    trackChunk.Events.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))),
                    "There are new events references.");
            }
            break;

            case ContainerType.TrackChunks:
            case ContainerType.File:
            {
                RemoveChords_DetectionSettings_TrackChunks_WithPredicate(
                    containerType == ContainerType.File,
                    settings,
                    new[] { midiEvents },
                    match,
                    new[] { expectedMidiEvents },
                    expectedRemovedCount);
            }
            break;
            }
        }
Example #12
0
        /// <summary>
        /// Splits chords contained in the specified collection of <see cref="TrackChunk"/> by the
        /// specified step so every chord will be split at points equally distanced from each
        /// other starting from the chord's start time.
        /// </summary>
        /// <remarks>
        /// Chords with zero length and chords with length smaller than <paramref name="step"/>
        /// will not be split.
        /// </remarks>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="step">Step to split chords by.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunks"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="step"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsByStep(this IEnumerable <TrackChunk> trackChunks, ITimeSpan step, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsNull(nameof(step), step);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            foreach (var trackChunk in trackChunks)
            {
                trackChunk.SplitChordsByStep(step, tempoMap, settings);
            }
        }
Example #13
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="TrackChunk"/> by the specified grid.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="grid">Grid to split chords by.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunk"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="grid"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsByGrid(this TrackChunk trackChunk, IGrid grid, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsNull(nameof(grid), grid);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            SplitTrackChunkChords(trackChunk, (splitter, chords) => splitter.SplitByGrid(chords, grid, tempoMap), settings);
        }
Example #14
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="MidiFile"/> by the specified ratio of a
        /// chord's length measuring it from the chord's start or end. For example, 0.5 means splitting
        /// at the center of a chord.
        /// </summary>
        /// <param name="midiFile"><see cref="MidiFile"/> to split chords in.</param>
        /// <param name="ratio">Ratio of a chord's length to split by. Valid values are from 0 to 1.</param>
        /// <param name="lengthType">The type a chord's length should be processed according to.</param>
        /// <param name="from">Point of a chord distance should be measured from.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException"><paramref name="midiFile"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ratio"/> is out of valid range.</exception>
        /// <exception cref="InvalidEnumArgumentException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="lengthType"/> specified an invalid value.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="from"/> specified an invalid value.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsAtDistance(this MidiFile midiFile, double ratio, TimeSpanType lengthType, LengthedObjectTarget from, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsOutOfRange(nameof(ratio),
                                         ratio,
                                         LengthedObjectsSplitter <Chord> .ZeroRatio,
                                         LengthedObjectsSplitter <Chord> .FullLengthRatio,
                                         $"Ratio is out of [{LengthedObjectsSplitter<Chord>.ZeroRatio}; {LengthedObjectsSplitter<Chord>.FullLengthRatio}] range.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);

            var tempoMap = midiFile.GetTempoMap();

            midiFile.GetTrackChunks().SplitChordsAtDistance(ratio, lengthType, from, tempoMap, settings);
        }
Example #15
0
        private static void SplitTrackChunkChords(TrackChunk trackChunk, Func <ChordsSplitter, IEnumerable <Chord>, IEnumerable <Chord> > splitOperation, ChordDetectionSettings settings)
        {
            using (var chordsManager = trackChunk.ManageChords(settings))
            {
                var chords = chordsManager.Chords;

                var chordsSplitter = new ChordsSplitter();
                var newChords      = splitOperation(chordsSplitter, chords).ToList();

                chords.Clear();
                chords.Add(newChords);
            }
        }
Example #16
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="TrackChunk"/> into the specified number
        /// of parts of the equal length.
        /// </summary>
        /// <remarks>
        /// If a chord has zero length, it will be split into the specified number of parts of zero length.
        /// </remarks>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="partsNumber">The number of parts to split chords into.</param>
        /// <param name="lengthType">Type of a part's length.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunk"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="partsNumber"/> is zero or negative.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="lengthType"/> specified an invalid value.</exception>
        public static void SplitChordsByPartsNumber(this TrackChunk trackChunk, int partsNumber, TimeSpanType lengthType, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsNonpositive(nameof(partsNumber), partsNumber, "Parts number is zero or negative.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            SplitTrackChunkChords(trackChunk, (splitter, chords) => splitter.SplitByPartsNumber(chords, partsNumber, lengthType, tempoMap), settings);
        }
Example #17
0
        /// <summary>
        /// Splits chords contained in the specified collection of <see cref="TrackChunk"/> by the
        /// specified ratio of a chord's length measuring it from the chord's start or end.
        /// For example, 0.5 means splitting at the center of a chord.
        /// </summary>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="ratio">Ratio of a chord's length to split by. Valid values are from 0 to 1.</param>
        /// <param name="lengthType">The type a chord's length should be processed according to.</param>
        /// <param name="from">Point of a chord distance should be measured from.</param>
        /// <param name="tempoMap">Tempo map used for distances calculations.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunks"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ratio"/> is out of valid range.</exception>
        /// <exception cref="InvalidEnumArgumentException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="lengthType"/> specified an invalid value.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="from"/> specified an invalid value.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsAtDistance(this IEnumerable <TrackChunk> trackChunks, double ratio, TimeSpanType lengthType, LengthedObjectTarget from, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsOutOfRange(nameof(ratio),
                                         ratio,
                                         LengthedObjectsSplitter <Chord> .ZeroRatio,
                                         LengthedObjectsSplitter <Chord> .FullLengthRatio,
                                         $"Ratio is out of [{LengthedObjectsSplitter<Chord>.ZeroRatio}; {LengthedObjectsSplitter<Chord>.FullLengthRatio}] range.");
            ThrowIfArgument.IsInvalidEnumValue(nameof(lengthType), lengthType);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            foreach (var trackChunk in trackChunks)
            {
                trackChunk.SplitChordsAtDistance(ratio, lengthType, from, tempoMap, settings);
            }
        }
Example #18
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="TrackChunk"/> by the specified step so
        /// every chord will be split at points equally distanced from each other starting from
        /// the chord's start time.
        /// </summary>
        /// <remarks>
        /// Chords with zero length and chords with length smaller than <paramref name="step"/>
        /// will not be split.
        /// </remarks>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="step">Step to split chords by.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunk"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="step"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsByStep(this TrackChunk trackChunk, ITimeSpan step, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsNull(nameof(step), step);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            SplitTrackChunkChords(trackChunk, (splitter, chords) => splitter.SplitByStep(chords, step, tempoMap), settings);
        }
Example #19
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="MidiFile"/> at the specified distance
        /// from a chord's start or end.
        /// </summary>
        /// <param name="midiFile"><see cref="MidiFile"/> to split chords in.</param>
        /// <param name="distance">Distance to split chords at.</param>
        /// <param name="from">Point of a chord <paramref name="distance"/> should be measured from.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="midiFile"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="distance"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="from"/> specified an invalid value.</exception>
        public static void SplitChordsAtDistance(this MidiFile midiFile, ITimeSpan distance, LengthedObjectTarget from, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsNull(nameof(distance), distance);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);

            var tempoMap = midiFile.GetTempoMap();

            midiFile.GetTrackChunks().SplitChordsAtDistance(distance, from, tempoMap, settings);
        }
Example #20
0
        /// <summary>
        /// Splits chords contained in the specified collection of <see cref="TrackChunk"/> at the specified
        /// distance from a chord's start or end.
        /// </summary>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="distance">Distance to split chords at.</param>
        /// <param name="from">Point of a chord <paramref name="distance"/> should be measured from.</param>
        /// <param name="tempoMap">Tempo map used for distances calculations.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunks"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="distance"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="from"/> specified an invalid value.</exception>
        public static void SplitChordsAtDistance(this IEnumerable <TrackChunk> trackChunks, ITimeSpan distance, LengthedObjectTarget from, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsNull(nameof(distance), distance);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            foreach (var trackChunk in trackChunks)
            {
                trackChunk.SplitChordsAtDistance(distance, from, tempoMap, settings);
            }
        }
Example #21
0
        /// <summary>
        /// Splits chords contained in the specified <see cref="TrackChunk"/> at the specified distance
        /// from a chord's start or end.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="distance">Distance to split chords at.</param>
        /// <param name="from">Point of a chord <paramref name="distance"/> should be measured from.</param>
        /// <param name="tempoMap">Tempo map used for distances calculations.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunk"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="distance"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="from"/> specified an invalid value.</exception>
        public static void SplitChordsAtDistance(this TrackChunk trackChunk, ITimeSpan distance, LengthedObjectTarget from, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsNull(nameof(distance), distance);
            ThrowIfArgument.IsInvalidEnumValue(nameof(from), from);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            SplitTrackChunkChords(trackChunk, (splitter, chords) => splitter.SplitAtDistance(chords, distance, from, tempoMap), settings);
        }
Example #22
0
        /// <summary>
        /// Splits chords contained in the specified collection of <see cref="TrackChunk"/> by the
        /// specified grid.
        /// </summary>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to split chords in.</param>
        /// <param name="grid">Grid to split chords by.</param>
        /// <param name="tempoMap">Tempo map used to calculate times to split by.</param>
        /// <param name="settings">Settings accoridng to which chords should be detected and built.</param>
        /// <exception cref="ArgumentNullException">
        /// <para>One of the following errors occured:</para>
        /// <list type="bullet">
        /// <item>
        /// <description><paramref name="trackChunks"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="grid"/> is <c>null</c>.</description>
        /// </item>
        /// <item>
        /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void SplitChordsByGrid(this IEnumerable <TrackChunk> trackChunks, IGrid grid, TempoMap tempoMap, ChordDetectionSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsNull(nameof(grid), grid);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            foreach (var trackChunk in trackChunks)
            {
                trackChunk.SplitChordsByGrid(grid, tempoMap, settings);
            }
        }