public void AddNote(MidiMessage p_message) { trackMessages.Add(p_message); if (p_message == null) { UnityEngine.Debug.Log("Message is NULL"); } p_message.setOwnerTrack(this); trackPPQLen += p_message.getTimeStamp(); p_message.setAbsTimestamp(trackPPQLen); numNotes++; UInt16 numBytesInMes = p_message.getNumBytes(); trkLen += numBytesInMes; trkLenBytes = BitConverter.GetBytes(numBytesInMes); if (BitConverter.IsLittleEndian) { Array.Reverse(trkLenBytes); } }
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); }