public MidiMetaEvent(uint time, int type, byte[] bytes, Midi midi, MidiTrack track)
    {
        Time = time;
        Type = type;
        Bytes = bytes;

        Midi = midi;
        Track = track;
    }
    public MidiCommandEvent(uint time, int command, int channel, byte[] args, Midi midi, MidiTrack track)
    {
        Time = time;
        Command = command;
        Channel = channel;
        Args = args;

        Midi = midi;
        Track = track;
    }
Esempio n. 3
0
 MidiTrackMetaData(MidiTrack track)
 {
     mTrack = track;
     if (mTrack.Name != null) {
         var matches = sTrackRegex.Matches(mTrack.Name);
         for (var i = 0; i < matches.Count; ++i) {
             var name = matches[i].Groups["key"].Value.ToLowerInvariant();
             var value = matches[i].Groups["value"].Value;
             if (sParserLUT.ContainsKey(name)) {
                 sParserLUT[name](this, value);
             }
         }
     }
 }
Esempio n. 4
0
        public TrackDisplay(MidiTrack[] tracks, Color[] trackColors)
        {
            m_displayElementList = new ArrayList();

            // store notes-
            ArrayList evts = new ArrayList();

            for (int n = 0; n < tracks.Length; n++)      //MidiTrack t in f.tracks)
            {
                MidiTrack t = tracks[n];
                if (!t.enabled)
                {
                    continue;
                }
                evts.Clear();
                float width = 1;

                for (int i = 0; i < t.events.Count; i++)
                {
                    if (t.get_e(i).IsMidi)
                    {
                        TimedMidiMsg m = (TimedMidiMsg)t.get_e(i);
                        if (m.m.IsNoteOn)
                        {
                            evts.Add(m);
                        }
                        else if (m.m.IsNoteOff)
                        {
                            TimedMidiMsg e1 = null;
                            TimedMidiMsg e2 = m;
                            foreach (TimedMidiMsg mm in evts)
                            {
                                if (mm.m.Byte2 == e2.m.Byte2)
                                {
                                    e1 = mm;
                                    evts.Remove(mm);
                                    break;
                                }
                            }
                            if (e1 != null)
                            {
                                TrackDisplayElement element =
                                    new TrackDisplayElement(e1.Time, e2.Time, e2.m.Byte2,
                                                            trackColors[Array.IndexOf(tracks, t)], width);

                                AddElement(element, n == 0, 0);
                            }
                        }
                    }
                    else if (t.get_e(i).IsMeta)
                    {
                        MetaMsg m = (MetaMsg)t.get_e(i);
                        if (m.Type == 6)        // "Marker"
                        {
                            if (m.Txt.ToLower() == "bold")
                            {
                                width = 2;
                            }
                            else if (m.Txt.ToLower() == "stop")
                            {
                                width = 1;
                            }
                        }
                    }
                }
            }
        }
Esempio n. 5
0
        /// <summary>Create the demo sequence.</summary>
        /// <returns>The created midi sequence.</returns>
        public MidiSequence CreateSequence()
        {
            MidiSequence sequence = new MidiSequence(0, 120);
            MidiTrack    track    = sequence.AddTrack();

            track.Events.Add(new TimeSignature(0, 4, 2, 24, 8));
            track.Events.Add(new KeySignature(0, Key.NoFlatsOrSharps, Tonality.Major));
            track.Events.Add(new Tempo(0, 416667));
            track.Events.Add(new ProgramChange(0, 0, GeneralMidiInstruments.AcousticGrand));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(11, 0, "E6", 60));
            track.Events.Add(new Controller(56, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(24, 0, "D#6", 66));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(2, 0, "E6", 0));
            track.Events.Add(new NoteOn(75, 0, "E6", 60));
            track.Events.Add(new NoteOn(16, 0, "D#6", 0));
            track.Events.Add(new NoteOn(72, 0, "D#6", 62));
            track.Events.Add(new NoteOn(8, 0, "E6", 0));
            track.Events.Add(new NoteOn(77, 0, "E6", 72));
            track.Events.Add(new NoteOn(16, 0, "D#6", 0));
            track.Events.Add(new NoteOn(64, 0, "B5", 71));
            track.Events.Add(new NoteOn(12, 0, "E6", 0));
            track.Events.Add(new NoteOn(64, 0, "D6", 85));
            track.Events.Add(new NoteOn(19, 0, "B5", 0));
            track.Events.Add(new NoteOn(60, 0, "C6", 80));
            track.Events.Add(new NoteOn(24, 0, "D6", 0));
            track.Events.Add(new NoteOn(51, 0, "A3", 66));
            track.Events.Add(new NoteOn(5, 0, "A5", 73));
            track.Events.Add(new NoteOn(13, 0, "C6", 0));
            track.Events.Add(new Controller(24, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(35, 0, "E4", 70));
            track.Events.Add(new NoteOn(51, 0, "A5", 0));
            track.Events.Add(new NoteOn(23, 0, "A4", 75));
            track.Events.Add(new NoteOn(72, 0, "A4", 0));
            track.Events.Add(new NoteOn(0, 0, "C5", 78));
            track.Events.Add(new NoteOn(73, 0, "E5", 86));
            track.Events.Add(new NoteOn(13, 0, "A3", 0));
            track.Events.Add(new NoteOn(42, 0, "E4", 0));
            track.Events.Add(new NoteOn(17, 0, "A5", 87));
            track.Events.Add(new NoteOn(19, 0, "C5", 0));
            track.Events.Add(new NoteOn(14, 0, "E5", 0));
            track.Events.Add(new NoteOn(40, 0, "E3", 72));
            track.Events.Add(new NoteOn(1, 0, "B5", 84));
            track.Events.Add(new Controller(4, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(10, 0, "A5", 0));
            track.Events.Add(new Controller(36, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(19, 0, "E3", 0));
            track.Events.Add(new NoteOn(5, 0, "E4", 70));
            track.Events.Add(new NoteOn(47, 0, "E4", 0));
            track.Events.Add(new NoteOn(0, 0, "B5", 0));
            track.Events.Add(new NoteOn(9, 0, "G#4", 85));
            track.Events.Add(new NoteOn(62, 0, "E5", 82));
            track.Events.Add(new NoteOn(66, 0, "G#4", 0));
            track.Events.Add(new NoteOn(5, 0, "G#5", 85));
            track.Events.Add(new NoteOn(72, 0, "B5", 93));
            track.Events.Add(new NoteOn(3, 0, "E5", 0));
            track.Events.Add(new NoteOn(29, 0, "G#5", 0));
            track.Events.Add(new NoteOn(38, 0, "C6", 78));
            track.Events.Add(new NoteOn(4, 0, "A3", 66));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(3, 0, "B5", 0));
            track.Events.Add(new Controller(38, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(27, 0, "E4", 72));
            track.Events.Add(new NoteOn(76, 0, "A4", 70));
            track.Events.Add(new NoteOn(68, 0, "E5", 75));
            track.Events.Add(new NoteOn(5, 0, "C6", 0));
            track.Events.Add(new NoteOn(46, 0, "A4", 0));
            track.Events.Add(new NoteOn(20, 0, "A3", 0));
            track.Events.Add(new NoteOn(5, 0, "E4", 0));
            track.Events.Add(new NoteOn(3, 0, "E5", 0));
            track.Events.Add(new NoteOn(1, 0, "E6", 74));
            track.Events.Add(new NoteOn(70, 0, "E6", 0));
            track.Events.Add(new NoteOn(2, 0, "D#6", 82));
            track.Events.Add(new NoteOn(76, 0, "E6", 90));
            track.Events.Add(new NoteOn(6, 0, "D#6", 0));
            track.Events.Add(new Controller(4, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new NoteOn(59, 0, "D#6", 86));
            track.Events.Add(new NoteOn(14, 0, "E6", 0));
            track.Events.Add(new NoteOn(57, 0, "E6", 103));
            track.Events.Add(new NoteOn(20, 0, "D#6", 0));
            track.Events.Add(new NoteOn(56, 0, "B5", 90));
            track.Events.Add(new NoteOn(11, 0, "E6", 0));
            track.Events.Add(new NoteOn(66, 0, "D6", 86));
            track.Events.Add(new NoteOn(11, 0, "B5", 0));
            track.Events.Add(new NoteOn(62, 0, "C6", 85));
            track.Events.Add(new NoteOn(8, 0, "D6", 0));
            track.Events.Add(new NoteOn(72, 0, "A5", 77));
            track.Events.Add(new NoteOn(3, 0, "C6", 0));
            track.Events.Add(new NoteOn(1, 0, "A3", 55));
            track.Events.Add(new Controller(16, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(52, 0, "E4", 60));
            track.Events.Add(new NoteOn(28, 0, "A5", 0));
            track.Events.Add(new NoteOn(50, 0, "A4", 77));
            track.Events.Add(new NoteOn(63, 0, "C5", 90));
            track.Events.Add(new NoteOn(3, 0, "A4", 0));
            track.Events.Add(new NoteOn(57, 0, "A3", 0));
            track.Events.Add(new NoteOn(14, 0, "E5", 86));
            track.Events.Add(new NoteOn(66, 0, "E4", 0));
            track.Events.Add(new NoteOn(3, 0, "A5", 82));
            track.Events.Add(new NoteOn(3, 0, "C5", 0));
            track.Events.Add(new NoteOn(12, 0, "E5", 0));
            track.Events.Add(new NoteOn(54, 0, "B5", 89));
            track.Events.Add(new NoteOn(3, 0, "E3", 79));
            track.Events.Add(new NoteOn(7, 0, "A5", 0));
            track.Events.Add(new Controller(2, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new Controller(45, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(14, 0, "E3", 0));
            track.Events.Add(new NoteOn(7, 0, "E4", 68));
            track.Events.Add(new NoteOn(66, 0, "E4", 0));
            track.Events.Add(new NoteOn(11, 0, "G#4", 84));
            track.Events.Add(new NoteOn(67, 0, "D5", 82));
            track.Events.Add(new NoteOn(11, 0, "B5", 0));
            track.Events.Add(new NoteOn(4, 0, "G#4", 0));
            track.Events.Add(new NoteOn(68, 0, "C6", 73));
            track.Events.Add(new NoteOn(37, 0, "D5", 0));
            track.Events.Add(new NoteOn(35, 0, "B5", 69));
            track.Events.Add(new NoteOn(69, 0, "B5", 0));
            track.Events.Add(new NoteOn(3, 0, "C6", 0));
            track.Events.Add(new NoteOn(6, 0, "A3", 60));
            track.Events.Add(new NoteOn(2, 0, "A5", 68));
            track.Events.Add(new Controller(0, 0, Controllers.EffectControl1Fine, 0));
            track.Events.Add(new Controller(49, 0, Controllers.EffectControl1Fine, 127));
            track.Events.Add(new NoteOn(29, 0, "E4", 66));
            track.Events.Add(new NoteOn(90, 0, "A4", 71));
            track.Events.Add(new NoteOn(23, 0, "A5", 0));
            track.Events.Add(new NoteOn(5, 0, "A3", 0));
            track.Events.Add(new NoteOn(16, 0, "E4", 0));
            track.Events.Add(new NoteOn(0, 0, "A4", 0));
            track.Events.Add(new NoteOn(130, 0, "E6", 80));
            track.Events.Add(new EndOfTrack(130));
            return(sequence);
        }
Esempio n. 6
0
 public override void ExecuteEvent(MidiTrack track)
 {
 }
Esempio n. 7
0
 /// <summary>Intializes the meta event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="metaEventID">The event ID for this meta event.</param>
 /// <param name="data">The data associated with the event.</param>
 public UnknownMetaMidiEvent(MidiTrack owner, long deltaTime, byte metaEventID, byte[] data) :
     base(owner, deltaTime, metaEventID)
 {
     Data = data;
 }
 public override void Integrate(MidiTrack track)
 {
     Debug.Assert(time == 0);
     throw new System.NotImplementedException();
 }
Esempio n. 9
0
    public void TestSplitTrack()
    {
        MidiTrack track = new MidiTrack(1);
        int start, number;

        /* Create notes between 70 and 80 */
        for (int i = 0; i < 100; i++) {
            start = i * 10;
            number = 70 + (i % 10);
            MidiNote note = new MidiNote(start, 0, number, 10);
            track.AddNote(note);
        }

        /* Create notes between 65 and 75 */
        for (int i = 0; i < 100; i++) {
            start = i * 10 + 1;
            number = 65 + (i % 10);
            MidiNote note = new MidiNote(start, 0, number, 10);
            track.AddNote(note);
        }

        /* Create notes between 50 and 60 */
        for (int i = 0; i < 100; i++) {
            start = i * 10;
            number = 50 + (i % 10);
            MidiNote note = new MidiNote(start, 0, number, 10);
            track.AddNote(note);
        }

        /* Create notes between 55 and 65 */
        for (int i = 0; i < 100; i++) {
            start = i * 10 + 1;
            number = 55 + (i % 10);
            MidiNote note = new MidiNote(start, 0, number, 10);
            track.AddNote(note);
        }

        track.Notes.Sort( track.Notes[0] );
        List<MidiTrack> tracks = MidiFile.SplitTrack(track, 40);

        Assert.AreEqual(tracks[0].Notes.Count, 200);
        Assert.AreEqual(tracks[1].Notes.Count, 200);

        for (int i = 0; i < 100; i++) {
            MidiNote note1 = tracks[0].Notes[i*2];
            MidiNote note2 = tracks[0].Notes[i*2 + 1];
            Assert.AreEqual(note1.StartTime, i*10);
            Assert.AreEqual(note2.StartTime, i*10 + 1);
            Assert.AreEqual(note1.Number, 70 + (i % 10));
            Assert.AreEqual(note2.Number, 65 + (i % 10));
        }
        for (int i = 0; i < 100; i++) {
            MidiNote note1 = tracks[1].Notes[i*2];
            MidiNote note2 = tracks[1].Notes[i*2 + 1];
            Assert.AreEqual(note1.StartTime, i*10);
            Assert.AreEqual(note2.StartTime, i*10 + 1);
            Assert.AreEqual(note1.Number, 50 + (i % 10));
            Assert.AreEqual(note2.Number, 55 + (i % 10));
        }
    }
Esempio n. 10
0
    public void TestRoundStartTimes()
    {
        const byte notenum = 20;

        List<MidiTrack> tracks = new List<MidiTrack>();
        MidiTrack track1 = new MidiTrack(0);
        track1.AddNote(new MidiNote(0, 0, notenum, 60));
        track1.AddNote(new MidiNote(3, 0, notenum+1, 60));
        track1.AddNote(new MidiNote(15, 0, notenum+2, 60));
        track1.AddNote(new MidiNote(22, 0, notenum+3, 60));
        track1.AddNote(new MidiNote(62, 0, notenum+4, 60));

        MidiTrack track2 = new MidiTrack(1);
        track2.AddNote(new MidiNote(2, 0, notenum+10, 60));
        track2.AddNote(new MidiNote(10, 0, notenum+11, 60));
        track2.AddNote(new MidiNote(20, 0, notenum+12, 60));
        track2.AddNote(new MidiNote(35, 0, notenum+13, 60));
        track2.AddNote(new MidiNote(36, 0, notenum+14, 60));

        tracks.Add(track1);
        tracks.Add(track2);

        int quarter = 130;
        int tempo = 500000;
        TimeSignature time = new TimeSignature(4, 4, quarter, tempo);

        /* quarternote * 60,000 / 500,000 = 15 pulses
         * So notes within 15 pulses should be grouped together.
         * 0, 2, 3, 10, 15 are grouped to starttime 0
         * 20, 22, 35      are grouped to starttime 20
         * 36              is still 36
         * 62              is still 62
         */
        MidiFile.RoundStartTimes(tracks, 60, time);
        List<MidiNote> notes1 = tracks[0].Notes;
        List<MidiNote> notes2 = tracks[1].Notes;
        Assert.AreEqual(notes1.Count, 5);
        Assert.AreEqual(notes2.Count, 5);

        Assert.AreEqual(notes1[0].Number, notenum);
        Assert.AreEqual(notes1[1].Number, notenum+1);
        Assert.AreEqual(notes1[2].Number, notenum+2);
        Assert.AreEqual(notes1[3].Number, notenum+3);
        Assert.AreEqual(notes1[4].Number, notenum+4);

        Assert.AreEqual(notes2[0].Number, notenum+10);
        Assert.AreEqual(notes2[1].Number, notenum+11);
        Assert.AreEqual(notes2[2].Number, notenum+12);
        Assert.AreEqual(notes2[3].Number, notenum+13);
        Assert.AreEqual(notes2[4].Number, notenum+14);

        Assert.AreEqual(notes1[0].StartTime, 0);
        Assert.AreEqual(notes1[1].StartTime, 0);
        Assert.AreEqual(notes1[2].StartTime, 0);
        Assert.AreEqual(notes1[3].StartTime, 20);
        Assert.AreEqual(notes1[3].StartTime, 20);
        Assert.AreEqual(notes1[4].StartTime, 62);

        Assert.AreEqual(notes2[0].StartTime, 0);
        Assert.AreEqual(notes2[1].StartTime, 0);
        Assert.AreEqual(notes2[2].StartTime, 20);
        Assert.AreEqual(notes2[3].StartTime, 20);
        Assert.AreEqual(notes2[4].StartTime, 36);
    }
Esempio n. 11
0
 public void TestRoundDurations()
 {
     MidiTrack track = new MidiTrack(1);
     MidiNote note = new MidiNote(0, 0, 55, 45);
     track.AddNote(note);
     int[] starttimes = new int[] { 50, 90, 101, 123 };
     foreach (int start in starttimes) {
         note = new MidiNote(start, 0, 55, 1);
         track.AddNote(note);
     }
     List<MidiTrack> tracks = new List<MidiTrack>();
     tracks.Add(track);
     int quarternote = 40;
     MidiFile.RoundDurations(tracks, quarternote);
     Assert.AreEqual(track.Notes[0].Duration, 45);
     Assert.AreEqual(track.Notes[1].Duration, 40);
     Assert.AreEqual(track.Notes[2].Duration, 10);
     Assert.AreEqual(track.Notes[3].Duration, 20);
     Assert.AreEqual(track.Notes[4].Duration, 1);
 }
Esempio n. 12
0
        /// <summary>
        /// Parse's MTrk Chunk
        /// </summary>
        /// <param name="start"Index where the Chunk starts (excluding MTrk)</param>
        /// <param name="length">Length of the track</param>
        private void ParseTrack(int start, int length)
        {
            MidiTrack midiTrack = new MidiTrack(this);

            int ticks = 0;
            for (int i = start; i < start + length;)
            {
                //Update ticks
                int[] delta = GetDelta(i);
                ticks += MidiDecTime2normalTime(delta);

                //Move cursor
                i += delta.Length;

                if (_data[i] == 0x90 || _data[i] == 0x80)
                {
                    ChannelVoice voice = ChannelVoiceFactory.Create(ticks, _data, i);
                    midiTrack.Voice.Add(voice);

                    i += 3;
                }
                else if (_data[i] == 0xFF)
                {
                    i += ProcessMetaEvent(midiTrack, i);
                }
            }

            //Set total ticks
            midiTrack.Ticks = ticks;

            this._tracks.Add(midiTrack);
        }
Esempio n. 13
0
        /// <summary>
        /// Process meta events
        /// </summary>
        /// <param name="start">index of event</param>
        /// <returns>Length of event in bytes</returns>
        private int ProcessMetaEvent(MidiTrack midiTrack, int n)
        {
            byte flag = _data[n + 1];
            byte len = 0;

            if (flag == 0x00)                       //FF 00 02 ss ss
            {
                len = 5;
            }
            else if(flag == 0x03)                   //Set Track name
            {
                len = _data[n + 2];
                midiTrack.Name = Encoding.UTF8.GetString(_data, n+3, len);
                len += 3;
            }
            else if (flag >= 0x01 && flag <= 0x07)  //FF nn len txt
            {
                len = _data[n + 2];
                len += 3;
            }
            else if (flag == 0x20)                  //FF 20 01 cc
            {
                len = 5;
            }
            else if (flag == 0x2F)                  //FF 2F 00 (End of track)
            {
                len = 3;
            }
            else if (flag == 0x51)                  //FF 51 03 tt tt tt (Set tempo)
            {
                len = 6;
                byte[] tempo = { 0x00, _data[n + 3], _data[n + 4], _data[n + 5] };
                Array.Reverse(tempo);
                this.Tempo = BitConverter.ToInt32(tempo, 0);
            }
            else if (flag == 0x54)                  //FF 54 05 hh mm ss fr ff
            {
                len = 8;
            }
            else if (flag == 0x58)                  //FF 58 04 nn dd cc bb
            {
                len = 7;
            }
            else if (flag == 0x59)                  //FF 58 04 nn dd cc bb
            {
                len = 7;
            }
            else if (flag == 0x7F)                  //FF 7F <len> <id> <data>
            {
                len = _data[n + 2];
                len += 3;
            }

            return len;
        }
Esempio n. 14
0
 public static MidiTrackMetaData fromTrack(MidiTrack track)
 {
     if (track == null) {
         return null;
     }
     return new MidiTrackMetaData(track);
 }
Esempio n. 15
0
        static public void fixLoopCarryBack(MidiFile midiFile)
        {
            Debug.WriteLine("Fixing Loop Carryback Errors...");
            // first of all we need to check if the MIDI actually loops
            // we only have to check the first track for the [ ] brackets in the marker Events
            bool hasLoopStart  = false;
            long loopStartTick = 0;
            bool hasLoopEnd    = false;
            long loopEndTick   = 0;

            if (midiFile.midiTracks.Count == 0)
            {
                return;
            }
            MidiTrack metaTrack = midiFile.midiTracks[0];

            for (int currentEvent = 0; currentEvent < metaTrack.midiEvents.Count; currentEvent++)
            {
                byte[] eventData = metaTrack.midiEvents[currentEvent].getEventData();
                if (eventData[0] != 0xFF || eventData[1] != 0x6)   // if event is META and marker type
                {
                    continue;
                }

                if (eventData[2] == 0x1 && Encoding.ASCII.GetString(eventData, 3, 1) == "[")
                {
                    hasLoopStart  = true;
                    loopStartTick = metaTrack.midiEvents[currentEvent].absoluteTicks;
                }
                else if (eventData[2] == 0x1 && Encoding.ASCII.GetString(eventData, 3, 1) == "]")
                {
                    hasLoopEnd  = true;
                    loopEndTick = metaTrack.midiEvents[currentEvent].absoluteTicks;
                }
            }

            // we now got the loop points if there are any
            if (hasLoopStart == false || hasLoopEnd == false)
            {
                Debug.WriteLine("MIDI is not looped!");
                return;
            }
            // now the carryback prevention is done
            for (int currentTrack = 0; currentTrack < midiFile.midiTracks.Count; currentTrack++)
            {
                MidiTrack trk         = midiFile.midiTracks[currentTrack];
                int       midiChannel = getChannelNumberFromTrack(trk); // first of all we need to get the midi channel on the current track

                agbControllerState loopStartState = new agbControllerState();

                if (trk.midiEvents.Count == 0)
                {
                    continue;  // skip the track if it has no events
                }
                if (midiChannel == -1 && currentTrack != 0)
                {
                    continue;       // skip track if it has no midi events and we don't need to consider the tempo track
                }
                int eventAtLoopStart = trk.midiEvents.Count - 1;

                #region recordStartState
                for (int currentEvent = 0; currentEvent < trk.midiEvents.Count; currentEvent++)
                {
                    // now all events get recorded on continously update the loop start state
                    if (trk.midiEvents[currentEvent].absoluteTicks > loopStartTick)
                    {
                        eventAtLoopStart = currentEvent;
                        break;
                    }
                    byte[] eventData = trk.midiEvents[currentEvent].getEventData();
                    if (eventData[0] == 0xFF && eventData[1] == 0x51) // check if META tempo event occurs
                    {
                        loopStartState.Tempo[0] = eventData[3];       // set all tempo values
                        loopStartState.Tempo[1] = eventData[4];
                        loopStartState.Tempo[2] = eventData[5];
                    }
                    else if (eventData[0] >> 4 == 0xB)         // is event a controller event?
                    {
                        if (eventData[1] == 0x1)               // if MOD controller
                        {
                            loopStartState.Mod = eventData[2]; // save mod state
                        }
                        else if (eventData[1] == 0x7)
                        {
                            loopStartState.Volume = eventData[2];   // save volume state
                        }
                        else if (eventData[1] == 0xA)
                        {
                            loopStartState.Pan = eventData[2];  // save pan position
                        }
                        else if (eventData[1] == 0x14)
                        {
                            loopStartState.BendR = eventData[2];    // save pseudo AGB bendr
                        }
                    }
                    else if (eventData[0] >> 4 == 0xC)      // if voice change event
                    {
                        loopStartState.Voice = eventData[1];
                    }
                    else if (eventData[0] >> 4 == 0xE)      // if pitch bend
                    {
                        loopStartState.BendLSB = eventData[1];
                        loopStartState.BendMSB = eventData[2];
                    }
                }
                #endregion

                /* override all changes from the loop start state to the loop end state so we can
                 * continue on with checking the trackdata for carryback errors we need to correct
                 */
                agbControllerState loopEndState = (agbControllerState)loopStartState.Clone();
                // recorded loop start state, now record until

                int eventAtLoopEnd = trk.midiEvents.Count;

                #region recordLoopEndState
                for (int currentEvent = eventAtLoopStart; currentEvent < trk.midiEvents.Count; currentEvent++)
                {
                    // now all events get recorded on continously update the loop start state
                    if (trk.midiEvents[currentEvent].absoluteTicks >= loopEndTick)
                    {
                        // if the loop end occurs before the end of the event data set it's value manually
                        eventAtLoopEnd = currentEvent;
                        break;
                    }
                    byte[] eventData = trk.midiEvents[currentEvent].getEventData();
                    if (eventData[0] == 0xFF && eventData[1] == 0x51) // check if META tempo event occurs
                    {
                        loopEndState.Tempo[0] = eventData[3];         // set all tempo values
                        loopEndState.Tempo[1] = eventData[4];
                        loopEndState.Tempo[2] = eventData[5];
                    }
                    else if (eventData[0] >> 4 == 0xB)  // is event a controller event?
                    {
                        if (eventData[1] == 0x1)
                        {
                            loopEndState.Mod = eventData[2];      // save mod state
                        }
                        else if (eventData[1] == 0x7)
                        {
                            loopEndState.Volume = eventData[2];   // save volume state
                        }
                        else if (eventData[1] == 0xA)
                        {
                            loopEndState.Pan = eventData[2];      // save pan position
                        }
                        else if (eventData[1] == 0x14)
                        {
                            loopEndState.BendR = eventData[2];    // save pseudo AGB bendr
                        }
                    }
                    else if (eventData[0] >> 4 == 0xC)      // if voice change event
                    {
                        loopEndState.Voice = eventData[1];
                    }
                    else if (eventData[0] >> 4 == 0xE)      // if pitch bend
                    {
                        loopEndState.BendLSB = eventData[1];
                        loopEndState.BendMSB = eventData[2];
                    }
                }
                #endregion

                // now we need to fill in the events at the loop end event slot "eventAtLoopEnd"
                // check if the values vary and set them accordingly
                if (!Enumerable.SequenceEqual(loopStartState.Tempo, loopEndState.Tempo) &&
                    loopStartState.Tempo[0] != 0 && loopStartState.Tempo[1] != 0 && loopStartState.Tempo[2] != 0)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MetaMidiEvent(loopStartTick, 0x51, loopStartState.Tempo));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MetaMidiEvent(loopStartTick, 0x51, loopStartState.Tempo));
                    }
                }
                // only do this fixing if the midi channel is actually defined (META only tracks are skipped here)
                if (midiChannel == -1)
                {
                    continue;
                }

                // only fix if voice is a valid voice number (0-127)
                if (loopStartState.Voice != loopEndState.Voice && loopStartState.Voice != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.Program, loopStartState.Voice, 0x0));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.Program, loopStartState.Voice, 0x0));
                    }
                }
                // fix volume
                if (loopStartState.Volume != loopEndState.Volume && loopStartState.Volume != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.Controller, 0x7, loopStartState.Volume));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.Controller, 0x7, loopStartState.Volume));
                    }
                }
                // fix PAN
                if (loopStartState.Pan != loopEndState.Pan && loopStartState.Pan != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.Controller, 0xA, loopStartState.Pan));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.Controller, 0xA, loopStartState.Pan));
                    }
                }
                // fix BENDR
                if (loopStartState.BendR != loopEndState.BendR && loopStartState.BendR != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.Controller, 20, loopStartState.BendR));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.Controller, 20, loopStartState.BendR));
                    }
                }
                // fix MOD
                if (loopStartState.Mod != loopEndState.Mod && loopStartState.Mod != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.Controller, 0x1, loopStartState.Mod));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.Controller, 0x1, loopStartState.Mod));
                    }
                }
                // fix BEND
                if ((loopStartState.BendLSB != loopEndState.BendLSB ||
                     loopStartState.BendMSB != loopEndState.BendMSB) &&
                    loopStartState.BendLSB != 0xFF)
                {
                    if (eventAtLoopStart >= trk.midiEvents.Count)
                    {
                        trk.midiEvents.Add(new MessageMidiEvent(
                                               loopStartTick, (byte)midiChannel, NormalType.PitchBend, loopStartState.BendLSB, loopStartState.BendMSB));
                    }
                    else
                    {
                        trk.midiEvents.Insert(eventAtLoopStart, new MessageMidiEvent(
                                                  loopStartTick, (byte)midiChannel, NormalType.PitchBend, loopStartState.BendLSB, loopStartState.BendMSB));
                    }
                }
            }
        }
Esempio n. 16
0
 /// <summary>Initialize the ProgramChange MIDI event message.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The delta-time since the previous message.</param>
 /// <param name="channel">The channel to which to write the message (0 through 15).</param>
 /// <param name="number">The instrument to which to change.</param>
 public ProgramChangeVoiceMidiEvent(MidiTrack owner, long deltaTime, byte channel, GeneralMidiInstrument number) :
     this(owner, deltaTime, channel, (byte)number)
 {
 }
Esempio n. 17
0
    private void loadStream(Stream stream, bool reloading = false)
    {
        byte[] array = new byte[4];
        stream.Read(array, 0, 4);
        if (Encoding.UTF8.GetString(array, 0, array.Length) != "MThd")
        {
            return;
        }
        midiHeader = new MidiHeader();
        stream.Read(array, 0, 4);
        Array.Reverse(array);
        BitConverter.ToInt32(array, 0);
        array = new byte[2];
        stream.Read(array, 0, 2);
        Array.Reverse(array);
        midiHeader.setMidiFormat(BitConverter.ToInt16(array, 0));
        stream.Read(array, 0, 2);
        Array.Reverse(array);
        int num = BitConverter.ToInt16(array, 0);

        stream.Read(array, 0, 2);
        Array.Reverse(array);
        int num2 = BitConverter.ToInt16(array, 0);

        midiHeader.DeltaTiming = (num2 & 0x7FFF);
        midiHeader.TimeFormat  = (((num2 & 0x8000) > 0) ? MidiHelper.MidiTimeFormat.FamesPerSecond : MidiHelper.MidiTimeFormat.TicksPerBeat);
        bool flag = (!reloading || tracks.Count != num) ? true : false;

        if (flag)
        {
            tracks.Clear();
            seqEvt.Events.Clear();
        }
        int num3 = 0;

        while (true)
        {
            if (num3 >= num)
            {
                return;
            }
            MidiTrack          midiTrack          = null;
            MidiSequencerEvent midiSequencerEvent = null;
            if (flag)
            {
                midiTrack = new MidiTrack();
                tracks.Add(midiTrack);
                midiSequencerEvent = new MidiSequencerEvent();
                seqEvt.Events.Add(midiSequencerEvent);
            }
            else
            {
                midiTrack           = tracks[num3];
                midiTrack.TotalTime = 0uL;
                midiSequencerEvent  = seqEvt.Events[num3];
            }
            List <byte>      list  = new List <byte>();
            List <byte>      list2 = new List <byte>();
            List <MidiEvent> list3 = new List <MidiEvent>();
            list.Add(0);
            list2.Add(0);
            array = new byte[4];
            stream.Read(array, 0, 4);
            if (Encoding.UTF8.GetString(array, 0, array.Length) != "MTrk")
            {
                break;
            }
            stream.Read(array, 0, 4);
            Array.Reverse(array);
            int num4 = BitConverter.ToInt32(array, 0);
            array = new byte[num4];
            stream.Read(array, 0, num4);
            int       i    = 0;
            byte      b    = 0;
            int       num5 = 0;
            MidiEvent midiEvent;
            for (; i < array.Length; list3.Add(midiEvent), tracks[num3].TotalTime = tracks[num3].TotalTime + midiEvent.deltaTime)
            {
                ushort numOfBytes = 0;
                uint   data       = BitConverter.ToUInt32(array, i);
                midiEvent           = new MidiEvent();
                midiEvent.deltaTime = GetTime(data, ref numOfBytes);
                i += 4 - (4 - numOfBytes);
                byte b2   = array[i];
                int  num6 = GetChannel(b2);
                if (b2 < 128)
                {
                    b2   = b;
                    num6 = num5;
                    i--;
                }
                if (b2 != byte.MaxValue)
                {
                    b2 = (byte)(b2 & 0xF0);
                }
                b    = b2;
                num5 = num6;
                switch (b2)
                {
                case 128:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Note_Off;
                    i++;
                    midiEvent.channel       = (byte)num6;
                    midiEvent.Parameters[0] = midiEvent.channel;
                    midiEvent.parameter1    = array[i++];
                    midiEvent.parameter2    = array[i++];
                    midiEvent.Parameters[1] = midiEvent.parameter1;
                    midiEvent.Parameters[2] = midiEvent.parameter2;
                    continue;

                case 144:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Note_On;
                    i++;
                    midiEvent.channel       = (byte)num6;
                    midiEvent.Parameters[0] = midiEvent.channel;
                    midiEvent.parameter1    = array[i++];
                    midiEvent.parameter2    = array[i++];
                    midiEvent.Parameters[1] = midiEvent.parameter1;
                    midiEvent.Parameters[2] = midiEvent.parameter2;
                    if (midiEvent.parameter2 == 0)
                    {
                        midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Note_Off;
                    }
                    tracks[num3].NotesPlayed++;
                    continue;

                case 160:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Note_Aftertouch;
                    midiEvent.channel          = (byte)num6;
                    midiEvent.Parameters[0]    = midiEvent.channel;
                    i++;
                    midiEvent.parameter1 = array[++i];
                    midiEvent.parameter2 = array[++i];
                    continue;

                case 176:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Controller;
                    midiEvent.channel          = (byte)num6;
                    midiEvent.Parameters[0]    = midiEvent.channel;
                    i++;
                    midiEvent.parameter1    = array[i++];
                    midiEvent.parameter2    = array[i++];
                    midiEvent.Parameters[1] = midiEvent.parameter1;
                    midiEvent.Parameters[2] = midiEvent.parameter2;
                    continue;

                case 192:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Program_Change;
                    midiEvent.channel          = (byte)num6;
                    midiEvent.Parameters[0]    = midiEvent.channel;
                    i++;
                    midiEvent.parameter1    = array[i++];
                    midiEvent.Parameters[1] = midiEvent.parameter1;
                    if (midiEvent.channel != 9)
                    {
                        if (!list.Contains(midiEvent.parameter1))
                        {
                            list.Add(midiEvent.parameter1);
                        }
                    }
                    else if (!list2.Contains(midiEvent.parameter1))
                    {
                        list2.Add(midiEvent.parameter1);
                    }
                    continue;

                case 208:
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Channel_Aftertouch;
                    midiEvent.channel          = (byte)num6;
                    midiEvent.Parameters[0]    = midiEvent.channel;
                    i++;
                    midiEvent.parameter1 = array[++i];
                    continue;

                case 224:
                {
                    midiEvent.midiChannelEvent = MidiHelper.MidiChannelEvent.Pitch_Bend;
                    midiEvent.channel          = (byte)num6;
                    midiEvent.Parameters[0]    = midiEvent.channel;
                    i++;
                    midiEvent.parameter1 = array[++i];
                    midiEvent.parameter2 = array[++i];
                    ushort parameter = midiEvent.parameter1;
                    parameter = (ushort)(parameter << 7);
                    parameter = (ushort)(parameter | midiEvent.parameter2);
                    midiEvent.Parameters[1] = ((double)(int)parameter - 8192.0) / 8192.0;
                    continue;
                }

                case byte.MaxValue:
                    switch (array[++i])
                    {
                    case 0:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Sequence_Number;
                        i++;
                        break;

                    case 1:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Text_Event;
                        i++;
                        midiEvent.parameter1    = array[i++];
                        midiEvent.Parameters[0] = midiEvent.parameter1;
                        midiEvent.Parameters[1] = Encoding.UTF8.GetString(array, i, array[i - 1]);
                        i += array[i - 1];
                        break;

                    case 2:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Copyright_Notice;
                        i++;
                        midiEvent.parameter1    = array[i++];
                        midiEvent.Parameters[0] = midiEvent.parameter1;
                        midiEvent.Parameters[1] = Encoding.UTF8.GetString(array, i, array[i - 1]);
                        i += array[i - 1];
                        break;

                    case 3:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Sequence_Or_Track_Name;
                        i++;
                        midiEvent.parameter1    = array[i++];
                        midiEvent.Parameters[0] = midiEvent.parameter1;
                        midiEvent.Parameters[1] = Encoding.UTF8.GetString(array, i, array[i - 1]);
                        i += array[i - 1];
                        break;

                    case 4:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Instrument_Name;
                        i++;
                        midiEvent.Parameters[0] = Encoding.UTF8.GetString(array, i + 1, array[i]);
                        i += array[i] + 1;
                        break;

                    case 5:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Lyric_Text;
                        i++;
                        midiEvent.Parameters[0] = Encoding.UTF8.GetString(array, i + 1, array[i]);
                        i += array[i] + 1;
                        break;

                    case 6:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Marker_Text;
                        i++;
                        midiEvent.Parameters[0] = Encoding.UTF8.GetString(array, i + 1, array[i]);
                        i += array[i] + 1;
                        break;

                    case 7:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Cue_Point;
                        i++;
                        midiEvent.Parameters[0] = Encoding.UTF8.GetString(array, i + 1, array[i]);
                        i += array[i] + 1;
                        break;

                    case 32:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Midi_Channel_Prefix_Assignment;
                        i++;
                        midiEvent.parameter1    = array[i++];
                        midiEvent.Parameters[0] = midiEvent.parameter1;
                        midiEvent.Parameters[1] = array[i++];
                        break;

                    case 47:
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.End_of_Track;
                        i += 2;
                        break;

                    case 81:
                    {
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Tempo;
                        i++;
                        midiEvent.Parameters[4] = array[i++];
                        byte[] array3 = new byte[4];
                        for (int num29 = 0; num29 < 3; num29++)
                        {
                            array3[num29 + 1] = array[num29 + i];
                        }
                        i += 3;
                        byte[] array4 = new byte[4];
                        for (int num30 = 0; num30 < 4; num30++)
                        {
                            array4[3 - num30] = array3[num30];
                        }
                        uint num31 = BitConverter.ToUInt32(array4, 0);
                        midiEvent.Parameters[0] = num31;
                        break;
                    }

                    case 84:
                    {
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Smpte_Offset;
                        i++;
                        int num16 = array[i++];
                        if (num16 >= 4)
                        {
                            for (int n = 0; n < 4; n++)
                            {
                                midiEvent.Parameters[n] = array[i++];
                            }
                        }
                        else
                        {
                            for (int num18 = 0; num18 < num16; num18++)
                            {
                                midiEvent.Parameters[num18] = array[i++];
                            }
                        }
                        for (int num20 = 4; num20 < num16; num20++)
                        {
                            i++;
                        }
                        break;
                    }

                    case 88:
                    {
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Time_Signature;
                        i++;
                        int num22 = array[i++];
                        if (num22 >= 4)
                        {
                            for (int num23 = 0; num23 < 4; num23++)
                            {
                                midiEvent.Parameters[num23] = array[i++];
                            }
                        }
                        else
                        {
                            for (int num25 = 0; num25 < num22; num25++)
                            {
                                midiEvent.Parameters[num25] = array[i++];
                            }
                        }
                        for (int num27 = 4; num27 < num22; num27++)
                        {
                            i++;
                        }
                        break;
                    }

                    case 89:
                    {
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Key_Signature;
                        i++;
                        int num10 = array[i++];
                        if (num10 >= 4)
                        {
                            for (int k = 0; k < 4; k++)
                            {
                                midiEvent.Parameters[k] = array[i++];
                            }
                        }
                        else
                        {
                            for (int l = 0; l < num10; l++)
                            {
                                midiEvent.Parameters[l] = array[i++];
                            }
                        }
                        for (int m = 4; m < num10; m++)
                        {
                            i++;
                        }
                        break;
                    }

                    case 127:
                    {
                        midiEvent.midiMetaEvent = MidiHelper.MidiMetaEvent.Sequencer_Specific_Event;
                        i++;
                        midiEvent.Parameters[4] = array[i++];
                        byte[] array2 = new byte[(byte)midiEvent.Parameters[4]];
                        for (int j = 0; j < array2.Length; j++)
                        {
                            array2[j] = array[i++];
                        }
                        midiEvent.Parameters[0] = array2;
                        break;
                    }
                    }
                    continue;

                case 240:
                    break;

                default:
                    continue;
                }
                for (; array[i] != 247; i++)
                {
                }
                i++;
            }
            tracks[num3].Programs     = list.ToArray();
            tracks[num3].DrumPrograms = list2.ToArray();
            tracks[num3].MidiEvents   = list3.ToArray();
            num3++;
        }
        throw new Exception("Invalid track!");
    }
Esempio n. 18
0
        /// <summary>
        /// Creates a notechart from the specified midi path and the actual charttype
        /// (i.e. ExpertSingle from notes.mid).  Due to the overhead necessary to
        /// parse a midi file.  I am going to cram all midi->chart operations into
        /// one function call.
        /// This function uses the Toub midi parser which is much faster than Sanford,
        /// but will throw an exception on certian midi files.
        /// </summary>
        /// <param name="chartSelection">
        /// The information on which particular notechart to use.
        /// </param>
        /// <param name="chartInfo">The metadata on the chart.</param>
        /// <param name="BPMChanges">The list of BPM changes for this chart.</param>
        /// <returns>
        /// A filled out Notechart containing the needed information from the *.mid file.
        /// </returns>
        public static Notes ParseMidiInformationToub(ChartSelection chartSelection,
                                                     Info chartInfo,
                                                     List <BPMChange> BPMChanges)
        {
            Notes notechartToReturn = new Notes();

            notechartToReturn.instrument = chartSelection.instrument;
            notechartToReturn.difficulty = chartSelection.difficulty;

            // The following two switch's are used to get the proper midi terminology for
            // the selected track and difficulty.
            string instrumentPart = null;
            string greenKey       = null;
            string redKey         = null;
            string yellowKey      = null;
            string blueKey        = null;
            string orangeKey      = null;

            switch (chartSelection.instrument)
            {
            case "Single":
                instrumentPart = "PART GUITAR";
                break;

            case "DoubleGuitar":
                instrumentPart = "PART GUITAR COOP";
                break;

            case "DoubleBass":
                instrumentPart = "PART BASS";
                break;

            case "Drums":
                instrumentPart = "PART DRUMS";
                break;

            default:
                instrumentPart = "PART GUITAR";
                break;
            }

            switch (chartSelection.difficulty)
            {
            case "Expert":
                greenKey  = "C8";
                redKey    = "C#8";
                yellowKey = "D8";
                blueKey   = "D#8";
                orangeKey = "E8";
                break;

            case "Hard":
                greenKey  = "C7";
                redKey    = "C#7";
                yellowKey = "D7";
                blueKey   = "D#7";
                orangeKey = "E7";
                break;

            case "Medium":
                greenKey  = "C6";
                redKey    = "C#6";
                yellowKey = "D6";
                blueKey   = "D#6";
                orangeKey = "E6";
                break;

            case "Easy":
                greenKey  = "C5";
                redKey    = "C#5";
                yellowKey = "D5";
                blueKey   = "D#5";
                orangeKey = "E5";
                break;

            default:
                greenKey  = "C8";
                redKey    = "C#8";
                yellowKey = "D8";
                blueKey   = "D#8";
                orangeKey = "E8";
                break;
            }

            MidiSequence mySequence = MidiSequence.Import(chartSelection.directory + "\\notes.mid");

            MidiTrack[] myTracks = mySequence.GetTracks();
            chartInfo.resolution = mySequence.Division;

            MidiTrack trackToUse     = new MidiTrack();
            uint      totalTickValue = 0;

            // Go through each event in the first track (which contains the BPM changes)
            // and parse the resulting string.
            for (int i = 0; i < myTracks[0].Events.Count; i++)
            {
                Toub.Sound.Midi.MidiEvent currEvent = myTracks[0].Events[i];
                string   eventString      = currEvent.ToString();
                string[] splitEventString = eventString.Split('\t');

                // Since ticks are stored relative to each other (e.g. 300 ticks
                // until next note), we must maintain the total tick amout.
                totalTickValue += Convert.ToUInt32(splitEventString[1]);
                if (splitEventString[0] == "Tempo")
                {
                    // In midi files, bpm chages are stored as "microseconds per quarter note"
                    // and must be converted to BPM, and then into the non decimal format the game
                    // uses.
                    double currBPMDouble = 60000000 / Convert.ToDouble(splitEventString[3]);
                    uint   BPMToAdd      = (uint)(currBPMDouble * 1000);
                    BPMChanges.Add(new BPMChange(totalTickValue, BPMToAdd));
                }
            }

            trackToUse = new MidiTrack();
            // Find the specified instrument's track
            foreach (MidiTrack currTrack in myTracks)
            {
                string   trackHeader = currTrack.Events[0].ToString();
                string[] splitHeader = trackHeader.Split('\t');

                // -If we come across a "T1 GEMS" track, we're in GH1 territory.
                // -GH2/FoF has both PART BASS and PART RHYTHM (one or the other depending
                //  on the chart).
                if (((splitHeader[3] == instrumentPart) || (splitHeader[3] == "T1 GEMS")) ||
                    ((splitHeader[3] == "PART RHYTHM") && (instrumentPart == "PART BASS")))
                {
                    trackToUse = currTrack;
                }
            }

            totalTickValue = 0;
            uint currTickValue = 0;
            Note currNote      = new Note();
            bool blankNote     = true;

            // Scan through and record every note specific to the selected difficulty
            for (int i = 0; i < trackToUse.Events.Count; i++)
            {
                string   currEvent  = trackToUse.Events[i].ToString();
                string[] splitEvent = currEvent.Split('\t');
                currTickValue   = Convert.ToUInt32(splitEvent[1]);
                totalTickValue += currTickValue;

                // We need to specify wether a note is blank or not so we don't add
                // blank notes from other difficulties into the chart, but if we have
                // a filled out note, any nonzero tick value means we are moving to a
                // new note, so we must cut our ties and add this note to the chart.
                if ((currTickValue != 0) && !blankNote)
                {
                    notechartToReturn.notes.Add(currNote);
                    currNote  = new Note();
                    blankNote = true;
                }

                // The "0x64" I think means "not was hit."  There is another
                // set of notes that use "0x00" that all appear slightly after
                // the "0x64" notes.
                if ((splitEvent[0] == "NoteOn") && (splitEvent[4] != "0x00"))
                {
                    // Only consider notes within the octave our difficulty is in.
                    if ((splitEvent[3] == greenKey) || (splitEvent[3] == redKey) ||
                        (splitEvent[3] == yellowKey) || (splitEvent[3] == blueKey) ||
                        (splitEvent[3] == orangeKey))
                    {
                        // If it's a new note, we need to setup the tick value of it.
                        if (blankNote)
                        {
                            currNote.tickValue = totalTickValue;
                            blankNote          = false;
                        }
                        if (splitEvent[3] == greenKey)
                        {
                            currNote.addNote(0);
                        }
                        else if (splitEvent[3] == redKey)
                        {
                            currNote.addNote(1);
                        }
                        else if (splitEvent[3] == yellowKey)
                        {
                            currNote.addNote(2);
                        }
                        else if (splitEvent[3] == blueKey)
                        {
                            currNote.addNote(3);
                        }
                        else if (splitEvent[3] == orangeKey)
                        {
                            currNote.addNote(4);
                        }
                    }
                }
            }

            return(notechartToReturn);
        }
Esempio n. 19
0
 public override void ExecuteEvent(MidiTrack track)
 {
     track.SetTempo(tempo);
 }
        private void WriteMidiTrack(MidiTrack obj)
        {
            track_strings = new List <string>();

            Write((byte)1);
            if (first_track || obj.Name == "EVENTS")
            {
                Write(-1);
            }
            else
            {
                Write(0);
            }
            first_track = false;
            // Subtract 1 for the end-of-track event
            Write(obj.Messages.Count - 1);
            uint ticks = 0;

            foreach (var m in obj.Messages)
            {
                byte kind, d1, d2, d3;
                switch (m)
                {
                case NoteOffEvent e:
                    kind = 1;
                    d1   = (byte)(0x80 | e.Channel);
                    d2   = e.Key;
                    d3   = e.Velocity;
                    break;

                case NoteOnEvent e:
                    kind = 1;
                    d1   = (byte)(0x90 | e.Channel);
                    d2   = e.Key;
                    d3   = e.Velocity;
                    break;

                case ControllerEvent e:
                    kind = 1;
                    d1   = (byte)(0xB0 | e.Channel);
                    d2   = e.Controller;
                    d3   = e.Value;
                    break;

                case ProgramChgEvent e:
                    kind = 1;
                    d1   = (byte)(0xC0 | e.Channel);
                    d2   = e.Program;
                    d3   = 0;
                    break;

                case ChannelPressureEvent e:
                    kind = 1;
                    d1   = (byte)(0xD0 | e.Channel);
                    d2   = e.Pressure;
                    d3   = 0;
                    break;

                case PitchBendEvent e:
                    kind = 1;
                    d1   = (byte)(0xE0 | e.Channel);
                    d2   = (byte)(e.Bend & 0xFF);
                    d3   = (byte)(e.Bend >> 8);
                    break;

                case TempoEvent e:
                    kind = 2;
                    d1   = (byte)(e.MicrosPerQn >> 16);
                    d2   = (byte)(e.MicrosPerQn & 0xFFU);
                    d3   = (byte)((e.MicrosPerQn >> 8) & 0xFFU);
                    break;

                case TimeSignature e:
                    kind = 4;
                    d1   = e.Numerator;
                    d2   = (byte)(1 << e.Denominator);
                    d3   = 0;
                    break;

                case MetaTextEvent e:
                    kind = 8;
                    var idx = GetString(e.Text);
                    d2 = (byte)(idx & 0xFF);
                    d3 = (byte)(idx >> 8);
                    switch (e)
                    {
                    case TextEvent x:
                        d1 = 1;
                        break;

                    case TrackName x:
                        d1 = 3;
                        break;

                    case Lyric x:
                        d1 = 5;
                        break;

                    default:
                        d1 = 1;
                        break;
                    }
                    break;

                case EndOfTrackEvent e:
                    continue;

                default:
                    throw new Exception("Unknown Midi Message type");
                }
                ticks += m.DeltaTime;
                Write(ticks);
                Write(kind);
                Write(d1);
                Write(d2);
                Write(d3);
            }
            Write(track_strings.Count);
            track_strings.ForEach(Write);
        }
Esempio n. 21
0
 /** Return true if this track contains multiple channels.
  * If a MidiFile contains only one track, and it has multiple channels,
  * then we treat each channel as a separate track.
  */
 static bool HasMultipleChannels(MidiTrack track)
 {
     int channel = track.Notes[0].Channel;
     foreach (MidiNote note in track.Notes) {
     if (note.Channel != channel) {
         return true;
     }
     }
     return false;
 }
Esempio n. 22
0
        //***************************************************************
        // PUBLIC UTILITIES
        //***************************************************************

        //---------------------------------------------------------------
        // returns list of drumset instrument names
        //---------------------------------------------------------------

        /* ## TO DO
         * function getDrumset(){
         *  return array(
         *  35=>'Acoustic Bass Drum',
         *  36=>'Bass Drum 1',
         *  37=>'Side Stick',
         *  38=>'Acoustic Snare',
         *  39=>'Hand Clap',
         *  40=>'Electric Snare',
         *  41=>'Low Floor Tom',
         *  42=>'Closed Hi-Hat',
         *  43=>'High Floor Tom',
         *  44=>'Pedal Hi-Hat',
         *  45=>'Low Tom',
         *  46=>'Open Hi-Hat',
         *  47=>'Low Mid Tom',
         *  48=>'High Mid Tom',
         *  49=>'Crash Cymbal 1',
         *  50=>'High Tom',
         *  51=>'Ride Cymbal 1',
         *  52=>'Chinese Cymbal',
         *  53=>'Ride Bell',
         *  54=>'Tambourine',
         *  55=>'Splash Cymbal',
         *  56=>'Cowbell',
         *  57=>'Crash Cymbal 2',
         *  58=>'Vibraslap',
         *  59=>'Ride Cymbal 2',
         *  60=>'High Bongo',
         *  61=>'Low Bongo',
         *  62=>'Mute High Conga',
         *  63=>'Open High Conga',
         *  64=>'Low Conga',
         *  65=>'High Timbale',
         *  66=>'Low Timbale',
         *  //35..66
         *  67=>'High Agogo',
         *  68=>'Low Agogo',
         *  69=>'Cabase',
         *  70=>'Maracas',
         *  71=>'Short Whistle',
         *  72=>'Long Whistle',
         *  73=>'Short Guiro',
         *  74=>'Long Guiro',
         *  75=>'Claves',
         *  76=>'High Wood Block',
         *  77=>'Low Wood Block',
         *  78=>'Mute Cuica',
         *  79=>'Open Cuica',
         *  80=>'Mute Triangle',
         *  81=>'Open Triangle');
         * }
         */

        //---------------------------------------------------------------
        // returns list of standard drum kit names
        //---------------------------------------------------------------

        /* ## TO DO
         * function getDrumkitList(){
         *  return array(
         *      1   => 'Dry',
         *      9   => 'Room',
         *      19  => 'Power',
         *      25  => 'Electronic',
         *      33  => 'Jazz',
         *      41  => 'Brush',
         *      57  => 'SFX',
         *      128 => 'Default'
         *  );
         * }
         */

        //---------------------------------------------------------------
        // returns list of note names
        //---------------------------------------------------------------

        /*
         * function getNoteList(){
         * //note 69 (A6) = A440
         * //note 60 (C6) = Middle C
         *  return array(
         *  //Do          Re           Mi    Fa           So           La           Ti
         *  'C0', 'Cs0', 'D0', 'Ds0', 'E0', 'F0', 'Fs0', 'G0', 'Gs0', 'A0', 'As0', 'B0',
         *  'C1', 'Cs1', 'D1', 'Ds1', 'E1', 'F1', 'Fs1', 'G1', 'Gs1', 'A1', 'As1', 'B1',
         *  'C2', 'Cs2', 'D2', 'Ds2', 'E2', 'F2', 'Fs2', 'G2', 'Gs2', 'A2', 'As2', 'B2',
         *  'C3', 'Cs3', 'D3', 'Ds3', 'E3', 'F3', 'Fs3', 'G3', 'Gs3', 'A3', 'As3', 'B3',
         *  'C4', 'Cs4', 'D4', 'Ds4', 'E4', 'F4', 'Fs4', 'G4', 'Gs4', 'A4', 'As4', 'B4',
         *  'C5', 'Cs5', 'D5', 'Ds5', 'E5', 'F5', 'Fs5', 'G5', 'Gs5', 'A5', 'As5', 'B5',
         *  'C6', 'Cs6', 'D6', 'Ds6', 'E6', 'F6', 'Fs6', 'G6', 'Gs6', 'A6', 'As6', 'B6',
         *  'C7', 'Cs7', 'D7', 'Ds7', 'E7', 'F7', 'Fs7', 'G7', 'Gs7', 'A7', 'As7', 'B7',
         *  'C8', 'Cs8', 'D8', 'Ds8', 'E8', 'F8', 'Fs8', 'G8', 'Gs8', 'A8', 'As8', 'B8',
         *  'C9', 'Cs9', 'D9', 'Ds9', 'E9', 'F9', 'Fs9', 'G9', 'Gs9', 'A9', 'As9', 'B9',
         *  'C10','Cs10','D10','Ds10','E10','F10','Fs10','G10');
         * }
         */
        #endregion

        private MidiTrack parseTrack(byte[] data, int trackNumber)
        {
            MidiTrack track = new MidiTrack();

            int trackLen = data.Length;

            int       position     = 0;
            long      currentTicks = 0;
            int       currentDelta;
            byte      eventType;
            int       eventTypeHigh;
            int       eventTypeLow;
            byte      meta;
            int       num;
            int       len;
            byte      tmp;
            byte      c;
            string    txt;
            MidiEvent evt;

            int  currentTempo   = 0;
            long lastTempoTicks = -1;

            while (position < trackLen)
            {
                // timedelta
                currentDelta  = readVarLen(ref data, ref position);
                currentTicks += currentDelta;

                eventType     = data[position];
                eventTypeHigh = (eventType >> 4);
                eventTypeLow  = (eventType - eventTypeHigh * 16);
                switch (eventTypeHigh)
                {
                case MidiEvents.EVT_PROGRAM_CHANGE:     //PrCh = ProgramChange
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1]);
                    evt.Description = " PrCh ch=" + evt.Channel + " p=" + evt.Param0;
                    track.Add(evt);

                    position += 2;
                    break;

                case MidiEvents.EVT_NOTE_ON:     //On
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1], data[position + 2]);
                    evt.Description = " On ch=" + evt.Channel + " n=" + evt.Param0 + " v=" + evt.Param1;
                    track.Add(evt);

                    position += 3;
                    break;

                case MidiEvents.EVT_NOTE_OFF:     //Off
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1], data[position + 2]);
                    evt.Description = " Off ch=" + evt.Channel + " n=" + evt.Param0 + " v=" + evt.Param1;
                    track.Add(evt);

                    position += 3;
                    break;

                case MidiEvents.EVT_POLY_PRESSURE:     //PoPr = PolyPressure
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1], data[position + 2]);
                    evt.Description = " PoPr ch=" + evt.Channel + " n=" + evt.Param0 + " v=" + evt.Param1;
                    track.Add(evt);

                    position += 3;
                    break;

                case MidiEvents.EVT_CONTROLLER_CHANGE:     //Par = ControllerChange
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1], data[position + 2]);
                    evt.Description = " Par ch=" + evt.Channel + " c=" + evt.Param0 + " v=" + evt.Param1;
                    track.Add(evt);

                    position += 3;
                    break;

                case MidiEvents.EVT_CHANNEL_PRESSURE:     //ChPr = ChannelPressure
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, data[position + 1]);
                    evt.Description = " ChPr ch=" + evt.Channel + " v=" + evt.Param0;
                    track.Add(evt);

                    position += 2;
                    break;

                case MidiEvents.EVT_PITCH_BEND:     //Pb = PitchBend
                    evt             = new MidiEvent(currentTicks, eventTypeHigh, eventTypeLow + 1, (data[position + 1] & 0x7F) | ((data[position + 2] & 0x7F) << 7));
                    evt.Description = " Pb ch=" + evt.Channel + " v=" + evt.Param0;
                    track.Add(evt);

                    position += 3;
                    break;

                default:
                    switch (eventType)
                    {
                    case 0xFF:         // Meta
                        meta = data[position + 1];
                        switch (meta)
                        {
                        case MidiEvents.META_SEQUENCE_NUM:             // sequence_number
                            tmp = data[position + 2];
                            if (tmp == 0x00)
                            {
                                num = trackNumber; position += 3;
                            }
                            else
                            {
                                num = 1; position += 5;
                            }

                            evt             = new MidiEvent(currentTicks, meta, -1, num);
                            evt.isMetaEvent = true;
                            evt.Description = " Seqnr " + evt.Param0;
                            track.Add(evt);

                            break;

                        case MidiEvents.META_TEXT:            // Meta Text
                        case MidiEvents.META_COPYRIGHT:       // Meta Copyright
                        case MidiEvents.META_TRACK_NAME:      // Meta TrackName ???sequence_name???
                        case MidiEvents.META_INSTRUMENT_NAME: // Meta InstrumentName
                        case MidiEvents.META_LYRICS:          // Meta Lyrics
                        case MidiEvents.META_MARKER:          // Meta Marker
                        case MidiEvents.META_CUE:             // Meta Cue
                            string[] texttypes = new string[7] {
                                "Text", "Copyright", "TrkName", "InstrName", "Lyric", "Marker", "Cue"
                            };

                            string textType = texttypes[meta - 1];
                            position += 2;
                            len       = readVarLen(ref data, ref position);
                            if ((len + position) > trackLen)
                            {
                                throw new InvalidDataException("Meta " + textType + " has corrupt variable length field (" + len + ") [track: " + trackNumber + " dt: " + currentDelta + "]");
                            }

                            txt = Encoding.ASCII.GetString(data, position, len);
                            if (MidiEvents.META_TEXT == meta || MidiEvents.META_TRACK_NAME == meta || MidiEvents.META_MARKER == meta)
                            {
                                comment.Append(txt).Append(Settings.InternalValueSeparator);
                            }
                            else if (MidiEvents.META_COPYRIGHT == meta)
                            {
                                tagData.IntegrateValue(TagData.TAG_FIELD_COPYRIGHT, txt);
                            }

                            evt             = new MidiEvent(currentTicks, meta, -1, meta - 1);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta " + textType + " \"" + txt + "\"";
                            track.Add(evt);

                            position += len;
                            break;

                        case MidiEvents.META_CHANNEL_PREFIX:             // ChannelPrefix
                            evt             = new MidiEvent(currentTicks, meta, -1, data[position + 3]);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta ChannelPrefix " + evt.Param0;
                            track.Add(evt);

                            position += 4;
                            break;

                        case MidiEvents.META_CHANNEL_PREFIX_PORT:             // ChannelPrefixOrPort
                            evt             = new MidiEvent(currentTicks, meta, -1, data[position + 3]);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta ChannelPrefixOrPort " + evt.Param0;
                            track.Add(evt);

                            position += 4;
                            break;

                        case MidiEvents.META_TRACK_END:             // Meta TrkEnd
                            evt             = new MidiEvent(currentTicks, meta, -1, -1);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta TrkEnd";
                            track.Add(evt);

                            track.Ticks = currentTicks;
                            if (lastTempoTicks > -1)             // there has been at least one tempo change in the track
                            {
                                track.Duration += (currentTicks - lastTempoTicks) * currentTempo;
                            }
                            else
                            {
                                track.Duration = currentTicks * this.tempo;
                            }
                            return(track);           //ignore rest

                        case MidiEvents.META_TEMPO:  // Tempo
                            // Adds (ticks since last tempo event)*current tempo to track duration
                            if (lastTempoTicks > -1)
                            {
                                track.Duration += (currentTicks - lastTempoTicks) * currentTempo;
                            }
                            lastTempoTicks = currentTicks;

                            currentTempo = data[position + 3] * 0x010000 + data[position + 4] * 0x0100 + data[position + 5];
                            if (0 == currentTempo)
                            {
                                currentTempo = DEFAULT_TEMPO;
                            }

                            evt             = new MidiEvent(currentTicks, meta, -1, currentTempo);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta Tempo " + evt.Param0 + " (duration :" + track.Duration + ")";
                            track.Add(evt);

                            // Sets song tempo as last tempo event of 1st track
                            // according to some MIDI files convention
                            if (0 == trackNumber /* && 0 == this.tempo*/)
                            {
                                this.tempo       = currentTempo;
                                this.tempoMsgNum = track.events.Count - 1;
                            }
                            position += 6;
                            break;

                        case MidiEvents.META_SMPTE_OFFSET:             // SMPTE offset
                            byte h  = data[position + 3];
                            byte m  = data[position + 4];
                            byte s  = data[position + 5];
                            byte f  = data[position + 6];
                            byte fh = data[position + 7];

                            // TODO : store the arguments in a solid structure within MidiEvent
                            evt             = new MidiEvent(currentTicks, meta, -1, -1);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta SMPTE " + h + " " + m + " " + s + " " + f + " " + fh;
                            track.Add(evt);

                            position += 8;
                            break;

                        case MidiEvents.META_TIME_SIGNATURE:             // TimeSig
                            byte z  = data[position + 3];
                            int  t  = 2 ^ data[position + 4];
                            byte mc = data[position + 5];
                            c = data[position + 6];

                            // TODO : store the arguments in a solid structure within MidiEvent
                            evt             = new MidiEvent(currentTicks, meta, -1, -1);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta TimeSig " + z + "/" + t + " " + mc + " " + c;
                            track.Add(evt);

                            position += 7;
                            break;

                        case MidiEvents.META_KEY_SIGNATURE:             // KeySig
                            evt             = new MidiEvent(currentTicks, meta, -1, data[position + 3], data[position + 4]);
                            evt.isMetaEvent = true;
                            evt.Description = " Meta KeySig vz=" + evt.Param0 + " " + (evt.Param1 == 0 ? "major" : "minor");
                            track.Add(evt);

                            position += 5;
                            break;

                        case MidiEvents.META_SEQUENCER_DATA:             // Sequencer specific data
                            position += 2;
                            len       = readVarLen(ref data, ref position);
                            if ((len + position) > trackLen)
                            {
                                throw new InvalidDataException("SeqSpec has corrupt variable length field (" + len + ") [track: " + trackNumber + " dt: " + currentDelta + "]");
                            }
                            position -= 3;
                            {
                                //String str = Encoding.ASCII.GetString(data, position + 3, len); //data.=' '.sprintf("%02x",(byte)($data[$p+3+$i]));
                                evt             = new MidiEvent(currentTicks, meta, -1, currentTempo);
                                evt.isMetaEvent = true;
                                evt.Description = " Meta SeqSpec";
                                track.Add(evt);
                            }
                            position += len + 3;
                            break;

                        default:
                            // "unknown" Meta-Events
                            byte metacode = data[position + 1];
                            position += 2;
                            len       = readVarLen(ref data, ref position);
                            if ((len + position) > trackLen)
                            {
                                throw new InvalidDataException("Meta " + metacode + " has corrupt variable length field (" + len + ") [track: " + trackNumber + " dt: " + currentDelta + "]");
                            }
                            position -= 3;
                            {
                                String str = Encoding.ASCII.GetString(data, position + 3, len);             //sprintf("%02x",(byte)($data[$p+3+$i]));
                                evt             = new MidiEvent(currentTicks, meta, -1, currentTempo);
                                evt.isMetaEvent = true;
                                evt.Description = " Meta 0x" + metacode + " " + str;
                                track.Add(evt);
                            }
                            position += len + 3;

                            break;
                        }                      // switch meta
                        break;                 // End Meta

                    case MidiEvents.EVT_SYSEX: // SysEx
                        position += 1;
                        len       = readVarLen(ref data, ref position);
                        if ((len + position) > trackLen)
                        {
                            throw new InvalidDataException("SysEx has corrupt variable length field (" + len + ") [track: " + trackNumber + " dt: " + currentDelta + " p: " + position + "]");
                        }
                        {
                            //String str = "f0" + Encoding.ASCII.GetString(data, position + 2, len); //str+=' '.sprintf("%02x",(byte)(data[p+2+i]));
                            evt             = new MidiEvent(currentTicks, eventTypeHigh, -1, currentTempo);
                            evt.isMetaEvent = true;
                            evt.Description = " SysEx";
                            track.Add(evt);
                        }
                        position += len;
                        break;

                    default:         // Repetition of last event?
                        if ((track.LastEvent.Type == MidiEvents.EVT_NOTE_ON) || (track.LastEvent.Type == MidiEvents.EVT_NOTE_OFF))
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, data[position], data[position + 1]);
                            evt.Description = " " + (track.LastEvent.Type == MidiEvents.EVT_NOTE_ON ? "On" : "Off") + " ch=" + evt.Channel + " n=" + evt.Param0 + " v=" + evt.Param1;
                            track.Add(evt);

                            position += 2;
                        }
                        else if (track.LastEvent.Type == MidiEvents.EVT_PROGRAM_CHANGE)
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, data[position]);
                            evt.Description = " PrCh ch=" + evt.Channel + " p=" + evt.Param0;
                            track.Add(evt);

                            position += 1;
                        }
                        else if (track.LastEvent.Type == MidiEvents.EVT_POLY_PRESSURE)
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, data[position + 1], data[position + 2]);
                            evt.Description = " PoPr ch=" + evt.Channel + " n=" + evt.Param0 + " v=" + evt.Param1;
                            track.Add(evt);

                            position += 2;
                        }
                        else if (track.LastEvent.Type == MidiEvents.EVT_CHANNEL_PRESSURE)
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, data[position]);
                            evt.Description = " ChPr ch=" + evt.Channel + " v=" + evt.Param0;
                            track.Add(evt);

                            position += 1;
                        }
                        else if (track.LastEvent.Type == MidiEvents.EVT_CONTROLLER_CHANGE)
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, data[position], data[position + 1]);
                            evt.Description = " Par ch=" + evt.Channel + " c=" + evt.Param0 + " v=" + evt.Param1;
                            track.Add(evt);

                            position += 2;
                        }
                        else if (track.LastEvent.Type == MidiEvents.EVT_PITCH_BEND)
                        {
                            evt             = new MidiEvent(currentTicks, track.LastEvent.Type, track.LastEvent.Channel, (data[position] & 0x7F) | ((data[position + 1] & 0x7F) << 7));
                            evt.Description = " Pb ch=" + evt.Channel + " v=" + evt.Param0;
                            track.Add(evt);

                            position += 2;
                        }
                        //default:
                        // MM: ToDo: Repetition of SysEx and META-events? with <last>?? \n";
                        //  _err("unknown repetition: $last");
                        break;
                    }     // eventType
                    break;
                } // $high
            } // while p < trackLen
            track.Ticks = currentTicks;
            if (lastTempoTicks > -1)
            {
                track.Duration += (currentTicks - lastTempoTicks) * currentTempo;
            }
            else
            {
                track.Duration = currentTicks * this.tempo;
            }

            return(track);
        }
Esempio n. 23
0
        /** Split the given track into multiple tracks, separating each
         * channel into a separate track.
         */
        private static List<MidiTrack> SplitChannels(MidiTrack origtrack, List<MidiEvent> events)
        {
            /* Find the instrument used for each channel */
            int[] channelInstruments = new int[16];
            foreach (MidiEvent mevent in events) {
            if (mevent.EventFlag == EventProgramChange) {
                channelInstruments[mevent.Channel] = mevent.Instrument;
            }
            }
            channelInstruments[9] = 128; /* Channel 9 = Percussion */

            List<MidiTrack> result = new List<MidiTrack>();
            foreach (MidiNote note in origtrack.Notes) {
            bool foundchannel = false;
            foreach (MidiTrack track in result) {
                if (note.Channel == track.Notes[0].Channel) {
                    foundchannel = true;
                    track.AddNote(note);
                }
            }
            if (!foundchannel) {
                MidiTrack track = new MidiTrack(result.Count + 1);
                track.AddNote(note);
                track.Instrument = channelInstruments[note.Channel];
                result.Add(track);
            }
            }
            return result;
        }
Esempio n. 24
0
 public SequencerPointer(MidiTrack track, int eventIndex)
 {
     Track      = track;
     EventIndex = eventIndex;
 }
Esempio n. 25
0
        /** Combine the notes in the given tracks into a single MidiTrack.
         *  The individual tracks are already sorted.  To merge them, we
         *  use a mergesort-like algorithm.
         */
        public static MidiTrack CombineToSingleTrack(List<MidiTrack> tracks)
        {
            /* Add all notes into one track */
            MidiTrack result = new MidiTrack(1);

            if (tracks.Count == 0) {
            return result;
            }
            else if (tracks.Count == 1) {
            MidiTrack track = tracks[0];
            foreach (MidiNote note in track.Notes) {
                result.AddNote(note);
            }
            return result;
            }

            int[] noteindex = new int[64];
            int[] notecount = new int[64];

            for (int tracknum = 0; tracknum < tracks.Count; tracknum++) {
            noteindex[tracknum] = 0;
            notecount[tracknum] = tracks[tracknum].Notes.Count;
            }
            MidiNote prevnote = null;
            while (true) {
            MidiNote lowestnote = null;
            int lowestTrack = -1;
            for (int tracknum = 0; tracknum < tracks.Count; tracknum++) {
                MidiTrack track = tracks[tracknum];
                if (noteindex[tracknum] >= notecount[tracknum]) {
                    continue;
                }
                MidiNote note = track.Notes[ noteindex[tracknum] ];
                if (lowestnote == null) {
                    lowestnote = note;
                    lowestTrack = tracknum;
                }
                else if (note.StartTime < lowestnote.StartTime) {
                    lowestnote = note;
                    lowestTrack = tracknum;
                }
                else if (note.StartTime == lowestnote.StartTime && note.Number < lowestnote.Number) {
                    lowestnote = note;
                    lowestTrack = tracknum;
                }
            }
            if (lowestnote == null) {
                /* We've finished the merge */
                break;
            }
            noteindex[lowestTrack]++;
            if ((prevnote != null) && (prevnote.StartTime == lowestnote.StartTime) &&
                (prevnote.Number == lowestnote.Number) ) {

                /* Don't add duplicate notes, with the same start time and number */
                if (lowestnote.Duration > prevnote.Duration) {
                    prevnote.Duration = lowestnote.Duration;
                }
            }
            else {
                result.AddNote(lowestnote);
                prevnote = lowestnote;
            }
            }

            return result;
        }
Esempio n. 26
0
        public void LoadSequence()
        {
            _midiFile.MidiTracks.Clear();
            int cMidiChn = 0;

            // process each track
            for (int currentTrack = 0; currentTrack < _smdInfo.NumTracks; currentTrack++)
            {
                long cTick          = 0;
                int  cOctave        = 0;
                byte cProgram       = 0;
                bool bendIsInit     = false;
                int  lastDelay      = 0;
                int  lastNoteLength = 1;

                MidiTrack cTrack;

                _midiFile.MidiTracks.Add(cTrack = new MidiTrack());

                if (currentTrack == 0)
                {
                    cTrack.MidiEvents.Add(
                        new MetaMessage(
                            0,
                            3, // sequence name
                            Encoding.ASCII.GetBytes(_smdInfo.SequenceName)
                            )
                        );
                }

                _smdReader.BaseStream.Position = _smdInfo.TrackOffset[currentTrack] + 0x14; // skip the first 4 bytes of the track data

                while (true)
                {
                    byte cmd = _smdReader.ReadByte();
                    if (cmd >= 0x0 && cmd <= 0x7F) // note
                    {
                        int noteArgument = _smdReader.ReadByte();
                        int octaveDelta  = ((noteArgument >> 4) & 0x3) - 2;
                        cOctave += octaveDelta;
                        byte midiKey    = (byte)(cOctave * 12 + (noteArgument & 0xF));
                        int  numArgs    = (noteArgument >> 6) & 0x3;
                        int  noteLength = 0;
                        if (numArgs == 0)
                        {
                            noteLength = lastNoteLength;
                        }
                        else
                        {
                            for (int i = 0; i < numArgs; i++)
                            {
                                noteLength = (noteLength << 8) + _smdReader.ReadByte();
                            }
                            lastNoteLength = noteLength;
                        }
                        if (midiKey >= 0 && midiKey <= 0x7F)
                        {
                            cTrack.MidiEvents.Add(
                                new MidiMessage(
                                    cTick,
                                    (byte)(cMidiChn & 0xF),
                                    (cProgram == 127) ? drummap[midiKey] : (byte)(midiKey + (sbyte)transpose[cProgram]),
                                    cmd,
                                    NormalType.NoteOn
                                    )
                                );
                            cTrack.MidiEvents.Add(
                                new MidiMessage(
                                    Math.Max(0, cTick + (noteLength * 2) - 1),
                                    (byte)(cMidiChn & 0xF),
                                    (cProgram == 127) ? drummap[midiKey] : (byte)(midiKey + (sbyte)transpose[cProgram]),
                                    0,
                                    NormalType.NoteOff
                                    )
                                );
                        }
                        else
                        {
                            Console.WriteLine("Dropped invalid note event on track " + currentTrack);
                        }
                    }
                    else if (cmd >= 0x80 && cmd <= 0x8F) // if delay
                    {
                        long delayTo = cTick + (2 * (lastDelay = _delayLut[cmd - 0x80]));
                        cTick = delayTo;
                    }
                    else if (cmd == 0x90)
                    {
                        long delayTo = cTick + (lastDelay * 2);
                        cTick = delayTo;
                    }
                    else if (cmd == 0x91)
                    {
                        lastDelay += _smdReader.ReadSByte();
                        if (lastDelay < 0)
                        {
                            lastDelay = 0;
                        }
                        long delayTo = cTick + (lastDelay * 2);
                        cTick = delayTo;
                    }
                    else if (cmd == 0x92)
                    {
                        long delayTo = cTick + (2 * (lastDelay = _smdReader.ReadByte()));
                        cTick = delayTo;
                    }
                    else if (cmd == 0x93)
                    {
                        int  a       = _smdReader.ReadByte();
                        int  b       = _smdReader.ReadByte();
                        long delayTo = cTick + (2 * (lastDelay = (a | (b << 8))));
                        cTick = delayTo;
                    }
                    else if (cmd == 0x98) // FINE | LOOP
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes("end")
                                )
                            );
                        break;
                    }
                    else if (cmd == 0x99)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes("loopStart")
                                )
                            );
                    }
                    else if (cmd == 0x9C)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0x9D)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xA0) // set octave
                    {
                        cOctave = _smdReader.ReadByte();
                    }
                    else if (cmd == 0xA4)
                    {
                        byte   bpm           = _smdReader.ReadByte();
                        int    microsPerBeat = 60 * 1000 * 1000 / bpm;
                        byte[] speed         = new byte[3];
                        speed[0] = (byte)(microsPerBeat >> 16);
                        speed[1] = (byte)((microsPerBeat >> 8) & 0xFF);
                        speed[2] = (byte)(microsPerBeat & 0xFF);
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                0x51,
                                speed
                                )
                            );
                    }
                    else if (cmd == 0xA8)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2")
                                                        + ":" + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xA9)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xAA)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xAC)
                    {
                        //hasEvents = true;
                        cProgram = _smdReader.ReadByte();
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                midimap[cProgram],
                                0, // dummy
                                NormalType.Program
                                )
                            );
                    }
                    else if (cmd == 0xB2)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xB4)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2")
                                                        + ":" + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xB5)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xBE)
                    {
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                1, // mod wheel
                                _smdReader.ReadByte(),
                                NormalType.Controller
                                )
                            );
                    }
                    else if (cmd == 0xBF)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xC0)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xD0)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xD1)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xD2)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xD4)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1, // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xD6)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2")
                                                        + ":" + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xD7)
                    {
                        //hasEvents = true;
                        byte a = _smdReader.ReadByte();
                        byte b = _smdReader.ReadByte();

                        // insert bend rage if it hasn't been yet

                        if (!bendIsInit)
                        {
                            // rp msb = 0; rp lsb = 0; de msb = 8; de lsb = 0
                            cTrack.MidiEvents.Add(new MidiMessage(0, (byte)(cMidiChn & 0xF), 101, 0, NormalType.Controller));
                            cTrack.MidiEvents.Add(new MidiMessage(0, (byte)(cMidiChn & 0xF), 100, 0, NormalType.Controller));
                            cTrack.MidiEvents.Add(new MidiMessage(0, (byte)(cMidiChn & 0xF), 6, 8, NormalType.Controller));
                            cTrack.MidiEvents.Add(new MidiMessage(0, (byte)(cMidiChn & 0xF), 38, 0, NormalType.Controller));
                            bendIsInit = true;
                        }
                        ushort pitch = (ushort)(((a << 8) | b) + 0x8000);
                        byte   msb   = (byte)(pitch >> 9);
                        byte   lsb   = (byte)((pitch >> 2) & 0x7F);
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                lsb,
                                msb,
                                NormalType.PitchBend
                                )
                            );

                        /*cTrack.MidiEvents.Add(
                         *  new MetaMessage(
                         *      cTick,
                         *      1,
                         *      Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + a.ToString("X2")
                         + ":" + b.ToString("X2")
                         +          )
                         +      )
                         +  );*/
                    }
                    else if (cmd == 0xDB)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else if (cmd == 0xDC)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1, // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xE0)
                    {
                        //hasEvents = true;
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                7, // volume controller
                                _smdReader.ReadByte(),
                                NormalType.Controller
                                )
                            );
                    }
                    else if (cmd == 0xE2)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1, // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xE3)
                    {
                        //hasEvents = true;
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                11,     // expression controller
                                _smdReader.ReadByte(),
                                NormalType.Controller
                                )
                            );
                    }
                    else if (cmd == 0xE8)
                    {
                        //hasEvents = true;
                        cTrack.MidiEvents.Add(
                            new MidiMessage(
                                cTick,
                                (byte)(cMidiChn & 0xF),
                                0xA,     // PAN controller
                                _smdReader.ReadByte(),
                                NormalType.Controller
                                )
                            );
                    }
                    else if (cmd == 0xEA)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1, // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2") + ":"
                                                        + _smdReader.ReadByte().ToString("X2")
                                                        )
                                )
                            );
                    }
                    else if (cmd == 0xF6)
                    {
                        cTrack.MidiEvents.Add(
                            new MetaMessage(
                                cTick,
                                1,     // text event
                                Encoding.ASCII.GetBytes(cmd.ToString("X2") + ":" + _smdReader.ReadByte().ToString("X2"))
                                )
                            );
                    }
                    else
                    {
                        throw new Exception("Command " + cmd.ToString("X2") + " at 0x" + _smdReader.BaseStream.Position.ToString(("X8")) + " not known");
                    }
                } // end while

                cMidiChn++;
            }
            _midiFile.SortTrackEvents();
            FixMidiChannels();
        }
Esempio n. 27
0
        /* Split the given MidiTrack into two tracks, top and bottom.
         * The highest notes will go into top, the lowest into bottom.
         * This function is used to split piano songs into left-hand (bottom)
         * and right-hand (top) tracks.
         */
        public static List<MidiTrack> SplitTrack(MidiTrack track, int measurelen)
        {
            List<MidiNote> notes = track.Notes;
            int count = notes.Count;

            MidiTrack top = new MidiTrack(1);
            MidiTrack bottom = new MidiTrack(2);
            List<MidiTrack> result = new List<MidiTrack>(2);
            result.Add(top); result.Add(bottom);

            if (count == 0)
            return result;

            int prevhigh  = 76; /* E5, top of treble staff */
            int prevlow   = 45; /* A3, bottom of bass staff */
            int startindex = 0;

            foreach (MidiNote note in notes) {
            int high, low, highExact, lowExact;

            int number = note.Number;
            high = low = highExact = lowExact = number;

            while (notes[startindex].EndTime < note.StartTime) {
                startindex++;
            }

            /* I've tried several algorithms for splitting a track in two,
             * and the one below seems to work the best:
             * - If this note is more than an octave from the high/low notes
             *   (that start exactly at this start time), choose the closest one.
             * - If this note is more than an octave from the high/low notes
             *   (in this note's time duration), choose the closest one.
             * - If the high and low notes (that start exactly at this starttime)
             *   are more than an octave apart, choose the closest note.
             * - If the high and low notes (that overlap this starttime)
             *   are more than an octave apart, choose the closest note.
             * - Else, look at the previous high/low notes that were more than an
             *   octave apart.  Choose the closeset note.
             */
            FindHighLowNotes(notes, measurelen, startindex, note.StartTime, note.EndTime,
                             ref high, ref low);
            FindExactHighLowNotes(notes, startindex, note.StartTime,
                                  ref highExact, ref lowExact);

            if (highExact - number > 12 || number - lowExact > 12) {
                if (highExact - number <= number - lowExact) {
                    top.AddNote(note);
                }
                else {
                    bottom.AddNote(note);
                }
            }
            else if (high - number > 12 || number - low > 12) {
                if (high - number <= number - low) {
                    top.AddNote(note);
                }
                else {
                    bottom.AddNote(note);
                }
            }
            else if (highExact - lowExact > 12) {
                if (highExact - number <= number - lowExact) {
                    top.AddNote(note);
                }
                else {
                    bottom.AddNote(note);
                }
            }
            else if (high - low > 12) {
                if (high - number <= number - low) {
                    top.AddNote(note);
                }
                else {
                    bottom.AddNote(note);
                }
            }
            else {
                if (prevhigh - number <= number - prevlow) {
                    top.AddNote(note);
                }
                else {
                    bottom.AddNote(note);
                }
            }

            /* The prevhigh/prevlow are set to the last high/low
             * that are more than an octave apart.
             */
            if (high - low > 12) {
                prevhigh = high;
                prevlow = low;
            }
            }

            top.Notes.Sort(track.Notes[0]);
            bottom.Notes.Sort(track.Notes[0]);

            return result;
        }
Esempio n. 28
0
        void Output(OutputType type)
        {
            switch (type)
            {
            case OutputType.Midi:

                /*List<MidiEvent> midiEvents = new List<MidiEvent> ();
                 *
                 * double max = 0;
                 * for (int i = 0; i < notes.Count; i++) {
                 *      double d = notes[i].duration * 4;
                 *      double t1 = notes[i].time * 4;
                 *      double t2 = t1 + d;
                 *      max = t2 > max ? t2 : max;
                 *
                 *      NoteOnEvent note = new NoteOnEvent (Convert.ToInt64 (t1), 1, notes[i].noteNumber + 40, 127, Convert.ToInt32(d));
                 *      midiEvents.Add (note);
                 * }
                 * MidiEvent endMarker = new NoteEvent (Convert.ToInt64(max), 1, MidiCommandCode.StopSequence, 0, 0);
                 * midiEvents.Add (endMarker);
                 *
                 * MidiEventCollection collection = new MidiEventCollection (0, 1);
                 * collection.AddTrack (midiEvents);
                 *
                 * MidiFile.Export ("C:/Users/Jonas/OneDrive/GIP/Proef/Output/midi.mid", collection);*/

                MidiTrack track   = new MidiTrack();
                long      maxTime = 0;
                //string path = "C:/Users/Jonas/Desktop/result.txt";
                double previousTime = 0;
                for (int i = 0; i < notes.Count; i++)
                {
                    string path = "C:/Users/Jonas/Desktop/result.txt";
                    File.AppendAllText(path, string.Format("{0} at {1}\n", DecodeNote(notes[i].noteNumber + 44, NoteNotation.Short), notes[i].time));

                    double d  = 1;
                    double t1 = notes[i].time * 20 - previousTime;
                    double t2 = t1 + d;
                    if (t1 < 0)
                    {
                        continue;
                    }
                    previousTime = t2;



                    MidiEvent onEvent  = new OnNoteVoiceMidiEvent(Convert.ToInt64(t1), 1, (byte)(44 + notes[i].noteNumber), 63);
                    MidiEvent offEvent = new OffNoteVoiceMidiEvent(Convert.ToInt64(t2), 1, (byte)(44 + notes[i].noteNumber), 0);
                    long      t2long   = (long)t2;
                    maxTime = (t2long > maxTime) ? t2long : maxTime;

                    track.Events.Add(onEvent);
                    track.Events.Add(offEvent);
                }
                MidiEvent endMarker = new EndOfTrackMetaMidiEvent(maxTime);
                track.Events.Add(endMarker);
                MidiSequence sequence = new MidiSequence(Format.Zero, 1000);
                sequence.Tracks.Add(track);



                FileStream stream = new FileStream("C:/Users/Jonas/OneDrive/GIP/Proef/Output/midi.mid", FileMode.OpenOrCreate);
                sequence.Save(stream);
                stream.Close();
                break;

            case OutputType.Audio:
                double longest = 0;
                for (int i = 0; i < notes.Count; i++)
                {
                    double time = notes[i].time + notes[i].duration;
                    longest = Math.Max(time, longest);
                }
                double[] newSamples = new double[(int)Math.Ceiling(longest * rawAudio.sampleRate)];

                for (int i = 0; i < notes.Count; i++)
                {
                    int    startIndex = (int)Math.Floor(notes[i].time * rawAudio.sampleRate);
                    int    endIndex   = (int)Math.Floor((notes[i].time + notes[i].duration) * rawAudio.sampleRate);
                    double freq       = 110 * Math.Pow(1.059463094359295, notes[i].noteNumber);
                    double amp        = notes[i].amplitude;
                    for (int j = startIndex; j < endIndex; j++)
                    {
                        double time  = j * rawAudio.SampleLength + notes[i].time;
                        double value = Math.Sin(time * freq * 2 * Math.PI) * amp;
                        //double maxAmp = Math.Min (1, 5 * Math.Min (Math.Abs (time - notes[i].time), Math.Abs (time - (notes[i].time + notes[i].duration))));
                        newSamples[j] += value;
                    }
                }
                for (int i = 0; i < newSamples.Length; i++)
                {
                    newSamples[i] = Math.Max(Math.Min(1, newSamples[i]), -1);
                }
                int      avgSpread     = 35;
                double[] smoothSamples = new double[newSamples.Length - avgSpread];
                for (int i = 0; i < newSamples.Length - avgSpread; i++)
                {
                    double tot = 0;
                    for (int j = 0; j < avgSpread; j++)
                    {
                        tot += newSamples[i + j];
                    }
                    smoothSamples[i] = tot / avgSpread;
                }
                Song song = new Song(smoothSamples, rawAudio.channels, rawAudio.sampleRate);

                // GIPIO.SaveSong (song, GIPIO.outputPath + "test.wav");
                producedAudio = song;
                break;

            case OutputType.Wavelet:
                pixels = new uint[allAmps.Count * allAmps[0].Length];
                for (int x = 0; x < allAmps.Count; x++)
                {
                    for (int y = 0; y < allAmps[0].Length; y++)
                    {
                        double i = allAmps[x][y];
                        // i *= 2;
                        i = Math.Min(1, i);
                        // double r = -2 * (i - 1.0) * (2 * (i - 1.0)) + 1;
                        // double g = -2 * (i - 0.5) * (2 * (i - 0.5)) + 1;
                        // double b = -2 * (i - 0.0) * (2 * (i - 0.0)) + 1;

                        double r, g, b;
                        r = g = b = i;

                        uint red   = (uint)Math.Round(r * 255);
                        uint green = (uint)Math.Round(g * 255);
                        uint blue  = (uint)Math.Round(b * 255);

                        int index = (allAmps[0].Length - y - 1) * allAmps.Count + x;
                        pixels[index] = (uint)((255 << 24) + (red << 16) + (green << 8) + blue);
                    }
                }
                DrawWavelet();

                break;
            }
        }
Esempio n. 29
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);
        }
Esempio n. 30
0
        static public void addAgbCompatibleEvents(MidiFile midiFile, byte modType)
        {
            int[] channelNumber = new int[midiFile.midiTracks.Count];
            for (int i = 0; i < midiFile.midiTracks.Count; i++)
            {
                channelNumber[i] = getChannelNumberFromTrack(midiFile.midiTracks[i]);
            }

            // add all MODT events

            Debug.WriteLine("Adding MODT and LFOS Events...");

            for (int i = 0; i < midiFile.midiTracks.Count; i++)
            {
                if (channelNumber[i] == -1)
                {
                    continue;                            // skip track if there is no regular MIDI commands
                }
                // add a MODT controller event in the beginning of the track and LFOS
                midiFile.midiTracks[i].midiEvents.Insert(
                    0, new MessageMidiEvent(0, (byte)channelNumber[i], NormalType.Controller, 21, 44));
                midiFile.midiTracks[i].midiEvents.Insert(
                    0, new MessageMidiEvent(0, (byte)channelNumber[i], NormalType.Controller, 22, modType));
            }

            Debug.WriteLine("Adding BENDR Events...");

            for (int currentTrack = 0; currentTrack < midiFile.midiTracks.Count; currentTrack++)
            {
                MidiTrack trk   = midiFile.midiTracks[currentTrack];
                byte      rpMSB = 0;
                byte      rpLSB = 0;
                for (int currentEvent = 0; currentEvent < trk.midiEvents.Count; currentEvent++)
                {
                    MessageMidiEvent ev;
                    if (trk.midiEvents[currentEvent] is MessageMidiEvent)
                    {
                        ev = trk.midiEvents[currentEvent] as MessageMidiEvent;
                    }
                    else
                    {
                        continue;
                    }

                    if (ev.type != NormalType.Controller)
                    {
                        continue;
                    }

                    switch (ev.parameter1)
                    {
                    case 0x64:     // midi RP
                        rpLSB = ev.parameter2;
                        break;

                    case 0x65:     // midi RP
                        rpLSB = ev.parameter2;
                        break;

                    case 0x6:      // midi data entry
                        if (rpLSB == 0 && rpMSB == 0)
                        {
                            // insert new event if right parameter slots are selected
                            long cTicks = ev.absoluteTicks;
                            trk.midiEvents.Insert(currentEvent, new MessageMidiEvent(
                                                      cTicks, (byte)channelNumber[currentTrack], NormalType.Controller, 20, ev.parameter2));
                            // extend the current event because we added one event and don't want to check this one again
                            currentEvent++;
                        }
                        break;

                    default:
                        break;
                    }
                }
            }
        }
Esempio n. 31
0
        private MidiTrack GetPixelTrack(Bitmap bitmap, string name, bool grayscale = true, bool invert = true)
        {
            MidiTrack result = null;

            if (bitmap is Bitmap)
            {
                result = new MidiTrack();

                int delta = (int)(noteLen * NoteType);

                var gray = bitmap.Height > 128 ? Resize(bitmap, 0, 128): bitmap;
                gray = grayscale ? GrayScale(gray) : gray;
                if (InvertSource && invert)
                {
                    gray = Invert(gray);
                }

                Color c;
                Color co    = gray.GetPixel(0, 0);
                int   count = 0;

                int[,] om = new int[gray.Width, gray.Height];
                Dictionary <int[, ], byte> nm = new Dictionary <int[, ], byte>();

                count = 0;

                bool[] blank = new bool[gray.Width];
                for (int i = 0; i < blank.Length; i++)
                {
                    blank[i] = true;
                }
                int marginL = 0;
                int marginR = 0;
                for (int x = 0; x < gray.Width; x++)
                {
                    //for (int y = 0; y < gray.Height; y++)
                    for (int y = gray.Height - 1; y >= 0; y--)
                    {
                        c = gray.GetPixel(x, y);
                        byte velocity = 0x40;
                        var  alpha    = CalcAlpha(c, co, out velocity);
                        if (alpha > 0)
                        {
                            om[x, y] = count * delta;
                            blank[x] = false;
                            if (marginL == 0)
                            {
                                marginL = x;
                            }
                            count = 0;
                            break;
                        }
                    }
                    if (blank[x])
                    {
                        count++;
                    }
                }
                marginR = count;

                //int offset = (int)(gray.Height / 2.0 - NoteCenter);
                int offset = (int)(NoteCenter - gray.Height / 2.0);
                if (offset < 0)
                {
                    offset = 0;
                }

                var track = new MidiTrack();
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x03, 0, Encoding.Default.GetBytes(name))));
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.NoteOff, (byte)NoteCenter, 0, Encoding.Default.GetBytes(""))));

                double[] alphav = new double[128];
                for (int x = 0; x < gray.Width; x++)
                {
                    if (blank[x])
                    {
                        continue;
                    }

                    bool IsDelta = false;
                    for (int y = gray.Height - 1; y >= 0; y--)
                    {
                        c = gray.GetPixel(x, y);
                        byte velocity = 0x40;
                        alphav[y] = CalcAlpha(c, co, out velocity);
                        if (alphav[y] > 0)
                        {
                            var noteOn = new MidiEvent(MidiEvent.NoteOn, (byte)(gray.Height - y - 1 + offset), velocity, Encoding.Default.GetBytes(""));
                            if (IsDelta)
                            {
                                track.AddMessage(new MidiMessage(0, noteOn));
                            }
                            else
                            {
                                track.AddMessage(new MidiMessage(om[x, y], noteOn));
                                IsDelta = true;
                            }
                        }
                    }
                    IsDelta = false;
                    for (int y = 0; y < gray.Height; y++)
                    {
                        if (alphav[y] > 0)
                        {
                            var noteOff = new MidiEvent(MidiEvent.NoteOn, (byte)(gray.Height - y - 1 + offset), 0x00, Encoding.Default.GetBytes(""));
                            if (IsDelta)
                            {
                                track.AddMessage(new MidiMessage(0, noteOff));
                            }
                            else
                            {
                                track.AddMessage(new MidiMessage(delta, noteOff));
                                IsDelta = true;
                            }
                        }
                    }
                }

                track.AddMessage(new MidiMessage(marginR * delta, new MidiEvent(MidiEvent.NoteOff, (byte)NoteCenter, 0, Encoding.Default.GetBytes(""))));
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));

                result = track;
            }

            return(result);
        }
 public override void Integrate(MidiTrack track)
 {
     //Do Nothing
 }
Esempio n. 33
0
        /// <summary>
        ///
        /// -----------------------
        /// Type    Event
        /// -----------------------
        /// 0x00    Sequence number
        /// 0x01    Text event
        /// 0x02    Copyright notice
        /// 0x03    Sequence or track name
        /// 0x04    Instrument name
        /// 0x05    Lyric text
        /// 0x06    Marker text
        /// 0x07    Cue point
        /// 0x20    MIDI channel prefix assignment
        /// 0x2F    End of track
        /// 0x51    Tempo setting
        /// 0x54    SMPTE offset
        /// 0x58    Time signature
        /// 0x59    Key signature
        /// 0x7F    Sequencer specific event
        /// -----------------------
        ///
        ///
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="singleTrack"></param>
        /// <returns></returns>
        public MidiMusic GetPixelMidi(Bitmap bitmap, bool singleTrack = true)
        {
            MidiMusic result = null;

            if (bitmap is Bitmap)
            {
                int delta = (int)(noteLen * NoteType);

                result = new MidiMusic();
                result.DeltaTimeSpec = noteLen;
                result.Format        = 1;

                var track_sys = GetMetaTrack(FileName);
                result.AddTrack(track_sys);

                if (singleTrack)
                {
                    var track = GetPixelTrack(bitmap, FileName);
                    result.AddTrack(track);
                }
                else
                {
                    var gray = GrayScale(bitmap.Height > 128 ? Resize(bitmap, 0, 128): bitmap);
                    if (InvertSource)
                    {
                        gray = Invert(gray);
                    }

                    Color c;
                    Color co    = gray.GetPixel(0, 0);
                    int   count = 0;

                    for (int y = 0; y < gray.Height; y++)
                    {
                        count = 0;
                        var track = new MidiTrack();
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x00, 0, Encoding.Default.GetBytes($"{y}"))));
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x03, 0, Encoding.Default.GetBytes($"{FileName}_{y}"))));
                        for (int x = 0; x < gray.Width; x++)
                        {
                            c = gray.GetPixel(x, y);
                            byte velocity = 0x40;
                            var  alpha    = CalcAlpha(c, co, out velocity);
                            if (alpha > 0)
                            {
                                var noteOn  = new MidiEvent(MidiEvent.NoteOn, 0x40, velocity, Encoding.Default.GetBytes(""));
                                var noteOff = new MidiEvent(MidiEvent.NoteOn, 0x40, 0x00, Encoding.Default.GetBytes(""));
                                track.AddMessage(new MidiMessage(count * delta, noteOn));
                                track.AddMessage(new MidiMessage(delta, noteOff));
                                count = 0;
                            }
                            else
                            {
                                count++;
                            }
                        }
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));
                        result.AddTrack(track);
                    }
                }
            }
            Music = result;

            return(result);
        }
Esempio n. 34
0
 /// <summary>Initialize the ProgramChange MIDI event message.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The delta-time since the previous message.</param>
 /// <param name="channel">The channel to which to write the message (0 through 15).</param>
 /// <param name="number">The number of the program to which to change.</param>
 public ProgramChangeVoiceMidiEvent(MidiTrack owner, long deltaTime, byte channel, byte number) :
     base(owner, deltaTime, CategoryId, channel)
 {
     Validate.SetIfInRange("number", ref m_number, number, 0, 127);
 }
Esempio n. 35
0
 /// <summary>Intializes the tempo meta event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="value">The tempo for the event.</param>
 public TempoMetaMidiEvent(MidiTrack owner, long deltaTime, int value)
     : base(owner, deltaTime, MetaId)
 {
     Value = value;
 }
Esempio n. 36
0
 /// <summary>Intializes the voice MIDI event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="category">The category identifier (0x0 through 0xF) for this voice event.</param>
 /// <param name="channel">The channel (0x0 through 0xF) for this voice event.</param>
 internal VoiceMidiEvent(MidiTrack owner, long deltaTime, byte category, byte channel)
     : base(owner, deltaTime)
 {
     Validate.SetIfInRange("category", ref m_category, category, 0x0, 0xF);
     Channel = channel;
 }
Esempio n. 37
0
 /// <summary>Initialize the event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 internal MidiEvent(MidiTrack owner, long deltaTime)
 {
     // Store the data
     Owner     = owner;
     DeltaTime = deltaTime;
 }
Esempio n. 38
0
 /// <summary>Intializes the channel prefix event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="prefix">The prefix for the event.</param>
 public ChannelPrefixMetaMidiEvent(MidiTrack owner, long deltaTime, byte prefix)
     : base(owner, deltaTime, MetaId)
 {
     Prefix = prefix;
 }
Esempio n. 39
0
 public CutSpecification(MidiTrack track, int fromTick, int toTick)
 {
     this.midiTrack = track;
     this.fromTick  = fromTick;
     this.toTick    = toTick;
 }
 public override void ExecuteEvent(MidiTrack track) => track.ExecuteRunningEvent(this);
Esempio n. 41
0
 /// <summary>Initialize the sequence/track name meta event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="text">The text associated with the event.</param>
 public SequenceTrackNameTextMetaMidiEvent(MidiTrack owner, long deltaTime, string text) : base(owner, deltaTime, MetaId, text)
 {
 }
Esempio n. 42
0
        public void ParseSequence(MidiSequence s, double sample_rate = 44100.0)
        {
            //First MIDI track should always contain the relevant tempo data.  We need to process this data to build a tempo map between ticks,
            //Translate each tick to a frame position, and push an event to a stack located at the given frame of our lookup dictionary.
            if (s.Tracks.Count == 0)
            {
                return;
            }

            eventsAtPosition.Clear();
            ActionSet.Clear();

            //Initial tempo is == 120bpm
            int beatLen = 480000;                                                 //beat length, in microseconds.  Set by tempo events.
            int divider = s.TicksPerBeatOrFrame > 0?  s.TicksPerBeatOrFrame : 48; //Beat divider.  Use this with beatLen to calculate a tick length.

            //Tick length in sample frames. Calculated based on sample_rate * beatLen/ticksPerBeat/1000000.
            //Useful to determine how many frames we can get away with skipping without worrying about an event miss.
            double tickLen = 441;

            TempoMap tempoMap    = new TempoMap(); //List of frame positions for every tick. Use to stuff events into position by looking for closest index
            int      frameOffset = 0;              //Update this every new tempo event found to account for shifts in deltas. The max value is ~12h at 48000hz.


            //Build the tempo map.
            foreach (MidiSharp.Events.MidiEvent m_event in s.Tracks[0])
            {
                if (!(m_event is TempoMetaMidiEvent))
                {
                    continue;
                }
                var ev = (TempoMetaMidiEvent)m_event;

                //Calculate the frames for each tick leading up to this next tempo event. Events on tick 0 will skip this and immediately update tempo.
                //Once the tempo map is built,  each tick index will return a corresponding frame until the end of track 0.  Any tick indices beyond
                //the list size should be calculated based on the last known tempo.
                //TODO:  When going through all track events and their deltas, should we extend the list further? Or will precalculating the
                //      event map, while slower initially, make keeping the tempo map completely unnecessary?

                for (int i = 0; i < ev.DeltaTime; i++)
                {
                    //Round to the nearest frame.
                    tempoMap.Add((int)Math.Round(frameOffset + i * tickLen));
                }

                //Update the frame offset to the frame where this event should exist.
                frameOffset = frameOffset + (int)Math.Round(ev.DeltaTime * tickLen);

                //Now update the actual tempo for the next operation.
                beatLen = ev.Value;
                tickLen = (sample_rate * beatLen) / (double)divider / 1000000.0; //Tick length in frames
            }

            // Now that all events on track 0 are processed, update the tempo map with the last known tempo value so we can calculate frames
            // for the rest of the events on the other tracks should their delta offset exceed the last tempo event.
            tempoMap.tickLen     = tickLen;
            tempoMap.frameOffset = frameOffset;


            //Now, iterate through all tracks and events and push them to the event map.
            // foreach (MidiTrack track in s.Tracks) //Assume enumerator moves in order...
            for (int t = 1; t < s.Tracks.Count; t++) //Assume enumerator moves in order...
            {
                MidiTrack track  = s.Tracks[t];
                int       offset = 0;
                for (int i = 0; i < track.Events.Count; i++)
                {
                    var ev    = track.Events[i];
                    var frame = tempoMap.CalcFrame((int)(ev.DeltaTime + offset));

                    List <MidiSharp.Events.MidiEvent> list;
                    if (eventsAtPosition.ContainsKey(frame)) //Make a new list if this key needs it.
                    {
                        list = eventsAtPosition[frame];
                    }
                    else
                    {
                        list = new List <MidiSharp.Events.MidiEvent>();
                        eventsAtPosition.Add(frame, list);
                    }

                    //Add the event to the list at this frame position.  TODO:  organize by MIDI channel?
                    list.Add(ev);

                    offset += (int)ev.DeltaTime;   //Move up the delta timer.
                }
            }
        }
Esempio n. 43
0
 /// <summary>Intializes the meta MIDI event.</summary>
 /// <param name="owner">The track that owns this event.</param>
 /// <param name="deltaTime">The amount of time before this event.</param>
 /// <param name="metaEventID">The ID of the meta event.</param>
 /// <param name="text">The text associated with the event.</param>
 internal BaseTextMetaMidiEvent(MidiTrack owner, long deltaTime, byte metaEventID, string text) :
     base(owner, deltaTime, metaEventID)
 {
     Text = text;
 }
 public TrackNotification(MidiTrack track, bool enabled)
 {
     Track   = track;
     Enabled = enabled;
 }
Esempio n. 45
0
    //http://www.midi.org/techspecs/midimessages.php
    /// <summary>
    ///  Loads the current MidiTrack from the Midi file.
    /// </summary>
    /// <returns>The loaded MidiTrack</returns>
    private MidiTrack LoadTrackChunk()
    {
        MidiTrack track = new MidiTrack(this);

        int length = ReadInt32();
        int command = 0;
        int midiChannel = 0;

        while (length > 0)
        {
            int numBytes = 0;
            uint vtime = ReadVariableLengthValue(out numBytes);
            length -= numBytes;
            byte eventType = _reader.ReadByte();
            length--;

            if (eventType >= 0xF0) //outside of normal event type range
            {
                switch (eventType)
                {
                    case 0xFF: //Meta Event
                    {
                        byte type = _reader.ReadByte();
                        length--;
                        uint eventLength = ReadVariableLengthValue(out numBytes);
                        length -= numBytes;
                        byte[] bytes = _reader.ReadBytes((int)eventLength);
                        length -= (int)eventLength;

                        track.AddEvent(new MidiMetaEvent(vtime, type, bytes, this, track));
                    }
                    break;

                    case 0xF0:
                    case 0xF7: //SysEx Event
                    {
                        uint sysexLength = ReadVariableLengthValue(out numBytes);
                        length -= numBytes;

                        byte[] bytes = _reader.ReadBytes((int)sysexLength);
                        length -= (int)sysexLength;

                        Debug.Log("Sysex message of length '" + sysexLength + "'.");
                    }
                    break;

                    default:
                        Debug.Log("Unknown event type '" + eventType + "'.");
                    break;
                }
            }
            else
            {
                if ((eventType & 0xF0) >= 0x80)
                {
                    //Channel specific midi command
                    command = (eventType & 0xF0);
                    midiChannel = (eventType & 0x0F);
                }
                else
                {
                    //Control Change command
                    _reader.BaseStream.Position--;
                    length++;
                }

                byte[] args;
                if (command != 0xC0 && command != 0xD0) //Program Change and Channel Key Pressure only have 1 argument instead of the default 2
                {
                    args = _reader.ReadBytes(2);
                    length -= 2;
                }
                else
                {
                    args = _reader.ReadBytes(1);
                    length -= 1;
                }

                track.AddEvent(new MidiCommandEvent(vtime, command, midiChannel, args, this, track));
            }
        }

        return track;
    }
Esempio n. 46
0
 /// <summary>
 /// Creates a MidiNote sequence from the given MidiTrack
 /// </summary>
 /// <param name="track">Midi Track to read</param>
 public NoteSequence(MidiTrack track)
 {
     this.Track = track;
     this.Reload();
 }
Esempio n. 47
0
 /// <summary>
 /// Creates a new note at a specific start and end time
 /// </summary>
 /// <param name="parent">MidiFile this is part of</param>
 /// <param name="start">Absolute start time in ticks</param>
 /// <param name="end">Absolute end time in ticks</param>
 public MidiNote(MidiTrack parent, int start, int end)
 {
     this.Parent = parent;
     this.Start = start;
     this.End = end;
 }