示例#1
0
        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)));
            }
        }
示例#2
0
        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());
        }
示例#4
0
        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;
                }
            }
        }
示例#5
0
        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;
                }
            };
        }
示例#6
0
        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;
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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;
                }
            };
        }