Пример #1
0
        /** Parse a single Midi track into a list of MidiEvents.
         * Entering this function, the file offset should be at the start of
         * the MTrk header.  Upon exiting, the file offset should be at the
         * start of the next MTrk header.
         */
        private List<MidiEvent> ReadTrack(MidiFileReader file)
        {
            List<MidiEvent> result = new List<MidiEvent>(20);
            int starttime = 0;
            string id = file.ReadAscii(4);

            if (id != "MTrk") {
            throw new MidiFileException("Bad MTrk header", file.GetOffset() - 4);
            }
            int tracklen = file.ReadInt();
            int trackend = tracklen + file.GetOffset();

            int eventflag = 0;

            while (file.GetOffset() < trackend) {

            // If the midi file is truncated here, we can still recover.
            // Just return what we've parsed so far.

            int startoffset, deltatime;
            byte peekevent;
            try {
                startoffset = file.GetOffset();
                deltatime = file.ReadVarlen();
                starttime += deltatime;
                peekevent = file.Peek();
            }
            catch (MidiFileException e) {
                return result;
            }

            MidiEvent mevent = new MidiEvent();
            result.Add(mevent);
            mevent.DeltaTime = deltatime;
            mevent.StartTime = starttime;

            if (peekevent >= EventNoteOff) {
                mevent.HasEventflag = true;
                eventflag = file.ReadByte();
            }

            // Console.WriteLine("offset {0}: event {1} {2} start {3} delta {4}",
            //                   startoffset, eventflag, EventName(eventflag),
            //                   starttime, mevent.DeltaTime);

            if (eventflag >= EventNoteOn && eventflag < EventNoteOn + 16) {
                mevent.EventFlag = EventNoteOn;
                mevent.Channel = (byte)(eventflag - EventNoteOn);
                mevent.Notenumber = file.ReadByte();
                mevent.Velocity = file.ReadByte();
            }
            else if (eventflag >= EventNoteOff && eventflag < EventNoteOff + 16) {
                mevent.EventFlag = EventNoteOff;
                mevent.Channel = (byte)(eventflag - EventNoteOff);
                mevent.Notenumber = file.ReadByte();
                mevent.Velocity = file.ReadByte();
            }
            else if (eventflag >= EventKeyPressure &&
                     eventflag < EventKeyPressure + 16) {
                mevent.EventFlag = EventKeyPressure;
                mevent.Channel = (byte)(eventflag - EventKeyPressure);
                mevent.Notenumber = file.ReadByte();
                mevent.KeyPressure = file.ReadByte();
            }
            else if (eventflag >= EventControlChange &&
                     eventflag < EventControlChange + 16) {
                mevent.EventFlag = EventControlChange;
                mevent.Channel = (byte)(eventflag - EventControlChange);
                mevent.ControlNum = file.ReadByte();
                mevent.ControlValue = file.ReadByte();
            }
            else if (eventflag >= EventProgramChange &&
                     eventflag < EventProgramChange + 16) {
                mevent.EventFlag = EventProgramChange;
                mevent.Channel = (byte)(eventflag - EventProgramChange);
                mevent.Instrument = file.ReadByte();
            }
            else if (eventflag >= EventChannelPressure &&
                     eventflag < EventChannelPressure + 16) {
                mevent.EventFlag = EventChannelPressure;
                mevent.Channel = (byte)(eventflag - EventChannelPressure);
                mevent.ChanPressure = file.ReadByte();
            }
            else if (eventflag >= EventPitchBend &&
                     eventflag < EventPitchBend + 16) {
                mevent.EventFlag = EventPitchBend;
                mevent.Channel = (byte)(eventflag - EventPitchBend);
                mevent.PitchBend = file.ReadShort();
            }
            else if (eventflag == SysexEvent1) {
                mevent.EventFlag = SysexEvent1;
                mevent.Metalength = file.ReadVarlen();
                mevent.Value = file.ReadBytes(mevent.Metalength);
            }
            else if (eventflag == SysexEvent2) {
                mevent.EventFlag = SysexEvent2;
                mevent.Metalength = file.ReadVarlen();
                mevent.Value = file.ReadBytes(mevent.Metalength);
            }
            else if (eventflag == MetaEvent) {
                mevent.EventFlag = MetaEvent;
                mevent.Metaevent = file.ReadByte();
                mevent.Metalength = file.ReadVarlen();
                mevent.Value = file.ReadBytes(mevent.Metalength);
                if (mevent.Metaevent == MetaEventTimeSignature) {
                    if (mevent.Metalength < 2) {
                        // throw new MidiFileException(
                        //  "Meta Event Time Signature len == " + mevent.Metalength  +
                        //  " != 4", file.GetOffset());
                        mevent.Numerator = (byte)0;
                        mevent.Denominator = (byte)4;
                    }
                    else if (mevent.Metalength >= 2 && mevent.Metalength < 4) {
                        mevent.Numerator = (byte)mevent.Value[0];
                        mevent.Denominator = (byte)System.Math.Pow(2, mevent.Value[1]);
                    }
                    else {
                        mevent.Numerator = (byte)mevent.Value[0];
                        mevent.Denominator = (byte)System.Math.Pow(2, mevent.Value[1]);
                    }
                }
                else if (mevent.Metaevent == MetaEventTempo) {
                    if (mevent.Metalength != 3) {
                        throw new MidiFileException(
                          "Meta Event Tempo len == " + mevent.Metalength +
                          " != 3", file.GetOffset());
                    }
                    mevent.Tempo = ( (mevent.Value[0] << 16) | (mevent.Value[1] << 8) | mevent.Value[2]);
                }
                else if (mevent.Metaevent == MetaEventEndOfTrack) {
                    /* break;  */
                }
            }
            else {
                throw new MidiFileException("Unknown event " + mevent.EventFlag,
                                             file.GetOffset()-1);
            }
            }

            return result;
        }
Пример #2
0
    public void TestVarlen()
    {
        byte[] data = new byte[12];

        data[0] = 0x40;

        data[1] = 0x90;
        data[2] = 0x30;

        data[3] = 0x81;
        data[4] = 0xA5;
        data[5] = 0x10;

        data[6] = 0x81;
        data[7] = 0x84;
        data[8] = 0xBF;
        data[9] = 0x05;

        WriteTestFile(data);
        MidiFileReader reader = new MidiFileReader(testfile);

        int len = varlen(0, 0, 0, data[0]);
        Assert.AreEqual(reader.GetOffset(), 0);
        Assert.AreEqual(reader.ReadVarlen(), len);
        Assert.AreEqual(reader.GetOffset(), 1);

        len = varlen(0, 0, data[1], data[2]);
        Assert.AreEqual(reader.ReadVarlen(), len);
        Assert.AreEqual(reader.GetOffset(), 3);

        len = varlen(0, data[3], data[4], data[5]);
        Assert.AreEqual(reader.ReadVarlen(), len);
        Assert.AreEqual(reader.GetOffset(), 6);

        len = varlen(data[6], data[7], data[8], data[9]);
        Assert.AreEqual(reader.ReadVarlen(), len);
        Assert.AreEqual(reader.GetOffset(), 10);

        File.Delete(testfile);
    }