예제 #1
0
        public MidiMessage copy()
        {
            MidiMessage other = (MidiMessage)this.MemberwiseClone();

            return(other);
        }
        protected int readTrack(int p_readPos)
        {
            int currentTrack = midiTracks.Count;

            byte[] trackSizeRaw = new byte[4];
            for (int i = 0; i < 4; i++)
            {
                trackSizeRaw[i] = readFile[p_readPos];
                p_readPos++;
            }
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(trackSizeRaw);
            }
            trackPosOffset += 8;                                    //offset for track header- timestamp and mtrk
            int trackSize = BitConverter.ToUInt16(trackSizeRaw, 0); //this is track size not including header or ender...

            MidiTrack track = new MidiTrack();

            byte runningStatus       = 0x00;
            bool canUseRunningStatus = false;

            //add all notes here. 4 is num bytes in track end message.

            while (p_readPos < (trackSize + trackPosOffset))
            {
                while (p_readPos + 2 < (trackSize + trackPosOffset))
                {
                    if (readFile[p_readPos] == 0x00 && readFile[p_readPos + 1] == 0xff)
                    {
                        p_readPos += 2;
                        switch (readFile[p_readPos])
                        {
                        case 0x00:
                            p_readPos += 2;
                            //00 FF 00 02 seqNum
                            //sequenceNum
                            break;

                        case 0x01:
                            //textEvent
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x02:
                            //copyrightMes
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x03:
                            //trackName
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x04:
                            //instName
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x05:
                            //lyrics
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x06:
                            //textMarker
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x07:
                            //cuePoint
                            p_readPos++;
                            p_readPos += (ushort)(readFile[p_readPos]);     //len byte and text length
                            break;

                        case 0x20:
                            //midiChannelPrefix
                            p_readPos += 2;
                            break;

                        case 0x2f:
                            //endOfTrack
                            p_readPos++;
                            break;

                        case 0x51:
                            //setTempo
                            p_readPos += 4;
                            break;

                        case 0x54:
                            //SMPTEOffset
                            p_readPos += 6;
                            break;

                        case 0x58:
                            //timeSignature
                            p_readPos += 5;
                            break;

                        case 0x59:
                            //keySignature
                            p_readPos += 3;
                            break;
                        }
                        p_readPos++; //move to next read pos
                    }
                    else
                    {
                        break;
                    }
                }

                if (p_readPos < (trackSize + trackPosOffset))
                {
                    List <byte> rawMessage        = new List <byte>();
                    int         numBytesTimestamp = 1;

                    //check for large timestamps
                    while (readFile[p_readPos] > 0x7F)
                    {
                        rawMessage.Add(readFile[p_readPos++]);
                        numBytesTimestamp++;
                    }

                    rawMessage.Add(readFile[p_readPos++]); //time stamp size will always be >= 1

                    //check if status byte or ctl byte is ignored
                    if ((readFile[p_readPos] & 0xF0) >= 0x80 && (readFile[p_readPos] & 0xF0) <= 0xE0)
                    {
                        canUseRunningStatus = true;
                        runningStatus       = readFile[p_readPos]; //store status for later
                        rawMessage.Add(readFile[p_readPos++]);     // add status byte- event type and channel
                        rawMessage.Add(readFile[p_readPos++]);     // add note byte
                        rawMessage.Add(readFile[p_readPos++]);     //add velocity byte
                    }
                    else if ((readFile[p_readPos] & 0xF0) == 0xF0)
                    {
                        canUseRunningStatus = false;
                        rawMessage.Add(readFile[p_readPos++]); // add status byte
                        rawMessage.Add(0x00);                  // add ctl byte- 0 as it's not used
                        rawMessage.Add(readFile[p_readPos++]); //add velocity byte
                    }
                    else if ((readFile[p_readPos] & 0xF0) <= 0x70 && canUseRunningStatus)
                    {
                        rawMessage.Add(runningStatus);         // add running status message
                        rawMessage.Add(readFile[p_readPos++]); // add note byte
                        rawMessage.Add(readFile[p_readPos++]); //add velocity byte
                    }

                    MidiMessage mes = new MidiMessage(rawMessage.ToArray(), numBytesTimestamp);
                    mes.setOwnerTrack(track);
                    track.AddNote(mes);
                }
            }
            track.setTrackNum(midiTracks.Count); //0 referenced
            addTrack(track);
            trackPosOffset += trackSize;
            return(p_readPos);
        }