/// <summary>
        /// Gets timed events contained in the specified <see cref="TrackChunk"/>.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to search for events.</param>
        /// <returns>Collection of timed events contained in <paramref name="trackChunk"/> ordered by time.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is <c>null</c>.</exception>
        public static ICollection <TimedEvent> GetTimedEvents(this TrackChunk trackChunk)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);

            return(trackChunk.Events.GetTimedEvents());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Stretches the current time span by multiplying its length by the specified multiplier.
        /// </summary>
        /// <param name="multiplier">Multiplier to stretch the time span by.</param>
        /// <returns>Time span that is the current time span stretched by the <paramref name="multiplier"/>.</returns>
        public ITimeSpan Multiply(double multiplier)
        {
            ThrowIfArgument.IsNegative(nameof(multiplier), multiplier, "Multiplier is negative.");

            return(new MetricTimeSpan(MathUtilities.RoundToLong(TotalMicroseconds * multiplier)));
        }
        /// <summary>
        /// Gets the ID of the specified musical note event.
        /// </summary>
        /// <param name="noteEvent">The musical note event for which to get the ID.</param>
        /// <returns>The ID of the specified musical note event.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="noteEvent"/> is <c>null</c>.</exception>
        public static NoteId GetNoteId(this NoteEvent noteEvent)
        {
            ThrowIfArgument.IsNull(nameof(noteEvent), noteEvent);

            return(new NoteId(noteEvent.Channel, noteEvent.NoteNumber));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Playback"/> with the specified
 /// collection of MIDI events, tempo map and output MIDI device to play events through.
 /// </summary>
 /// <param name="events">Collection of MIDI events to play.</param>
 /// <param name="tempoMap">Tempo map used to calculate events times.</param>
 /// <param name="outputDevice">Output MIDI device to play <paramref name="events"/> through.</param>
 /// <param name="clockSettings">Settings of the internal playback's clock.</param>
 /// <exception cref="ArgumentNullException">
 /// <para>One of the following errors occured:</para>
 /// <list type="bullet">
 /// <item>
 /// <description><paramref name="events"/> is <c>null</c>.</description>
 /// </item>
 /// <item>
 /// <description><paramref name="tempoMap"/> is <c>null</c>.</description>
 /// </item>
 /// <item>
 /// <description><paramref name="outputDevice"/> is <c>null</c>.</description>
 /// </item>
 /// </list>
 /// </exception>
 public Playback(IEnumerable <MidiEvent> events, TempoMap tempoMap, IOutputDevice outputDevice, MidiClockSettings clockSettings = null)
     : this(new[] { events }, tempoMap, outputDevice, clockSettings)
 {
     ThrowIfArgument.IsNull(nameof(events), events);
 }
        /// <summary>
        /// Retrieves the current time of the playback in the specified format.
        /// </summary>
        /// <param name="timeType">Type that will represent the current time.</param>
        /// <returns>The current time of the playback as an instance of time span defined by
        /// <paramref name="timeType"/>.</returns>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="timeType"/> specified an invalid value.</exception>
        public ITimeSpan GetCurrentTime(TimeSpanType timeType)
        {
            ThrowIfArgument.IsInvalidEnumValue(nameof(timeType), timeType);

            return(TimeConverter.ConvertTo((MetricTimeSpan)_clock.CurrentTime, timeType, TempoMap));
        }
        /// <summary>
        /// Creates an instance of the <see cref="UnknownChannelEventAction"/> to skip data bytes of
        /// unknown channel event.
        /// </summary>
        /// <param name="dataBytesToSkipCount">Count of data bytes to skip be reading engine.
        /// Data bytes are event bytes without status byte.</param>
        /// <returns>an instance of the <see cref="UnknownChannelEventAction"/> to skip data bytes of
        /// unknown channel event.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="dataBytesToSkipCount"/> is negative.</exception>
        public static UnknownChannelEventAction SkipData(int dataBytesToSkipCount)
        {
            ThrowIfArgument.IsNegative(nameof(dataBytesToSkipCount), dataBytesToSkipCount, "Count of data bytes to skip is negative.");

            return(new UnknownChannelEventAction(UnknownChannelEventInstruction.SkipData, dataBytesToSkipCount));
        }
Ejemplo n.º 7
0
        private void AddNotes(IEnumerable <Note> notes)
        {
            ThrowIfArgument.IsNull(nameof(notes), notes);

            _notesManager.Notes.Add(notes);
        }
        public static TrackChunk ToTrackChunk(this IEnumerable <TimedEvent> events)
        {
            ThrowIfArgument.IsNull(nameof(events), events);

            return(((IEnumerable <ITimedObject>)events).ToTrackChunk());
        }
        public static MidiFile ToFile(this IEnumerable <TimedEvent> events)
        {
            ThrowIfArgument.IsNull(nameof(events), events);

            return(((IEnumerable <ITimedObject>)events).ToFile());
        }
        /// <summary>
        /// Creates an instance of the <see cref="TimedEventsManager"/> initializing it with the
        /// events collection of the specified track chunk and comparison delegate for events
        /// that have same time.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> that holds events to manage.</param>
        /// <param name="sameTimeEventsComparison">Delegate to compare events with the same absolute time.</param>
        /// <returns>An instance of the <see cref="TimedEventsManager"/> that can be used to manage
        /// events represented by the <paramref name="trackChunk"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is <c>null</c>.</exception>
        public static TimedEventsManager ManageTimedEvents(this TrackChunk trackChunk, Comparison <MidiEvent> sameTimeEventsComparison = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);

            return(trackChunk.Events.ManageTimedEvents(sameTimeEventsComparison));
        }
        /// <summary>
        /// Removes all the <see cref="TimedEvent"/> that match the conditions defined by the specified predicate.
        /// </summary>
        /// <param name="file"><see cref="MidiFile"/> to search for events to remove.</param>
        /// <returns>Count of removed timed events.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="file"/> is <c>null</c>.</exception>
        public static int RemoveTimedEvents(this MidiFile file)
        {
            ThrowIfArgument.IsNull(nameof(file), file);

            return(file.GetTrackChunks().RemoveTimedEvents());
        }
        /// <summary>
        /// Removes all the <see cref="TimedEvent"/> that match the conditions defined by the specified predicate.
        /// </summary>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to search for events to remove.</param>
        /// <param name="match">The predicate that defines the conditions of the <see cref="TimedEvent"/> to remove.</param>
        /// <returns>Count of removed timed events.</returns>
        /// <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="match"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static int RemoveTimedEvents(this IEnumerable <TrackChunk> trackChunks, Predicate <TimedEvent> match)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);
            ThrowIfArgument.IsNull(nameof(match), match);

            var eventsCollections = trackChunks.Where(c => c != null).Select(c => c.Events).ToArray();
            var eventsCount       = eventsCollections.Sum(c => c.Count);

            var eventsCollectionsCount = eventsCollections.Length;

            if (eventsCollectionsCount == 0)
            {
                return(0);
            }

            if (eventsCollectionsCount == 1)
            {
                return(eventsCollections[0].RemoveTimedEvents(match));
            }

            var eventsCollectionIndices     = new int[eventsCollectionsCount];
            var eventsCollectionMaxIndices  = eventsCollections.Select(c => c.Count - 1).ToArray();
            var eventsCollectionTimes       = new long[eventsCollectionsCount];
            var eventsCollectionLatestTimes = new long[eventsCollectionsCount];
            var removedEventsCounts         = new int[eventsCollectionsCount];

            for (var i = 0; i < eventsCount; i++)
            {
                var eventsCollectionIndex = 0;
                var minTime = long.MaxValue;

                for (var j = 0; j < eventsCollectionsCount; j++)
                {
                    var index = eventsCollectionIndices[j];
                    if (index > eventsCollectionMaxIndices[j])
                    {
                        continue;
                    }

                    var eventTime = eventsCollections[j][index].DeltaTime + eventsCollectionTimes[j];
                    if (eventTime < minTime)
                    {
                        minTime = eventTime;
                        eventsCollectionIndex = j;
                    }
                }

                var midiEvent = eventsCollections[eventsCollectionIndex][eventsCollectionIndices[eventsCollectionIndex]];

                var timedEvent = new TimedEvent(midiEvent, minTime);
                if (match(timedEvent))
                {
                    removedEventsCounts[eventsCollectionIndex]++;
                }
                else
                {
                    midiEvent.DeltaTime = minTime - eventsCollectionLatestTimes[eventsCollectionIndex];
                    eventsCollections[eventsCollectionIndex][eventsCollectionIndices[eventsCollectionIndex] - removedEventsCounts[eventsCollectionIndex]] = midiEvent;
                    eventsCollectionLatestTimes[eventsCollectionIndex] = minTime;
                }

                eventsCollectionTimes[eventsCollectionIndex] = minTime;
                eventsCollectionIndices[eventsCollectionIndex]++;
            }

            for (var i = 0; i < eventsCollectionsCount; i++)
            {
                var removedEventsCount = removedEventsCounts[i];
                if (removedEventsCount > 0)
                {
                    eventsCollections[i]._events.RemoveRange(eventsCollections[i].Count - removedEventsCount, removedEventsCount);
                }
            }

            return(removedEventsCounts.Sum());
        }
        /// <summary>
        /// Creates an instance of the <see cref="TimedEventsManager"/> initializing it with the
        /// specified events collection and comparison delegate for events that have same time.
        /// </summary>
        /// <param name="eventsCollection"><see cref="EventsCollection"/> that holds events to manage.</param>
        /// <param name="sameTimeEventsComparison">Delegate to compare events with the same absolute time.</param>
        /// <returns>An instance of the <see cref="TimedEventsManager"/> that can be used to manage
        /// events represented by the <paramref name="eventsCollection"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="eventsCollection"/> is <c>null</c>.</exception>
        public static TimedEventsManager ManageTimedEvents(this EventsCollection eventsCollection, Comparison <MidiEvent> sameTimeEventsComparison = null)
        {
            ThrowIfArgument.IsNull(nameof(eventsCollection), eventsCollection);

            return(new TimedEventsManager(eventsCollection, sameTimeEventsComparison));
        }
        /// <summary>
        /// Gets timed events contained in the specified <see cref="MidiFile"/>.
        /// </summary>
        /// <param name="file"><see cref="MidiFile"/> to search for events.</param>
        /// <returns>Collection of timed events contained in <paramref name="file"/> ordered by time.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="file"/> is <c>null</c>.</exception>
        public static ICollection <TimedEvent> GetTimedEvents(this MidiFile file)
        {
            ThrowIfArgument.IsNull(nameof(file), file);

            return(file.GetTrackChunks().GetTimedEvents());
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Removes all changes of tempo that occured since the specified time.
        /// </summary>
        /// <param name="startTime">Time to remove changes of tempo since.</param>
        /// <exception cref="ArgumentNullException"><paramref name="startTime"/> is null.</exception>
        public void ClearTempo(ITime startTime)
        {
            ThrowIfArgument.IsNull(nameof(startTime), startTime);

            ClearTempo(TimeConverter.ConvertFrom(startTime, TempoMap));
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Gets octave of the note presented by the specified <see cref="NoteOnEvent"/>.
        /// </summary>
        /// <param name="noteEvent">Note event to get note octave of.</param>
        /// <returns>Note octave of the <paramref name="noteEvent"/>.</returns>
        /// <remarks>
        /// Octave number will be returned in scientific pitch notation which means
        /// that 4 will be returned for 60 note number.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="noteEvent"/> is null.</exception>
        public static int GetNoteOctave(this NoteEvent noteEvent)
        {
            ThrowIfArgument.IsNull(nameof(noteEvent), noteEvent);

            return(NoteUtilities.GetNoteOctave(noteEvent.NoteNumber));
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TempoMapManager"/> with the
        /// specified time division.
        /// </summary>
        /// <param name="timeDivision">Time division of a new tempo that will be managed by this manager.</param>
        /// <exception cref="ArgumentNullException"><paramref name="timeDivision"/> is null.</exception>
        public TempoMapManager(TimeDivision timeDivision)
        {
            ThrowIfArgument.IsNull(nameof(timeDivision), timeDivision);

            TempoMap = new TempoMap(timeDivision);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Sets the note number of the <see cref="NoteEvent"/> with the specified note name and octave.
        /// </summary>
        /// <param name="noteEvent">Note event to set the note number of.</param>
        /// <param name="noteName">Name of the note.</param>
        /// <param name="octave">Number of the octave.</param>
        /// <remarks>
        /// Octave number is specified in scientific pitch notation which means that 4 must be
        /// passed to get the number of the middle C.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="noteEvent"/> is null.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="noteName"/> specified an
        /// invalid value.</exception>
        /// <exception cref="ArgumentException">Note number is out of range for the specified note
        /// name and octave.</exception>
        public static void SetNoteNumber(this NoteEvent noteEvent, NoteName noteName, int octave)
        {
            ThrowIfArgument.IsNull(nameof(noteEvent), noteEvent);

            noteEvent.NoteNumber = NoteUtilities.GetNoteNumber(noteName, octave);
        }
Ejemplo n.º 19
0
        private void UnsubscribeFromChordEvents(Chord chord)
        {
            ThrowIfArgument.IsNull(nameof(chord), chord);

            chord.NotesCollectionChanged -= OnChordNotesCollectionChanged;
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Writes a byte array to the underlying stream.
        /// </summary>
        /// <param name="bytes">A byte array containing the data to write.</param>
        /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is <c>null</c>.</exception>
        /// <exception cref="ObjectDisposedException">Method was called after the writer was disposed.</exception>
        /// <exception cref="IOException">An I/O error occurred on the underlying stream.</exception>
        public void WriteBytes(byte[] bytes)
        {
            ThrowIfArgument.IsNull(nameof(bytes), bytes);

            WriteBytes(bytes, 0, bytes.Length);
        }
Ejemplo n.º 21
0
        private void RemoveNotes(IEnumerable <Note> notes)
        {
            ThrowIfArgument.IsNull(nameof(notes), notes);

            _notesManager.Notes.Remove(notes);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Gets an object that represents zero value of time span defined by the specified
        /// time span type.
        /// </summary>
        /// <param name="timeSpanType">The type of time span to get zero value.</param>
        /// <returns>An object that represents zero value of time span defined by <paramref name="timeSpanType"/>.</returns>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="timeSpanType"/> specified an
        /// invalid value.</exception>
        public static ITimeSpan GetZeroTimeSpan(TimeSpanType timeSpanType)
        {
            ThrowIfArgument.IsInvalidEnumValue(nameof(timeSpanType), timeSpanType);

            return(ZeroTimeSpans[timeSpanType]);
        }
        /// <summary>
        /// Retrieves the duration of the playback in the specified format.
        /// </summary>
        /// <param name="durationType">Type that will represent the duration.</param>
        /// <returns>The duration of the playback as an instance of time span defined by
        /// <paramref name="durationType"/>.</returns>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="durationType"/>
        /// specified an invalid value.</exception>
        public ITimeSpan GetDuration(TimeSpanType durationType)
        {
            ThrowIfArgument.IsInvalidEnumValue(nameof(durationType), durationType);

            return(TimeConverter.ConvertTo((MetricTimeSpan)_duration, durationType, TempoMap));
        }
Ejemplo n.º 24
0
        internal static ITimeSpan Subtract(ITimeSpan timeSpan1, ITimeSpan timeSpan2, TimeSpanMode mode)
        {
            ThrowIfArgument.IsInvalidEnumValue(nameof(mode), mode);

            return(new MathTimeSpan(timeSpan1, timeSpan2, MathOperation.Subtract, mode));
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MidiReader"/> with the specified stream.
        /// </summary>
        /// <param name="stream">Stream to read MIDI file from.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="stream"/> does not support reading,
        /// or is already closed.</exception>
        public MidiReader(Stream stream)
        {
            ThrowIfArgument.IsNull(nameof(stream), stream);

            _binaryReader = new BinaryReader(stream, SmfUtilities.DefaultEncoding);
        }
Ejemplo n.º 26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Playback"/> with the specified
 /// collection of MIDI events, tempo map and output MIDI device to play events through.
 /// </summary>
 /// <param name="events">Collection of MIDI events to play.</param>
 /// <param name="tempoMap">Tempo map used to calculate events times.</param>
 /// <param name="outputDevice">Output MIDI device to play <paramref name="events"/> through.</param>
 /// <exception cref="ArgumentNullException"><paramref name="events"/> is null. -or-
 /// <paramref name="tempoMap"/> is null. -or- <paramref name="outputDevice"/> is null.</exception>
 public Playback(IEnumerable <MidiEvent> events, TempoMap tempoMap, OutputDevice outputDevice)
     : this(new[] { events }, tempoMap, outputDevice)
 {
     ThrowIfArgument.IsNull(nameof(events), events);
 }
Ejemplo n.º 27
0
        /// <summary>
        /// Shrinks the current time span by dividing its length by the specified divisor.
        /// </summary>
        /// <param name="divisor">Divisor to shrink the time span by.</param>
        /// <returns>Time span that is the current time span shrinked by the <paramref name="divisor"/>.</returns>
        public ITimeSpan Divide(double divisor)
        {
            ThrowIfArgument.IsNonpositive(nameof(divisor), divisor, "Divisor is zero or negative.");

            return(new MetricTimeSpan(MathUtilities.RoundToLong(TotalMicroseconds / divisor)));
        }
 internal static void IsNegative(string parameterName, long notesTolerance)
 {
     ThrowIfArgument.IsNegative(parameterName, notesTolerance, "Notes tolerance is negative.");
 }
Ejemplo n.º 29
0
        /// <summary>
        /// Gets intervals from the root note of the specified chord. For example, +4 and +7 for C major
        /// (+4 for C and E, +7 for C and G).
        /// </summary>
        /// <param name="chord">Chord to get intervals from root note.</param>
        /// <returns>Intervals from the root note of the <paramref name="chord"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="chord"/> is null.</exception>
        /// <exception cref="InvalidOperationException">Some intervals are greater than <see cref="SevenBitNumber.MaxValue"/>.</exception>
        public static IEnumerable <Interval> GetIntervalsFromRootNote(this Chord chord)
        {
            ThrowIfArgument.IsNull(nameof(chord), chord);

            return(GetIntervalsFromRootNote(chord.NotesNames));
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Gets all channel numbers presented in the specified collection of <see cref="TrackChunk"/>.
        /// </summary>
        /// <param name="trackChunks">Collection of <see cref="TrackChunk"/> to get channels of.</param>
        /// <returns>Collection of channel numbers presented in the <paramref name="trackChunks"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="trackChunks"/> is null.</exception>
        public static IEnumerable <FourBitNumber> GetChannels(this IEnumerable <TrackChunk> trackChunks)
        {
            ThrowIfArgument.IsNull(nameof(trackChunks), trackChunks);

            return(trackChunks.Where(c => c != null).SelectMany(GetChannels).Distinct().ToArray());
        }