/// <summary>
        /// Reads content of a MIDI meta event.
        /// </summary>
        /// <param name="reader">Reader to read the content with.</param>
        /// <param name="settings">Settings according to which the event's content must be read.</param>
        /// <param name="size">Size of the event's content.</param>
        /// <exception cref="ArgumentOutOfRangeException">Text event cannot be read since the size is
        /// negative number.</exception>
        protected sealed override void ReadContent(MidiReader reader, ReadingSettings settings, int size)
        {
            ThrowIfArgument.IsNegative(
                nameof(size),
                size,
                "Text event cannot be read since the size is negative number.");

            if (size == 0)
            {
                switch (settings.ZeroLengthDataPolicy)
                {
                case ZeroLengthDataPolicy.ReadAsEmptyObject:
                    Text = string.Empty;
                    break;

                case ZeroLengthDataPolicy.ReadAsNull:
                    Text = null;
                    break;
                }

                return;
            }

            var bytes    = reader.ReadBytes(size);
            var encoding = settings.TextEncoding ?? SmfConstants.DefaultTextEncoding;

            var decodeTextCallback = settings.DecodeTextCallback;

            Text = decodeTextCallback != null
                ? decodeTextCallback(bytes, settings)
                : encoding.GetString(bytes);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BytesToMidiEventConverter"/> with the specified
        /// initial capacity of internal buffer.
        /// </summary>
        /// <param name="capacity">Initial capacity of the internal buffer.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is negative.</exception>
        public BytesToMidiEventConverter(int capacity)
        {
            ThrowIfArgument.IsNegative(nameof(capacity), capacity, "Capacity is negative.");

            _dataBytesStream = new MemoryStream(capacity);
            _midiReader      = new MidiReader(_dataBytesStream, new ReaderSettings());
        }
예제 #3
0
        /// <summary>
        /// Reads content of a MIDI meta event.
        /// </summary>
        /// <param name="reader">Reader to read the content with.</param>
        /// <param name="settings">Settings according to which the event's content must be read.</param>
        /// <param name="size">Size of the event's content.</param>
        /// <exception cref="ArgumentOutOfRangeException">Sequencer specific event cannot be read since the size is
        /// negative number.</exception>
        protected override void ReadContent(MidiReader reader, ReadingSettings settings, int size)
        {
            ThrowIfArgument.IsNegative(
                nameof(size),
                size,
                "Sequencer specific event cannot be read since the size is negative number.");

            if (size == 0)
            {
                switch (settings.ZeroLengthDataPolicy)
                {
                case ZeroLengthDataPolicy.ReadAsEmptyObject:
                    Data = new byte[0];
                    break;

                case ZeroLengthDataPolicy.ReadAsNull:
                    Data = null;
                    break;
                }

                return;
            }

            Data = reader.ReadBytes(size);
        }
예제 #4
0
        /// <summary>
        /// Resizes group of notes by the specified ratio treating all notes as single object. For example,
        /// resizing by ratio of 0.5 shrinks group of notes by two times.
        /// </summary>
        /// <param name="notes">Notes to resize.</param>
        /// <param name="ratio">Ratio to resize notes by.</param>
        /// <param name="distanceCalculationType">Type of distance calculations.</param>
        /// <param name="tempoMap"></param>
        /// <exception cref="ArgumentNullException"><paramref name="notes"/> is null. -or-
        /// <paramref name="tempoMap"/> is null.</exception>
        /// <exception cref="ArgumentException"><see cref="TimeSpanType.BarBeat"/> is used for
        /// <paramref name="distanceCalculationType"/> which is unsupported.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ratio"/> is negative.</exception>
        /// <exception cref="InvalidEnumArgumentException"><paramref name="distanceCalculationType"/> specified an
        /// invalid value.</exception>
        public static void ResizeNotes(this IEnumerable <Note> notes,
                                       double ratio,
                                       TimeSpanType distanceCalculationType,
                                       TempoMap tempoMap)
        {
            ThrowIfArgument.IsNull(nameof(notes), notes);
            ThrowIfArgument.IsNegative(nameof(ratio), ratio, "Ratio is negative");
            ThrowIfArgument.IsInvalidEnumValue(nameof(distanceCalculationType), distanceCalculationType);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            if (distanceCalculationType == TimeSpanType.BarBeat)
            {
                throw new ArgumentException("BarBeat distance calculation type is not supported.", nameof(distanceCalculationType));
            }

            var notNullNotes = notes.Where(n => n != null);

            if (!notNullNotes.Any())
            {
                return;
            }

            //

            var minStartTime = notNullNotes.Select(n => n.Time).Min();
            var startTime    = TimeConverter.ConvertTo(minStartTime, distanceCalculationType, tempoMap);

            ResizeNotesByRatio(notNullNotes, ratio, distanceCalculationType, tempoMap, startTime);
        }
예제 #5
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 MusicalTimeSpan(MathUtilities.RoundToLong(Numerator * MathUtilities.Round(multiplier, NumberOfDigitsAfterDecimalPoint) * FractionPartMultiplier),
                                       Denominator * FractionPartMultiplier));
        }
예제 #6
0
        /// <summary>
        /// Returns the current <see cref="MusicalTimeSpan"/> modified by the specified number
        /// of dots.
        /// </summary>
        /// <param name="dotsCount">The number of dots to modify the current <see cref="MusicalTimeSpan"/>.</param>
        /// <returns>The dotted version of the current <see cref="MusicalTimeSpan"/>.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="dotsCount"/> is negative.</exception>
        public MusicalTimeSpan Dotted(int dotsCount)
        {
            ThrowIfArgument.IsNegative(nameof(dotsCount), dotsCount, "Dots count is negative.");

            return(new MusicalTimeSpan(Numerator * ((1 << dotsCount + 1) - 1),
                                       Denominator * (1 << dotsCount)));
        }
예제 #7
0
        public static NoteName GetStep(this Scale scale, int step)
        {
            ThrowIfArgument.IsNull(nameof(scale), scale);
            ThrowIfArgument.IsNegative(nameof(step), step, "Step is negative.");

            return(scale.GetNotesNames().Skip(step).First());
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MidiEventToBytesConverter"/> with the specified
        /// initial capacity of internal buffer.
        /// </summary>
        /// <param name="capacity">Initial capacity of the internal buffer.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is negative.</exception>
        public MidiEventToBytesConverter(int capacity)
        {
            ThrowIfArgument.IsNegative(nameof(capacity), capacity, "Capacity is negative.");

            _dataBytesStream = new MemoryStream(capacity);
            _midiWriter      = new MidiWriter(_dataBytesStream);
        }
예제 #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ChannelEvent"/> with the specified parameters count.
        /// </summary>
        /// <param name="eventType">The type of event.</param>
        /// <param name="parametersCount">Count of the parameters for this channel event.</param>
        /// <exception cref="ArgumentOutOfRangeException">Parameters count is negative number which is unallowable.</exception>
        protected ChannelEvent(MidiEventType eventType, int parametersCount)
            : base(eventType)
        {
            ThrowIfArgument.IsNegative(nameof(parametersCount), parametersCount, "Parameters count is negative.");

            _parameters = new SevenBitNumber[parametersCount];
        }
예제 #10
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>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="multiplier"/> is negative.</exception>
        public ITimeSpan Multiply(double multiplier)
        {
            ThrowIfArgument.IsNegative(nameof(multiplier), multiplier, "Multiplier is negative.");

            return(new BarBeatFractionTimeSpan(MathUtilities.RoundToLong(Bars * multiplier),
                                               Beats * multiplier));
        }
        /// <summary>
        /// Resizes <see cref="MidiFile"/> by the specified ratio.
        /// </summary>
        /// <param name="midiFile"><see cref="MidiFile"/> to resize.</param>
        /// <param name="ratio">Ratio to resize <paramref name="midiFile"/> by.</param>
        /// <exception cref="ArgumentNullException"><paramref name="midiFile"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ratio"/> is negative.</exception>
        public static void Resize(this MidiFile midiFile, double ratio)
        {
            ThrowIfArgument.IsNull(nameof(midiFile), midiFile);
            ThrowIfArgument.IsNegative(nameof(ratio), ratio, "Ratio is negative");

            ResizeByRatio(midiFile, ratio);
        }
예제 #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BeatTimeSpan"/> with the specified
        /// number of beats.
        /// </summary>
        /// <param name="beats">The number of beats.</param>
        ///       /// <param name="ticks">The number of ticks.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ticks"/> is negative. -or-
        /// <paramref name="beats"/> is negative.</exception>
        public BeatTimeSpan(long beats, long ticks)
        {
            ThrowIfArgument.IsNegative(nameof(beats), beats, "Beats number is negative.");
            ThrowIfArgument.IsNegative(nameof(ticks), ticks, "Ticks number is negative.");

            Beats = beats;
            Ticks = ticks;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TicksPerQuarterNoteTimeDivision"/> with
        /// the specified ticks number per a quarter-note.
        /// </summary>
        /// <param name="ticksPerQuarterNote">Number of ticks which make up a quarter-note.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="ticksPerQuarterNote"/> is negative.</exception>
        public TicksPerQuarterNoteTimeDivision(short ticksPerQuarterNote)
        {
            ThrowIfArgument.IsNegative(nameof(ticksPerQuarterNote),
                                       ticksPerQuarterNote,
                                       "Ticks per quarter-note must be non-negative number.");

            TicksPerQuarterNote = ticksPerQuarterNote;
        }
예제 #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MetricTimeSpan"/> with the specified
        /// number of microseconds.
        /// </summary>
        /// <param name="totalMicroseconds">Number of microseconds which represents metric time span.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="totalMicroseconds"/> is negative.</exception>
        public MetricTimeSpan(long totalMicroseconds)
        {
            ThrowIfArgument.IsNegative(nameof(totalMicroseconds),
                                       totalMicroseconds,
                                       "Number of microseconds is negative.");

            _timeSpan = new TimeSpan(totalMicroseconds * TicksInMicrosecond);
        }
예제 #15
0
        /// <summary>
        /// Reads content of a MIDI event.
        /// </summary>
        /// <param name="reader">Reader to read the content with.</param>
        /// <param name="settings">Settings according to which the event's content must be read.</param>
        /// <param name="size">Size of the event's content.</param>
        internal sealed override void Read(MidiReader reader, ReadingSettings settings, int size)
        {
            ThrowIfArgument.IsNegative(nameof(size),
                                       size,
                                       "Non-negative size have to be specified in order to read SysEx event.");

            Data = reader.ReadBytes(size);
        }
예제 #16
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 BarBeatTimeSpan((long)Math.Round(Bars * multiplier),
                                       (long)Math.Round(Beats * multiplier),
                                       (long)Math.Round(Ticks * multiplier)));
        }
예제 #17
0
        /// <summary>
        /// Reads content of a MIDI meta event.
        /// </summary>
        /// <param name="reader">Reader to read the content with.</param>
        /// <param name="settings">Settings according to which the event's content must be read.</param>
        /// <param name="size">Size of the event's content.</param>
        /// <exception cref="ArgumentOutOfRangeException">Unknown meta event cannot be read since the size is
        /// negative number.</exception>
        protected override void ReadContent(MidiReader reader, ReadingSettings settings, int size)
        {
            ThrowIfArgument.IsNegative(nameof(size),
                                       size,
                                       "Unknown meta event cannot be read since the size is negative number.");

            Data = reader.ReadBytes(size);
        }
예제 #18
0
        /// <summary>
        /// Multiplies the specified <see cref="MusicalTimeSpan"/> by a number.
        /// </summary>
        /// <param name="timeSpan">The <see cref="MusicalTimeSpan"/> to multiply by <paramref name="number"/>.</param>
        /// <param name="number">The multiplier.</param>
        /// <returns>An object whose value is the result of multiplication of <paramref name="timeSpan"/> by
        /// <paramref name="number"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="timeSpan"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="number"/> is negative.</exception>
        public static MusicalTimeSpan operator *(MusicalTimeSpan timeSpan, long number)
        {
            ThrowIfArgument.IsNull(nameof(timeSpan), timeSpan);
            ThrowIfArgument.IsNegative(nameof(number), number, "Number is negative.");

            return(new MusicalTimeSpan(timeSpan.Numerator * number,
                                       timeSpan.Denominator));
        }
예제 #19
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BarBeatFractionTimeSpan"/> with the specified
        /// number of bars and beats.
        /// </summary>
        /// <param name="bars">The number of bars.</param>
        /// <param name="beats">The number of beats.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bars"/> is negative. -or-
        /// <paramref name="beats"/> is negative.</exception>
        public BarBeatFractionTimeSpan(long bars, double beats)
        {
            ThrowIfArgument.IsNegative(nameof(bars), bars, "Bars number is negative.");
            ThrowIfArgument.IsNegative(nameof(beats), beats, "Beats number is negative.");

            Bars  = bars;
            Beats = beats;
        }
예제 #20
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.IsNegative(nameof(divisor), divisor, "Divisor is negative.");

            return(new MathTimeSpan(TimeSpan1.Divide(divisor),
                                    TimeSpan2.Divide(divisor),
                                    Operation,
                                    Mode));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MidiEventToBytesConverter"/> with the specified
        /// initial capacity of internal buffer.
        /// </summary>
        /// <param name="capacity">Initial capacity of the internal buffer.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is negative.</exception>
        public MidiEventToBytesConverter(int capacity)
        {
            ThrowIfArgument.IsNegative(nameof(capacity), capacity, "Capacity is negative.");

            _dataBytesStream = new MemoryStream(capacity);
            _midiWriter      = new MidiWriter(_dataBytesStream, new WriterSettings {
                UseBuffering = false
            });
        }
예제 #22
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MetricTimeSpan"/> with the specified
        /// numbers of hours, minutes, seconds and milliseconds.
        /// </summary>
        /// <param name="hours">Number of hours.</param>
        /// <param name="minutes">Number of minutes.</param>
        /// <param name="seconds">Number of seconds.</param>
        /// <param name="milliseconds">Number of milliseconds.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="hours"/> is negative. -or-
        /// <paramref name="minutes"/> is negative. -or- <paramref name="seconds"/> is negative. -or-
        /// <paramref name="milliseconds"/> is negative.</exception>
        public MetricTimeSpan(int hours, int minutes, int seconds, int milliseconds)
        {
            ThrowIfArgument.IsNegative(nameof(hours), hours, "Number of hours is negative.");
            ThrowIfArgument.IsNegative(nameof(minutes), minutes, "Number of minutes is negative.");
            ThrowIfArgument.IsNegative(nameof(seconds), seconds, "Number of seconds is negative.");
            ThrowIfArgument.IsNegative(nameof(milliseconds), milliseconds, "Number of milliseconds is negative.");

            _timeSpan = new TimeSpan(0, hours, minutes, seconds, milliseconds);
        }
예제 #23
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 MathTimeSpan(TimeSpan1.Multiply(multiplier),
                                    TimeSpan2.Multiply(multiplier),
                                    Operation,
                                    Mode));
        }
예제 #24
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MusicalTime"/> with the specified
        /// number of bars, beats and fraction of the whole note length.
        /// </summary>
        /// <param name="bars">Number of bars.</param>
        /// <param name="beats">Number of beats.</param>
        /// <param name="fraction">Fraction of the whole note length.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bars"/> is negative. -or-
        /// <paramref name="beats"/> is negative.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="fraction"/> is null.</exception>
        public MusicalTime(int bars, int beats, Fraction fraction)
        {
            ThrowIfArgument.IsNegative(nameof(bars), bars, "Number of bars is negative.");
            ThrowIfArgument.IsNegative(nameof(beats), beats, "Number of beats is negative.");
            ThrowIfArgument.IsNull(nameof(fraction), fraction);

            Bars     = bars;
            Beats    = beats;
            Fraction = fraction;
        }
        public static int GetBarLength(long bars, TempoMap tempoMap)
        {
            ThrowIfArgument.IsNegative(nameof(bars), bars, "Bars number is negative.");
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            var timeSignatureAndticksPerQuarterNote = GetTimeSignatureAndTicksPerQuarterNote(bars, tempoMap);

            return(GetBarLength(timeSignatureAndticksPerQuarterNote.Item1,
                                timeSignatureAndticksPerQuarterNote.Item2));
        }
예제 #26
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MusicalTimeSpan"/> with the specified
        /// numerator and denominator of the fraction of the whole note's length.
        /// </summary>
        /// <param name="numerator">The numerator of fraction of the whole note's length.</param>
        /// <param name="denominator">The denominator of fraction of the whole note's length.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="numerator"/> is negative. -or-
        /// <paramref name="denominator"/> is zero or negative.</exception>
        public MusicalTimeSpan(long numerator, long denominator)
        {
            ThrowIfArgument.IsNegative(nameof(numerator), numerator, "Numerator is negative.");
            ThrowIfArgument.IsNonpositive(nameof(denominator), denominator, "Denominator is negative.");

            var greatestCommonDivisor = MathUtilities.GreatestCommonDivisor(numerator, denominator);

            Numerator   = numerator / greatestCommonDivisor;
            Denominator = denominator / greatestCommonDivisor;
        }
예제 #27
0
        /// <summary>
        /// Repeats the specified number of previous actions.
        /// </summary>
        /// <param name="actionsCount">Number of previous actions to repeat.</param>
        /// <param name="repetitionsCount">Count of repetitions.</param>
        /// <returns>The current <see cref="PatternBuilder"/>.</returns>
        /// <remarks>
        /// Note that <see cref="SetNoteLength(ILength)"/>, <see cref="SetOctave(int)"/>,
        /// <see cref="SetStep(ILength)"/> and <see cref="SetVelocity(SevenBitNumber)"/> are not
        /// actions and will not be repeated since default values applies immidiately on next actions.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="actionsCount"/> is
        /// negative. -or- <paramref name="actionsCount"/> is greater than count of existing actions. -or-
        /// <paramref name="repetitionsCount"/> is negative.</exception>
        public PatternBuilder Repeat(int actionsCount, int repetitionsCount)
        {
            ThrowIfArgument.IsNegative(nameof(actionsCount), actionsCount, "Actions count is negative.");
            ThrowIfArgument.IsGreaterThan(nameof(actionsCount),
                                          actionsCount,
                                          _actions.Count,
                                          "Actions count is greater than existing actions count.");
            ThrowIfArgument.IsNegative(nameof(repetitionsCount), repetitionsCount, "Repetitions count is negative.");

            return(RepeatActions(actionsCount, repetitionsCount));
        }
예제 #28
0
        /// <summary>
        /// Repeats the previous action the specified number of times.
        /// </summary>
        /// <param name="repetitionsCount">Count of repetitions.</param>
        /// <returns>The current <see cref="PatternBuilder"/>.</returns>
        /// <remarks>
        /// Note that <see cref="SetNoteLength(ILength)"/>, <see cref="SetOctave(int)"/>,
        /// <see cref="SetStep(ILength)"/> and <see cref="SetVelocity(SevenBitNumber)"/> are not
        /// actions and will not be repeated since default values applies immidiately on next actions.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="repetitionsCount"/> is negative.</exception>
        /// <exception cref="InvalidOperationException">There are no actions to repeat.</exception>
        public PatternBuilder Repeat(int repetitionsCount)
        {
            ThrowIfArgument.IsNegative(nameof(repetitionsCount), repetitionsCount, "Repetitions count is negative.");

            if (!_actions.Any())
            {
                throw new InvalidOperationException("There is no action to repeat.");
            }

            return(RepeatActions(1, repetitionsCount));
        }
예제 #29
0
        /// <summary>
        /// Reads content of a MIDI meta event.
        /// </summary>
        /// <param name="reader">Reader to read the content with.</param>
        /// <param name="settings">Settings according to which the event's content must be read.</param>
        /// <param name="size">Size of the event's content.</param>
        /// <exception cref="ArgumentOutOfRangeException">Text event cannot be read since the size is
        /// negative number.</exception>
        protected sealed override void ReadContent(MidiReader reader, ReadingSettings settings, int size)
        {
            ThrowIfArgument.IsNegative(nameof(size),
                                       size,
                                       "Text event cannot be read since the size is negative number.");

            if (size == 0)
            {
                return;
            }

            var bytes    = reader.ReadBytes(size);
            var encoding = settings.TextEncoding ?? SmfUtilities.DefaultEncoding;

            Text = encoding.GetString(bytes);
        }
예제 #30
0
        // TODO: improve performance
        /// <summary>
        /// Converts an instance of the <see cref="MidiEvent"/> to bytes array using the specified
        /// minimum size of resulting array.
        /// </summary>
        /// <param name="midiEvent">MIDI event to convert.</param>
        /// <param name="minSize">Minimum size of bytes array representing <paramref name="midiEvent"/>.</param>
        /// <returns>Array of bytes representing <paramref name="midiEvent"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="midiEvent"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="minSize"/> is negative.</exception>
        public byte[] Convert(MidiEvent midiEvent, int minSize)
        {
            ThrowIfArgument.IsNull(nameof(midiEvent), midiEvent);
            ThrowIfArgument.IsNegative(nameof(minSize), minSize, "Min size is negative.");

            _dataBytesStream.Seek(0, SeekOrigin.Begin);

            var eventWriter = EventWriterFactory.GetWriter(midiEvent);

            eventWriter.Write(midiEvent, _midiWriter, WritingSettings, true);

            var buffer   = _dataBytesStream.GetBuffer();
            var dataSize = _dataBytesStream.Position;
            var result   = new byte[Math.Max(dataSize, minSize)];

            Array.Copy(buffer, 0, result, 0, dataSize);

            return(result);
        }