Parse a midi file!

I’ve been having trouble with this for a while now…
I can’t find any answers that lead me to much.

Is it possible for me to parse a midi file to something like these items

class {

int InstrumentNumber;
float TimeCalled;
float Length;
int Pitch; //Any Format is Okay for Pitch

}

and have an array for them?

@nathanthesnooper,

If you write in C# you can use DryWetMIDI. It’s open source .NET library to work with MIDI files. With the library your task can be solved with this code:

    public sealed class NoteInfo
    {
        public int? ProgramNumber { get; set; }
        public long Time { get; set; }
        public long Length { get; set; }
        public int NoteNumber { get; set; }
    }

    private static IEnumerable<NoteInfo> GetNotesInfo(string filePath)
    {
        var midiFile = MidiFile.Read(filePath);

        // build the program changes map

        var programChanges = new Dictionary<FourBitNumber, Dictionary<long, SevenBitNumber>>();
        foreach (var timedEvent in midiFile.GetTimedEvents())
        {
            var programChangeEvent = timedEvent.Event as ProgramChangeEvent;
            if (programChangeEvent == null)
                continue;

            var channel = programChangeEvent.Channel;

            Dictionary<long, SevenBitNumber> changes;
            if (!programChanges.TryGetValue(channel, out changes))
                programChanges.Add(channel, changes = new Dictionary<long, SevenBitNumber>());

            changes[timedEvent.Time] = programChangeEvent.ProgramNumber;
        }

        // collect notes info

        return midiFile.GetNotes()
                       .Select(n => new NoteInfo
                       {
                           ProgramNumber = GetProgramNumber(n.Channel, n.Time, programChanges),
                           Time = n.Time,
                           Length = n.Length,
                           NoteNumber = n.NoteNumber
                       });
    }

    private static int? GetProgramNumber(FourBitNumber channel, long time, Dictionary<FourBitNumber, Dictionary<long, SevenBitNumber>> programChanges)
    {
        Dictionary<long, SevenBitNumber> changes;
        if (!programChanges.TryGetValue(channel, out changes))
            return null;

        var times = changes.Keys.Where(t => t <= time).ToArray();
        return times.Any()
            ? (int?)changes[times.Max()]
            : null;
    }

ProgramNumber is defined as int? since Program Change event can be missed in a file so in this case you should decide by yourself which instrument to use.

Time and Length defined as long because all timing in a MIDI file presented as integer numbers meaning of which defined by the time division of a file. In 99.9% files times and lengths expressed in ticks. If you want to get time as hours, minutes, seconds or fraction of the whole note’s length you can use TimeAs method on Note class:

TempoMap tempoMap = midiFile.GetTempoMap();

MetricTimeSpan metricTime = n.TimeAs<MetricTimeSpan>(tempoMap);
MusicalTimeSpan musicalTime = n.TimeAs<MusicalTimeSpan>(tempoMap);

For Length there is the LengthAs method:

MetricTimeSpan metricLength = n.LengthAs<MetricTimeSpan>(tempoMap);
MusicalTimeSpan musicalLength = n.LengthAs<MusicalTimeSpan>(tempoMap);