Example #1
0
        /** Parse the given Midi file, and return an instance of this MidiFile
         * class.  After reading the midi file, this object will contain:
         * - The raw list of midi events
         * - The Time Signature of the song
         * - All the tracks in the song which contain notes.
         * - The number, starttime, and duration of each note.
         */
        public void parse(MidiFileReader file, string filename)
        {
            string id;
            int len;

            this.filename = filename;
            tracks = new List<MidiTrack>();
            trackPerChannel = false;

            id = file.ReadAscii(4);
            if (id != "MThd") {
            throw new MidiFileException("Doesn't start with MThd", 0);
            }
            len = file.ReadInt();
            if (len !=  6) {
            throw new MidiFileException("Bad MThd header", 4);
            }
            trackmode = file.ReadShort();
            int num_tracks = file.ReadShort();
            quarternote = file.ReadShort();

            events = new List<MidiEvent>[num_tracks];
            for (int tracknum = 0; tracknum < num_tracks; tracknum++) {
            events[tracknum] = ReadTrack(file);
            MidiTrack track = new MidiTrack(events[tracknum], tracknum);
            if (track.Notes.Count > 0) {
                tracks.Add(track);
            }
            }

            /* Get the length of the song in pulses */
            foreach (MidiTrack track in tracks) {
            MidiNote last = track.Notes[track.Notes.Count-1];
            if (this.totalpulses < last.StartTime + last.Duration) {
                this.totalpulses = last.StartTime + last.Duration;
            }
            }

            /* If we only have one track with multiple channels, then treat
             * each channel as a separate track.
             */
            if (tracks.Count == 1 && HasMultipleChannels(tracks[0])) {
            tracks = SplitChannels(tracks[0], events[tracks[0].Number]);
            trackPerChannel = true;
            }

            CheckStartTimes(tracks);

            /* Determine the time signature */
            int tempo = 0;
            int numer = 0;
            int denom = 0;
            foreach (List<MidiEvent> list in events) {
            foreach (MidiEvent mevent in list) {
                if (mevent.Metaevent == MetaEventTempo && tempo == 0) {
                    tempo = mevent.Tempo;
                }
                if (mevent.Metaevent == MetaEventTimeSignature && numer == 0) {
                    numer = mevent.Numerator;
                    denom = mevent.Denominator;
                }
            }
            }
            if (tempo == 0) {
            tempo = 500000; /* 500,000 microseconds = 0.05 sec */
            }
            if (numer == 0) {
            numer = 4; denom = 4;
            }
            timesig = new TimeSignature(numer, denom, quarternote, tempo);
        }
Example #2
0
        public bool useDefaultInstruments; /** If true, don't change instruments */

        #endregion Fields

        #region Constructors

        public MidiOptions(MidiFile midifile)
        {
            int numtracks = midifile.Tracks.Count;
            tracks = new bool[numtracks];
            mute =  new bool[numtracks];
            instruments = new int[numtracks];
            for (int i = 0; i < tracks.Length; i++) {
            tracks[i] = true;
            mute[i] = false;
            instruments[i] = midifile.Tracks[i].Instrument;
            if (midifile.Tracks[i].InstrumentName == "Percussion") {
                tracks[i] = false;
            }
            }
            useDefaultInstruments = true;
            scrollVert = true;
            largeNoteSize = false;
            if (tracks.Length == 1) {
            twoStaffs = true;
            }
            else {
            twoStaffs = false;
            }
            showNoteLetters = NoteNameNone;
            showLyrics = true;
            showMeasures = false;
            shifttime = 0;
            transpose = 0;
            key = -1;
            time = midifile.Time;
            colors = null;
            shadeColor = Color.FromArgb(210, 205, 220);
            shade2Color = Color.FromArgb(80, 100, 250);
            combineInterval = 40;
            tempo = midifile.Time.Tempo;
            pauseTime = 0;
            playMeasuresInLoop = false;
            playMeasuresInLoopStart = 0;
            playMeasuresInLoopEnd = midifile.EndTime() / midifile.Time.Measure;
        }
Example #3
0
        /** In Midi Files, time is measured in pulses.  Notes that have
         * pulse times that are close together (like within 10 pulses)
         * will sound like they're the same chord.  We want to draw
         * these notes as a single chord, it makes the sheet music much
         * easier to read.  We don't want to draw notes that are close
         * together as two separate chords.
         *
         * The SymbolSpacing class only aligns notes that have exactly the same
         * start times.  Notes with slightly different start times will
         * appear in separate vertical columns.  This isn't what we want.
         * We want to align notes with approximately the same start times.
         * So, this function is used to assign the same starttime for notes
         * that are close together (timewise).
         */
        public static void RoundStartTimes(List<MidiTrack> tracks, int millisec, TimeSignature time)
        {
            /* Get all the starttimes in all tracks, in sorted order */
            List<int> starttimes = new List<int>();
            foreach (MidiTrack track in tracks) {
            foreach (MidiNote note in track.Notes) {
                starttimes.Add( note.StartTime );
            }
            }
            starttimes.Sort();

            /* Notes within "millisec" milliseconds apart will be combined. */
            int interval = time.Quarter * millisec * 1000 / time.Tempo;

            /* If two starttimes are within interval millisec, make them the same */
            for (int i = 0; i < starttimes.Count - 1; i++) {
            if (starttimes[i+1] - starttimes[i] <= interval) {
                starttimes[i+1] = starttimes[i];
            }
            }

            CheckStartTimes(tracks);

            /* Adjust the note starttimes, so that it matches one of the starttimes values */
            foreach (MidiTrack track in tracks) {
            int i = 0;

            foreach (MidiNote note in track.Notes) {
                while (i < starttimes.Count &&
                       note.StartTime - interval > starttimes[i]) {
                    i++;
                }

                if (note.StartTime > starttimes[i] &&
                    note.StartTime - starttimes[i] <= interval) {

                    note.StartTime = starttimes[i];
                }
            }
            track.Notes.Sort(track.Notes[0]);
            }
        }