예제 #1
0
//- static methods ------------------------------------------------------------

        public static Message getMessage(byte[] data)
        {
            Message msg = null;

            int status = data[0];

            if (status < 0xF0)          //midi channel message
            {
                int msgtype = status / 16;
                int channel = status % 16;

                int b1 = data[1];
                int b2 = 0;
                if ((msgtype != 0xC) && (msgtype != 0xD))
                {
                    b2 = data[2];
                }

                msg = Message.getChannelMessage(msgtype, channel, b1, b2);
            }
            else if (status == 0xF0)                        //sys ex msg
            {
                List <byte> bytes = new List <byte>(data);
                msg = new SysExMessage(bytes);
            }
            else
            {                                   //status msg
                int b1      = 0;
                int b2      = 0;
                int datalen = SystemMessage.SysMsgLen[status - 0xF0] - 1;
                if (datalen > 0)
                {
                    b1 = data[1];
                }
                if (datalen > 1)
                {
                    b2 = data[2];
                    b1 = ((b1 % 128) * 128) + (b2 % 128);
                }
                msg = new SystemMessage(status, b1);
            }

            return(msg);
        }
예제 #2
0
        //read data from a single track chunk
        private static void loadTrackData(MidiInStream stream, Sequence seq, int trackNum)
        {
            //read track header
            String trackSig        = stream.getString(4);
            uint   trackDataLength = stream.getFour();

            if (!trackSig.Equals("MTrk"))
            {
                throw new MidiFileException(stream.filename + " has an invalid track at ", stream.getDataPos() - 8);
            }

            Track track = seq.addTrack();                           //get new track from sequence

            track.setName("Track " + trackNum.ToString());

            int currentTime = 0;                //event time in ticks

            runningStatus = 0;
            sysexCont     = false;
            prevSysEx     = null;
            Event evt = null;

            int startpos = stream.getDataPos();

            while ((stream.getDataPos() - startpos) < trackDataLength)
            {
                currentTime += (int)stream.getVariableLengthVal();      //add delta time to current num of ticks
                evt          = loadEventData(stream);
                if ((evt != null) && !(evt is EndofTrackEvent ||
                                       evt is MarkerEvent || evt is CuePointEvent || //these are ignored in tracks other than track 0
                                       evt is TempoEvent || evt is SMPTEOffsetEvent ||
                                       evt is TimeSignatureEvent || evt is KeySignatureEvent))
                {
                    track.addEvent(evt, currentTime);
                }
            }

            //last event in track must be an "end of track" event
            if ((evt != null) && !(evt is EndofTrackEvent))
            {
                throw new MidiFileException(stream.filename + ": track " + curTrackNum.ToString() +
                                            "missing end of track event at ", stream.getDataPos() - 8);
            }
        }
예제 #3
0
        //build the tempo, meter and marker maps from tempo message from track 0
        private static void loadTrackZeroData(MidiInStream stream, Sequence seq)
        {
            //read track header
            String trackSig        = stream.getString(4);
            uint   trackDataLength = stream.getFour();

            if (!trackSig.Equals("MTrk"))
            {
                throw new MidiFileException(stream.filename + " has an invalid track 0 at ", stream.getDataPos() - 8);
            }

            int currentTime = 0;        //event time in ticks

            runningStatus = 0;
            sysexCont     = false;
            prevSysEx     = null;
            Event evt;

            Meter prevMeter = null;

            int startpos = stream.getDataPos();

            while ((stream.getDataPos() - startpos) < trackDataLength)
            {
                currentTime += (int)stream.getVariableLengthVal();      //add delta time to current num of ticks
                evt          = loadEventData(stream);

                if (evt is TempoEvent)
                {
                    Tempo tempo = new Tempo(currentTime, ((TempoEvent)evt).tempo);
                    seq.tempoMap.addTempo(tempo);
                }
                else if (evt is SMPTEOffsetEvent)       //not handling smpte timing yet
                {
                }
                else if (evt is TimeSignatureEvent)
                {
                    int   keysig = (prevMeter != null) ? prevMeter.keysig : 0;
                    Meter meter  = new Meter(currentTime, ((TimeSignatureEvent)evt).numer, ((TimeSignatureEvent)evt).denom, keysig);
                    seq.meterMap.addMeter(meter);
                    prevMeter = meter;
                }
                else if (evt is KeySignatureEvent)
                {
                    int numer = 4;
                    int denom = 4;
                    if (prevMeter != null)
                    {
                        numer = prevMeter.numer;
                        denom = prevMeter.denom;
                    }
                    Meter meter = new Meter(currentTime, numer, denom, ((KeySignatureEvent)evt).keySig);
                    seq.meterMap.addMeter(meter);
                    prevMeter = meter;
                }
                else if (evt is MarkerEvent)
                {
                }
                else if (evt is CuePointEvent)
                {
                }
            }
        }
예제 #4
0
        //read data for a midi message (80 - ff), handle sysex continuation and escape sequences
        private static Message loadMessageData(MidiInStream stream, int status)
        {
            Message msg = null;

            if (status < 0xF0)          //midi channel message
            {
                int msgtype = status / 16;
                int channel = status % 16;

                int b1 = stream.getOne();
                int b2 = 0;
                if ((msgtype != 0xC) && (msgtype != 0xD))
                {
                    b2 = stream.getOne();
                }

                msg = Message.getChannelMessage(msgtype, channel, b1, b2);
            }
            else if (status == 0xF0)            //sysex message
            {
                int         len       = stream.getOne();
                List <byte> sysExData = stream.getRange(len);
                sysexCont     = (sysExData[sysExData.Count - 1] != 0xf7);   //is the last byte of sysex data a F7?
                msg           = new SysExMessage(sysExData);
                prevSysEx     = (SysExMessage)msg;
                runningStatus = 0;                      //sysex msg cancel running status
            }
            else if (status == 0xF7)
            {
                if (sysexCont)                  //sysex continuation - append this data to prev sysex message
                {
                    int         len      = stream.getOne();
                    List <byte> contData = stream.getRange(len);
                    sysexCont = (contData[contData.Count - 1] != 0xf7);       //is the last byte of sysex data a F7?
                    prevSysEx.sysExData.AddRange(contData);
                }
                else
                {                                   //escape sequence
                    int         len     = stream.getOne();
                    List <byte> escData = stream.getRange(len);
                    msg = new EscapeMessage(escData);
                }
                runningStatus = 0;
            }
            else
            {                                   //system common msgs shouldn't occur here, but if they do, we need to skip them
                int b1      = 0;
                int b2      = 0;
                int datalen = SystemMessage.SysMsgLen[status - 0xF0] - 1;
                if (datalen > 0)
                {
                    b1 = stream.getOne();
                }
                if (datalen > 1)
                {
                    b2 = stream.getOne();
                    b1 = ((b1 % 128) * 128) + (b2 % 128);
                }
                msg           = new SystemMessage(status, b1);
                runningStatus = 0;
            }

            return(msg);
        }