/// <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()); }
/// <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); }
/// <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); }
/// <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)); }
/// <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))); }
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()); }
/// <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); }
/// <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]; }
/// <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); }
/// <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; }
/// <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); }
/// <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); }
/// <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))); }
/// <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); }
/// <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)); }
/// <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; }
/// <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 }); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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; }
/// <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)); }
/// <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)); }
/// <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); }
// 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); }