static MidiAnimationAsset ReadTrack(MidiDataStreamReader reader, uint tpqn) { // Chunk type if (reader.ReadChars(4) != "MTrk") { throw new FormatException("Can't find track chunk."); } // Chunk length var chunkEnd = reader.ReadBEUInt32(); chunkEnd += reader.Position; // MIDI event sequence var events = new List <MidiEvent>(); var ticks = 0u; var stat = (byte)0; while (reader.Position < chunkEnd) { // Delta time ticks += reader.ReadMultiByteValue(); // Status byte if ((reader.PeekByte() & 0x80u) != 0) { stat = reader.ReadByte(); } if (stat == 0xffu) { // 0xff: Meta event (unused) reader.Advance(1); reader.Advance(reader.ReadMultiByteValue()); } else if (stat == 0xf0u) { // 0xf0: SysEx (unused) while (reader.ReadByte() != 0xf7u) { } } else { // MIDI event var b1 = reader.ReadByte(); var b2 = (stat & 0xe0u) == 0xc0u ? (byte)0 : reader.ReadByte(); events.Add(new MidiEvent { time = ticks, status = stat, data1 = b1, data2 = b2 }); } } // Quantize duration with bars. var bars = (ticks + tpqn * 4 - 1) / (tpqn * 4); // Asset instantiation var asset = ScriptableObject.CreateInstance <MidiAnimationAsset>(); asset.template.tempo = 120; asset.template.duration = bars * tpqn * 4; asset.template.ticksPerQuarterNote = tpqn; asset.template.events = events.ToArray(); return(asset); }