internal override void Read(MidiReader reader, ReadingSettings settings, int size) { var data = reader.ReadByte(); var midiTimeCodeComponent = (byte)data.GetHead(); if (!Enum.IsDefined(typeof(MidiTimeCodeComponent), midiTimeCodeComponent)) { throw new InvalidMidiTimeCodeComponentException(midiTimeCodeComponent); } Component = (MidiTimeCodeComponent)midiTimeCodeComponent; var componentValue = data.GetTail(); if (componentValue > ComponentValueMasks[Component]) { switch (settings.InvalidSystemCommonEventParameterValuePolicy) { case InvalidSystemCommonEventParameterValuePolicy.Abort: throw new InvalidSystemCommonEventParameterValueException(EventType, $"{nameof(ComponentValue)} (component is {Component})", componentValue); case InvalidSystemCommonEventParameterValuePolicy.SnapToLimits: componentValue = (FourBitNumber)ComponentValueMasks[Component]; break; } } ComponentValue = componentValue; }
/// <summary> /// Reads chunk from the <see cref="MidiReader"/>'s underlying stream according to /// specified <see cref="ReadingSettings"/>. /// </summary> /// <param name="reader">Reader to read the chunk's data with.</param> /// <param name="settings">Settings according to which the chunk's data must be read.</param> /// <exception cref="ObjectDisposedException">Method was called after <paramref name="reader"/> /// was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the <paramref name="reader"/>'s /// underlying stream.</exception> /// <exception cref="InvalidChunkSizeException">Actual chunk's size differs from the one declared /// in its header.</exception> /// <exception cref="NotEnoughBytesException">Size of the chunk cannot be read since the reader's /// underlying stream doesn't have enough bytes.</exception> internal void Read(MidiReader reader, ReadingSettings settings) { // LOGREAD: c a // LOGREAD: c s a var size = reader.ReadDword(); // LOGREAD: c s z <{size}> var readerPosition = reader.Position; ReadContent(reader, settings, size); var bytesReadCount = reader.Position - readerPosition; if (settings.InvalidChunkSizePolicy == InvalidChunkSizePolicy.Abort && bytesReadCount != size) { throw new InvalidChunkSizeException(ChunkId, size, bytesReadCount); } // Skip unread bytes var bytesUnread = size - bytesReadCount; if (bytesUnread > 0) { reader.Position += Math.Min(bytesUnread, reader.Length); } // LOGREAD: c z <{ToString()}> }
/// <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> /// <exception cref="InvalidChannelEventParameterValueException">An invalid value for channel /// event's parameter was encountered.</exception> internal sealed override void Read(MidiReader reader, ReadingSettings settings, int size) { for (int i = 0; i < _parameters.Length; i++) { var parameter = reader.ReadByte(); if (parameter > SevenBitNumber.MaxValue) { switch (settings.InvalidChannelEventParameterValuePolicy) { case InvalidChannelEventParameterValuePolicy.Abort: throw new InvalidChannelEventParameterValueException($"{parameter} is invalid value for channel event's parameter.", parameter); case InvalidChannelEventParameterValuePolicy.ReadValid: parameter &= SevenBitNumber.MaxValue; break; case InvalidChannelEventParameterValuePolicy.SnapToLimits: parameter = SevenBitNumber.MaxValue; break; } } _parameters[i] = (SevenBitNumber)parameter; } }
/// <summary> /// Reads content of a <see cref="UnknownChunk"/>. /// </summary> /// <remarks> /// Content of an <see cref="UnknownChunk"/> is array of bytes. /// </remarks> /// <param name="reader">Reader to read the chunk's content with.</param> /// <param name="settings">Settings according to which the chunk's content must be read.</param> /// <param name="size">Expected size of the content taken from the chunk's header.</param> /// <exception cref="ObjectDisposedException">Method was called after the reader's underlying stream was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the reader's underlying stream.</exception> protected override void ReadContent(MidiReader reader, ReadingSettings settings, uint size) { if (size == 0) { switch (settings.ZeroLengthDataPolicy) { case ZeroLengthDataPolicy.ReadAsEmptyObject: Data = new byte[0]; break; case ZeroLengthDataPolicy.ReadAsNull: Data = null; break; } return; } var availableSize = reader.Length - reader.Position; var bytesCount = availableSize < size ? availableSize : size; var bytes = reader.ReadBytes((int)Math.Min(bytesCount, int.MaxValue)); if (bytes.Length < size && settings.NotEnoughBytesPolicy == NotEnoughBytesPolicy.Abort) { throw new NotEnoughBytesException( "Unknown chunk's data cannot be read since the reader's underlying stream doesn't have enough bytes.", size, bytes.Length); } Data = 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()); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var statusByte = reader.ReadByte(); var size = reader.ReadVlqNumber(); // Type eventType; var midiEvent = TryGetEventType(settings.CustomMetaEventTypes, statusByte, out eventType) ? (MetaEvent)Activator.CreateInstance(eventType) : new UnknownMetaEvent(statusByte); // var readerPosition = reader.Position; midiEvent.Read(reader, settings, size); var bytesRead = reader.Position - readerPosition; var bytesUnread = size - bytesRead; if (bytesUnread > 0) { reader.Position += bytesUnread; } return(midiEvent); }
/// <summary> /// Reads content of a <see cref="TrackChunk"/>. /// </summary> /// <remarks> /// Content of a <see cref="TrackChunk"/> is collection of MIDI events. /// </remarks> /// <param name="reader">Reader to read the chunk's content with.</param> /// <param name="settings">Settings according to which the chunk's content must be read.</param> /// <param name="size">Expected size of the content taken from the chunk's header.</param> /// <exception cref="ObjectDisposedException">Method was called after the writer's underlying stream /// was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the writer's underlying stream.</exception> /// <exception cref="UnexpectedRunningStatusException">Unexpected running status is encountered.</exception> /// <exception cref="UnknownChannelEventException">Reader has encountered an unknown channel event.</exception> /// <exception cref="NotEnoughBytesException">Not enough bytes to read an event.</exception> /// <exception cref="InvalidChannelEventParameterValueException">Value of a channel event's parameter just /// read is invalid.</exception> /// <exception cref="MissedEndOfTrackEventException">Track chunk doesn't end with End Of Track event.</exception> protected override void ReadContent(MidiReader reader, ReadingSettings settings, uint size) { var endReaderPosition = reader.Position + size; var endOfTrackPresented = false; byte?currentChannelEventStatusByte = null; // while (reader.Position < endReaderPosition && !reader.EndReached) { var midiEvent = ReadEvent(reader, settings, ref currentChannelEventStatusByte); if (midiEvent is EndOfTrackEvent) { endOfTrackPresented = true; break; } Events.Add(midiEvent); } // if (settings.MissedEndOfTrackPolicy == MissedEndOfTrackPolicy.Abort && !endOfTrackPresented) { throw new MissedEndOfTrackEventException(); } }
/// <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); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var statusByte = currentStatusByte.GetHead(); var channel = currentStatusByte.GetTail(); ChannelEvent channelEvent = null; switch (statusByte) { case EventStatusBytes.Channel.NoteOff: channelEvent = new NoteOffEvent(); break; case EventStatusBytes.Channel.NoteOn: channelEvent = new NoteOnEvent(); break; case EventStatusBytes.Channel.ControlChange: channelEvent = new ControlChangeEvent(); break; case EventStatusBytes.Channel.PitchBend: channelEvent = new PitchBendEvent(); break; case EventStatusBytes.Channel.ChannelAftertouch: channelEvent = new ChannelAftertouchEvent(); break; case EventStatusBytes.Channel.ProgramChange: channelEvent = new ProgramChangeEvent(); break; case EventStatusBytes.Channel.NoteAftertouch: channelEvent = new NoteAftertouchEvent(); break; default: ReactOnUnknownChannelEvent(statusByte, channel, reader, settings); return(null); } channelEvent.Read(reader, settings, MidiEvent.UnknownContentSize); channelEvent.Channel = channel; var noteOnEvent = channelEvent as NoteOnEvent; if (noteOnEvent != null && settings.SilentNoteOnPolicy == SilentNoteOnPolicy.NoteOff && noteOnEvent.Velocity == 0) { channelEvent = new NoteOffEvent { DeltaTime = noteOnEvent.DeltaTime, Channel = noteOnEvent.Channel, NoteNumber = noteOnEvent.NoteNumber } } ; return(channelEvent); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var statusByte = currentStatusByte.GetHead(); var channel = currentStatusByte.GetTail(); Type eventType; if (!StandardEventTypes.Channel.TryGetType(statusByte, out eventType)) { throw new UnknownChannelEventException(statusByte, channel); } var channelEvent = (ChannelEvent)Activator.CreateInstance(eventType); channelEvent.Read(reader, settings, MidiEvent.UnknownContentSize); channelEvent.Channel = channel; var noteOnEvent = channelEvent as NoteOnEvent; if (noteOnEvent != null && settings.SilentNoteOnPolicy == SilentNoteOnPolicy.NoteOff && noteOnEvent.Velocity == 0) { channelEvent = new NoteOffEvent { DeltaTime = noteOnEvent.DeltaTime, Channel = noteOnEvent.Channel, NoteNumber = noteOnEvent.NoteNumber } } ; return(channelEvent); } #endregion }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var size = reader.ReadVlqNumber(); // SysExEvent sysExEvent = null; switch (currentStatusByte) { case EventStatusBytes.Global.NormalSysEx: sysExEvent = new NormalSysExEvent(); break; case EventStatusBytes.Global.EscapeSysEx: sysExEvent = new EscapeSysExEvent(); break; } if (sysExEvent == null) { Debug.Fail("Unknown SysEx event."); } // sysExEvent.Read(reader, settings, size); return(sysExEvent); }
/// <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> /// 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> /// Reads content of a <see cref="TrackChunk"/>. /// </summary> /// <remarks> /// Content of a <see cref="TrackChunk"/> is collection of MIDI events. /// </remarks> /// <param name="reader">Reader to read the chunk's content with.</param> /// <param name="settings">Settings according to which the chunk's content must be read.</param> /// <param name="size">Expected size of the content taken from the chunk's header.</param> /// <exception cref="ObjectDisposedException">Method was called after the writer's underlying stream /// was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the writer's underlying stream.</exception> /// <exception cref="UnexpectedRunningStatusException">Unexpected running status is encountered.</exception> /// <exception cref="UnknownChannelEventException">Reader has encountered an unknown channel event.</exception> /// <exception cref="NotEnoughBytesException">Not enough bytes to read an event.</exception> /// <exception cref="InvalidChannelEventParameterValueException">Value of a channel event's parameter just /// read is invalid.</exception> /// <exception cref="MissedEndOfTrackEventException">Track chunk doesn't end with End Of Track event.</exception> protected override void ReadContent(MidiReader reader, ReadingSettings settings, uint size) { var useReadingHandlers = settings.UseReadingHandlers; if (useReadingHandlers) { foreach (var handler in settings.TrackChunkReadingHandlers) { handler.OnStartTrackChunkContentReading(this); } } // var endReaderPosition = reader.Position + size; var endOfTrackPresented = false; byte?currentChannelEventStatusByte = null; long absoluteTime = 0; // while (reader.Position < endReaderPosition && !reader.EndReached) { long deltaTime; var midiEvent = ReadEvent(reader, settings, ref currentChannelEventStatusByte, out deltaTime); if (midiEvent is EndOfTrackEvent) { endOfTrackPresented = true; break; } absoluteTime += deltaTime; if (midiEvent == null) { continue; } if (useReadingHandlers) { foreach (var handler in settings.EventReadingHandlers) { handler.OnFinishEventReading(midiEvent, absoluteTime); } } Events.Add(midiEvent); } // if (settings.MissedEndOfTrackPolicy == MissedEndOfTrackPolicy.Abort && !endOfTrackPresented) { throw new MissedEndOfTrackEventException(); } }
/// <summary> /// Reads an event from the reader's underlying stream. /// </summary> /// <param name="reader">Reader to read an event.</param> /// <param name="settings">Settings according to which an event must be read.</param> /// <param name="channelEventStatusByte">Current channel event status byte used as running status.</param> /// <returns>Instance of the <see cref="MidiEvent"/> representing a MIDI event.</returns> /// <exception cref="ObjectDisposedException">Method was called after the writer's underlying stream /// was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the writer's underlying stream.</exception> /// <exception cref="UnexpectedRunningStatusException">Unexpected running status is encountered.</exception> /// <exception cref="UnknownChannelEventException">Reader has encountered an unknown channel event.</exception> /// <exception cref="NotEnoughBytesException">Not enough bytes to read an event.</exception> /// <exception cref="InvalidChannelEventParameterValueException">Value of a channel event's parameter just /// read is invalid.</exception> private MidiEvent ReadEvent(MidiReader reader, ReadingSettings settings, ref byte?channelEventStatusByte) { var deltaTime = reader.ReadVlqLongNumber(); if (deltaTime < 0) { deltaTime = 0; } // var statusByte = reader.ReadByte(); if (statusByte <= SevenBitNumber.MaxValue) { if (channelEventStatusByte == null) { throw new UnexpectedRunningStatusException(); } statusByte = channelEventStatusByte.Value; reader.Position--; } // var eventReader = EventReaderFactory.GetReader(statusByte, smfOnly: true); var midiEvent = eventReader.Read(reader, settings, statusByte); // if (settings.SilentNoteOnPolicy == SilentNoteOnPolicy.NoteOff) { var noteOnEvent = midiEvent as NoteOnEvent; if (noteOnEvent?.Velocity == 0) { midiEvent = new NoteOffEvent { DeltaTime = noteOnEvent.DeltaTime, Channel = noteOnEvent.Channel, NoteNumber = noteOnEvent.NoteNumber }; } } // if (midiEvent is ChannelEvent) { channelEventStatusByte = statusByte; } // midiEvent.DeltaTime = deltaTime; return(midiEvent); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { Type eventType; StandardEventTypes.SystemRealTime.TryGetType(currentStatusByte, out eventType); var systemRealTimeEvent = (SystemRealTimeEvent)Activator.CreateInstance(eventType); systemRealTimeEvent.Read(reader, settings, MidiEvent.UnknownContentSize); return(systemRealTimeEvent); }
/// <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> protected override void ReadContent(MidiReader reader, ReadingSettings settings, int size) { Numerator = reader.ReadByte(); Denominator = (byte)Math.Pow(2, reader.ReadByte()); if (size >= 4) { ClocksPerClick = reader.ReadByte(); ThirtySecondNotesPerBeat = reader.ReadByte(); } }
/// <summary> /// Reads content of a <see cref="HeaderChunk"/>. /// </summary> /// <remarks> /// Content of a <see cref="HeaderChunk"/> is format of the file, number of track chunks and time division. /// </remarks> /// <param name="reader">Reader to read the chunk's content with.</param> /// <param name="settings">Settings according to which the chunk's content must be read.</param> /// <param name="size">Expected size of the content taken from the chunk's header.</param> /// <exception cref="ObjectDisposedException">Method was called after the reader's underlying stream was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the reader's underlying stream.</exception> /// <exception cref="UnknownFileFormatException">The header chunk contains unknown file format and /// <see cref="ReadingSettings.UnknownFileFormatPolicy"/> property of the <paramref name="settings"/> set to /// <see cref="UnknownFileFormatPolicy.Abort"/>.</exception> protected override void ReadContent(MidiReader reader, ReadingSettings settings, uint size) { var fileFormat = reader.ReadWord(); if (settings.UnknownFileFormatPolicy == UnknownFileFormatPolicy.Abort && !Enum.IsDefined(typeof(MidiFileFormat), fileFormat)) { throw new UnknownFileFormatException(fileFormat); } FileFormat = fileFormat; TracksNumber = reader.ReadWord(); TimeDivision = TimeDivisionFactory.GetTimeDivision(reader.ReadInt16()); }
private MidiEvent ReadEvent(MidiReader reader, ReadingSettings settings, ref byte?channelEventStatusByte, out long deltaTime) { // LOGREAD: e a // LOGREAD: dt a deltaTime = reader.ReadVlqLongNumber(); if (deltaTime < 0) { deltaTime = 0; } // LOGREAD: dt z <{deltaTime}> // LOGREAD: m a var statusByte = reader.ReadByte(); if (statusByte <= SevenBitNumber.MaxValue) { if (channelEventStatusByte == null) { throw new UnexpectedRunningStatusException(); } statusByte = channelEventStatusByte.Value; reader.Position--; } // var eventReader = EventReaderFactory.GetReader(statusByte, smfOnly: true); var midiEvent = eventReader.Read(reader, settings, statusByte); // if (midiEvent is ChannelEvent) { channelEventStatusByte = statusByte; } // if (midiEvent != null) { midiEvent._deltaTime = deltaTime; } // LOGREAD: m z // LOGREAD: e z <{midiEvent}> return(midiEvent); }
/// <summary> /// Reads content of a <see cref="UnknownChunk"/>. /// </summary> /// <remarks> /// Content of an <see cref="UnknownChunk"/> is array of bytes. /// </remarks> /// <param name="reader">Reader to read the chunk's content with.</param> /// <param name="settings">Settings according to which the chunk's content must be read.</param> /// <param name="size">Expected size of the content taken from the chunk's header.</param> /// <exception cref="ObjectDisposedException">Method was called after the reader's underlying stream was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the reader's underlying stream.</exception> protected override void ReadContent(MidiReader reader, ReadingSettings settings, uint size) { var availableSize = reader.Length - reader.Position; var bytes = reader.ReadBytes((int)(availableSize < size ? availableSize : size)); if (bytes.Length < size && settings.NotEnoughBytesPolicy == NotEnoughBytesPolicy.Abort) { throw new NotEnoughBytesException("Chunk's data cannot be read since the reader's underlying stream doesn't have enough bytes.", size, bytes.Length); } Data = bytes; }
/// <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> protected override void ReadContent(MidiReader reader, ReadingSettings settings, int size) { var invalidMetaEventParameterValuePolicy = settings.InvalidMetaEventParameterValuePolicy; Key = (sbyte)ProcessValue(reader.ReadSByte(), nameof(Key), MinKey, MaxKey, invalidMetaEventParameterValuePolicy); Scale = (byte)ProcessValue(reader.ReadByte(), nameof(Scale), MinScale, MaxScale, invalidMetaEventParameterValuePolicy); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var statusByte = currentStatusByte.GetHead(); var channel = currentStatusByte.GetTail(); Type eventType; if (!StandardEventTypes.Channel.TryGetType(statusByte, out eventType)) { throw new UnknownChannelEventException(statusByte, channel); } var channelEvent = (ChannelEvent)Activator.CreateInstance(eventType); channelEvent.Read(reader, settings, MidiEvent.UnknownContentSize); channelEvent.Channel = channel; return(channelEvent); }
internal override void Read(MidiReader reader, ReadingSettings settings, int size) { var number = reader.ReadByte(); if (number > SevenBitNumber.MaxValue) { switch (settings.InvalidSystemCommonEventParameterValuePolicy) { case InvalidSystemCommonEventParameterValuePolicy.Abort: throw new InvalidSystemCommonEventParameterValueException(GetType(), nameof(Number), number); case InvalidSystemCommonEventParameterValuePolicy.SnapToLimits: number = SevenBitNumber.MaxValue; break; } } Number = (SevenBitNumber)number; }
/// <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 ?? SmfConstants.DefaultTextEncoding; var decodeTextCallback = settings.DecodeTextCallback; Text = decodeTextCallback != null ? decodeTextCallback(bytes, settings) : encoding.GetString(bytes); }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var size = reader.ReadVlqNumber(); // Type eventType; var midiEvent = StandardEventTypes.SysEx.TryGetType(currentStatusByte, out eventType) ? (SysExEvent)Activator.CreateInstance(eventType) : null; if (midiEvent == null) { Debug.Fail("Unknown SysEx event."); } // midiEvent.Read(reader, settings, size); return(midiEvent); }
/// <summary> /// Reads channel event's data byte using the specified reader and settings. /// </summary> /// <param name="reader">Reader to read data byte with.</param> /// <param name="settings">Settings according to which a data byte should be read and processed.</param> /// <returns>A data byte read with <paramref name="reader"/>.</returns> protected byte ReadDataByte(MidiReader reader, ReadingSettings settings) { var value = reader.ReadByte(); if (value > SevenBitNumber.MaxValue) { switch (settings.InvalidChannelEventParameterValuePolicy) { case InvalidChannelEventParameterValuePolicy.Abort: throw new InvalidChannelEventParameterValueException(EventType, value); case InvalidChannelEventParameterValuePolicy.ReadValid: value &= SevenBitNumber.MaxValue; break; case InvalidChannelEventParameterValuePolicy.SnapToLimits: value = SevenBitNumber.MaxValue; break; } } return(value); }
/// <summary> /// Reads chunk from the <see cref="MidiReader"/>'s underlying stream according to /// specified <see cref="ReadingSettings"/>. /// </summary> /// <param name="reader">Reader to read the chunk's data with.</param> /// <param name="settings">Settings according to which the chunk's data must be read.</param> /// <exception cref="ObjectDisposedException">Method was called after <paramref name="reader"/> /// was disposed.</exception> /// <exception cref="IOException">An I/O error occurred on the <paramref name="reader"/>'s /// underlying stream.</exception> /// <exception cref="InvalidChunkSizeException">Actual chunk's size differs from the one declared /// in its header.</exception> /// <exception cref="NotEnoughBytesException">Size of the chunk cannot be read since the reader's /// underlying stream doesn't have enough bytes.</exception> internal void Read(MidiReader reader, ReadingSettings settings) { var size = reader.ReadDword(); var readerPosition = reader.Position; ReadContent(reader, settings, size); var bytesRead = reader.Position - readerPosition; if (settings.InvalidChunkSizePolicy == InvalidChunkSizePolicy.Abort && bytesRead != size) { throw new InvalidChunkSizeException(size, bytesRead); } // Skip unread bytes var bytesUnread = size - bytesRead; if (bytesUnread > 0) { reader.Position += Math.Min(bytesUnread, reader.Length); } }
public MidiEvent Read(MidiReader reader, ReadingSettings settings, byte currentStatusByte) { var statusByte = reader.ReadByte(); var size = reader.ReadVlqNumber(); // MetaEvent metaEvent; switch (statusByte) { case EventStatusBytes.Meta.Lyric: metaEvent = new LyricEvent(); break; case EventStatusBytes.Meta.SetTempo: metaEvent = new SetTempoEvent(); break; case EventStatusBytes.Meta.Text: metaEvent = new TextEvent(); break; case EventStatusBytes.Meta.SequenceTrackName: metaEvent = new SequenceTrackNameEvent(); break; case EventStatusBytes.Meta.PortPrefix: metaEvent = new PortPrefixEvent(); break; case EventStatusBytes.Meta.TimeSignature: metaEvent = new TimeSignatureEvent(); break; case EventStatusBytes.Meta.SequencerSpecific: metaEvent = new SequencerSpecificEvent(); break; case EventStatusBytes.Meta.KeySignature: metaEvent = new KeySignatureEvent(); break; case EventStatusBytes.Meta.Marker: metaEvent = new MarkerEvent(); break; case EventStatusBytes.Meta.ChannelPrefix: metaEvent = new ChannelPrefixEvent(); break; case EventStatusBytes.Meta.InstrumentName: metaEvent = new InstrumentNameEvent(); break; case EventStatusBytes.Meta.CopyrightNotice: metaEvent = new CopyrightNoticeEvent(); break; case EventStatusBytes.Meta.SmpteOffset: metaEvent = new SmpteOffsetEvent(); break; case EventStatusBytes.Meta.DeviceName: metaEvent = new DeviceNameEvent(); break; case EventStatusBytes.Meta.CuePoint: metaEvent = new CuePointEvent(); break; case EventStatusBytes.Meta.ProgramName: metaEvent = new ProgramNameEvent(); break; case EventStatusBytes.Meta.SequenceNumber: metaEvent = new SequenceNumberEvent(); break; case EventStatusBytes.Meta.EndOfTrack: metaEvent = new EndOfTrackEvent(); break; default: { Type eventType = null; metaEvent = settings.CustomMetaEventTypes?.TryGetType(statusByte, out eventType) == true && IsMetaEventType(eventType) ? (MetaEvent)Activator.CreateInstance(eventType) : new UnknownMetaEvent(statusByte); } break; } // var readerPosition = reader.Position; metaEvent.Read(reader, settings, size); var bytesRead = reader.Position - readerPosition; var bytesUnread = size - bytesRead; if (bytesUnread > 0) { reader.Position += bytesUnread; } return(metaEvent); }
/// <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 abstract void Read(MidiReader reader, ReadingSettings settings, int size);
internal override sealed void Read(MidiReader reader, ReadingSettings settings, int size) { }