MidiMessage ReadMessage(int deltaTime) { byte b = PeekByte(); running_status = b < 0x80 ? running_status : ReadByte(); int len; switch (running_status) { case MidiEvent.SysEx1: case MidiEvent.SysEx2: case MidiEvent.Meta: byte metaType = running_status == MidiEvent.Meta ? ReadByte() : (byte)0; len = ReadVariableLength(); byte[] args = new byte[len]; if (len > 0) { ReadBytes(args); } return(new MidiMessage(deltaTime, new MidiEvent(running_status, metaType, 0, args, 0, args.Length))); default: int value = running_status; value += ReadByte() << 8; if (MidiEvent.FixedDataSize(running_status) == 2) { value += ReadByte() << 16; } return(new MidiMessage(deltaTime, new MidiEvent(value))); } }
public static IEnumerable <MidiEvent> Convert(byte[] bytes, int index, int size) { int i = index; int end = index + size; while (i < end) { if (bytes [i] == 0xF0) { yield return(new MidiEvent(0xF0, 0, 0, bytes, index, size)); i += size; } else { var z = MidiEvent.FixedDataSize(bytes [i]); if (end < i + z) { throw new Exception(string.Format( "Received data was incomplete to build MIDI status message for '{0:X}' status.", bytes [i])); } yield return(new MidiEvent(bytes [i], (byte)(z > 0 ? bytes [i + 1] : 0), (byte)(z > 1 ? bytes [i + 2] : 0), null, 0, 0)); i += z + 1; } } }
private byte[] GetRawData() { List <byte> bytes = new List <byte>(); switch (Event.EventType) { case MidiEvent.SysEx1: case MidiEvent.SysEx2: bytes.Add(Event.StatusByte); bytes.AddRange(Event.ExtraData.Skip(Event.ExtraDataOffset).Take(Event.ExtraDataLength)); break; case MidiEvent.Meta: // do nothing. break; case MidiEvent.NoteOn: case MidiEvent.NoteOff: default: var size = MidiEvent.FixedDataSize(Event.StatusByte); bytes.Add(Event.StatusByte); if (size >= 1) { bytes.Add(Event.Msb); } if (size >= 2) { bytes.Add(Event.Lsb); } break; } return(bytes.ToArray()); }
public static IEnumerable <MidiEvent> Convert(byte[] bytes, int index, int size) { int i = index; int end = index + size; while (i < end) { if (bytes[i] == 0xF0) { var tmp = new byte [size]; Array.Copy(bytes, i, tmp, 0, tmp.Length); yield return(new MidiEvent(0xF0, 0, 0, tmp)); i += size; } else { if (end < i + MidiEvent.FixedDataSize(bytes [i])) { throw new Exception(string.Format("Received data was incomplete to build MIDI status message for '{0:X}' status.", bytes[i])); } var z = MidiEvent.FixedDataSize(bytes[i]); yield return(new MidiEvent(bytes [i], bytes [i + 1], (byte)(z > 1 ? bytes [i + 2] : 0), null)); i += z + 1; } } }
public MidiPlayer(MidiMusic music, IMidiOutput output, IMidiTimeManager timeManager) { if (music == null) { throw new ArgumentNullException("music"); } if (output == null) { throw new ArgumentNullException("output"); } if (timeManager == null) { throw new ArgumentNullException("timeManager"); } this.output = output; player = new MidiSyncPlayer(music, timeManager); EventReceived += (m) => { switch (m.EventType) { case MidiEvent.NoteOn: case MidiEvent.NoteOff: if (channel_mask != null && channel_mask [m.Channel]) { return; // ignore messages for the masked channel. } goto default; case MidiEvent.SysEx1: case MidiEvent.SysEx2: if (buffer.Length <= m.Data.Length) { buffer = new byte [buffer.Length * 2]; } buffer [0] = m.StatusByte; Array.Copy(m.Data, 0, buffer, 1, m.Data.Length); output.Send(buffer, 0, m.Data.Length + 1, 0); break; case MidiEvent.Meta: // do nothing. break; default: var size = MidiEvent.FixedDataSize(m.StatusByte); buffer [0] = m.StatusByte; buffer [1] = m.Msb; buffer [2] = m.Lsb; output.Send(buffer, 0, size + 1, 0); break; } }; }
public void WriteTrack(MidiTrack track) { stream.Write(Encoding.UTF8.GetBytes("MTrk"), 0, 4); WriteInt(GetTrackDataSize(track)); byte running_status = 0; foreach (MidiMessage e in track.Messages) { Write7BitVariableInteger(e.DeltaTime); switch (e.Event.EventType) { case MidiEvent.Meta: meta_event_writer(false, e, stream); break; case MidiEvent.SysEx1: case MidiEvent.SysEx2: stream.WriteByte(e.Event.EventType); Write7BitVariableInteger(e.Event.ExtraDataLength); stream.Write(e.Event.ExtraData, e.Event.ExtraDataOffset, e.Event.ExtraDataLength); break; default: if (DisableRunningStatus || e.Event.StatusByte != running_status) { stream.WriteByte(e.Event.StatusByte); } int len = MidiEvent.FixedDataSize(e.Event.EventType); stream.WriteByte(e.Event.Msb); if (len > 1) { stream.WriteByte(e.Event.Lsb); } if (len > 2) { throw new Exception("Unexpected data size: " + len); } break; } running_status = e.Event.StatusByte; } }
int GetTrackDataSize(MidiTrack track) { int size = 0; byte running_status = 0; foreach (MidiMessage e in track.Messages) { // delta time size += GetVariantLength(e.DeltaTime); // arguments switch (e.Event.EventType) { case MidiEvent.Meta: size += meta_event_writer(true, e, null); break; case MidiEvent.SysEx1: case MidiEvent.SysEx2: size++; size += GetVariantLength(e.Event.ExtraDataLength); size += e.Event.ExtraDataLength; break; default: // message type & channel if (DisableRunningStatus || running_status != e.Event.StatusByte) { size++; } size += MidiEvent.FixedDataSize(e.Event.EventType); break; } running_status = e.Event.StatusByte; } return(size); }
public MidiPlayer(MidiMusic music, IMidiOutput output, IMidiPlayerTimeManager timeManager) { if (music == null) { throw new ArgumentNullException("music"); } if (output == null) { throw new ArgumentNullException("output"); } if (timeManager == null) { throw new ArgumentNullException("timeManager"); } this.music = music; this.output = output; messages = SmfTrackMerger.Merge(music).Tracks [0].Messages; player = new MidiEventLooper(messages, timeManager, music.DeltaTimeSpec); player.Starting += () => { // all control reset on all channels. for (int i = 0; i < 16; i++) { buffer [0] = (byte)(i + 0xB0); buffer [1] = 0x79; buffer [2] = 0; output.Send(buffer, 0, 3, 0); } }; EventReceived += (m) => { switch (m.EventType) { case MidiEvent.NoteOn: case MidiEvent.NoteOff: if (channel_mask != null && channel_mask [m.Channel]) { return; // ignore messages for the masked channel. } goto default; case MidiEvent.SysEx1: case MidiEvent.SysEx2: if (buffer.Length <= m.Data.Length) { buffer = new byte [buffer.Length * 2]; } buffer [0] = m.StatusByte; Array.Copy(m.Data, 0, buffer, 1, m.Data.Length); output.Send(buffer, 0, m.Data.Length + 1, 0); break; case MidiEvent.Meta: // do nothing. break; default: var size = MidiEvent.FixedDataSize(m.StatusByte); buffer [0] = m.StatusByte; buffer [1] = m.Msb; buffer [2] = m.Lsb; output.Send(buffer, 0, size + 1, 0); break; } }; }