Пример #1
0
        public void NoteOn(byte idx)
        {
            _playedNotes[idx] = new PlayedNote()
            {
                Note = Notes[idx],
            };
            if (_freeChannels.Count() == 0)
            {
                return;
            }
            var newChannel = _freeChannels.Dequeue();

            _noteChannelMapping[idx]        = newChannel;
            _channelNoteMapping[newChannel] = _playedNotes[idx];
        }
Пример #2
0
        //======Generate other data from known information===
        private void AnalyzeMIDI()
        {
            long tempo = 500000; //Default tempo in case none is given

            //Create lists and arrays
            //-to put PlayedNotes in per track
            //-to store notes that have been pressed but not released
            //-To track what event we're checking, per track
            List<List<PlayedNote>> lists = new List<List<PlayedNote>>();
            List<List<PlayedNote>> unfinishednotes = new List<List<PlayedNote>>();
            for (int i = 0; i < tracks.Length; i++)
            {
                lists.Add(new List<PlayedNote>());
                unfinishednotes.Add(new List<PlayedNote>());
            }

            int[] currentevent = new int[lists.Count]; //Tracks the current event # per list
            long[] currenttime = new long[lists.Count];
            for (int i = 0; i < lists.Count; i++)
            {
                currentevent[i] = 0;
                currenttime[i] = 0;
            }

            List<TempoChange> tempoChanges = new List<TempoChange>();
            this.tempoChanges = new TempoChange[0];

            //Start reading all the lists at the same time, in MIDI timing order
            bool reading = true;

            while (reading)
            {
                //Check which next MIDI event of all tracks has the lowest delta time
                long lowesttime = long.MaxValue;
                int lowestlist = -1;
                for (int i = 0; i < lists.Count; i++)
                {
                    if (currentevent[i] < tracks[i].events.Length) //Ignore if at end of track
                    {
                        if (tracks[i].events[currentevent[i]].time + currenttime[i] < lowesttime)
                        {
                            lowestlist = i;
                            lowesttime = tracks[i].events[currentevent[i]].time + currenttime[i];
                        }
                    }
                }
                if (lowestlist == -1) { reading = false; } //All tracks at end of track
                else //You got the current event, parse it
                {
                    long newtempo = tempo;
                    Event ev = tracks[lowestlist].events[currentevent[lowestlist]];
                    if (ev.type == EventType.Midi)
                    {
                        ReanalyzeType: //Jumps here if case NoteOn realizes it's actually a NoteOff
                        switch(ev.midiEvent.midiType)
                        {
                            case MidiType.NoteOn: //Note on event
                                {
                                    if (ev.midiEvent.note.velocity == 0)
                                    {
                                        ev.midiEvent.midiType = MidiType.NoteOff;
                                        goto ReanalyzeType; //Return to start of switch to fall to NoteOff instead
                                    }
                                    PlayedNote pn = new PlayedNote();
                                    pn.note = ev.midiEvent.note;
                                    pn.time = currenttime[lowestlist] + TicksToMicroSeconds(ev.time, tempo, currenttime[lowestlist]);
                                    unfinishednotes[lowestlist].Add(pn);
                                    break;
                                }

                            case MidiType.NoteOff: //Note off event
                                {
                                    PlayedNote pn = new PlayedNote();
                                    for (int i = 0; i < unfinishednotes[lowestlist].Count; i++)
                                    {
                                        if (unfinishednotes[lowestlist][i].note.number == ev.midiEvent.note.number)
                                        {
                                            pn = unfinishednotes[lowestlist][i];
                                        }
                                    }
                                    unfinishednotes[lowestlist].Remove(pn); //TODO: Improve, causes 33% of CPU usage of entire LoadMIDI(), has to look for IndexOf() which causes slowdown
                                    pn.length = (currenttime[lowestlist] + TicksToMicroSeconds(ev.time, tempo, currenttime[lowestlist])) - pn.time;
                                    float division = pn.length / tempo;
                                    Msg("Division: " + division);
                                    if (division > 7.9 && division < 8.1) pn.lengthtype = LengthType.DoubleWhole;
                                    else if (division > 3.9 && division < 4.1) pn.lengthtype = LengthType.Whole;
                                    else if (division > 1.9 && division < 2.1) pn.lengthtype = LengthType.Half;
                                    else if (division > 0.9 && division < 1.1) pn.lengthtype = LengthType.Quarter;
                                    else if (division > 0.45 && division < 0.55) pn.lengthtype = LengthType.Eighth;
                                    else if (division > 0.20 && division < 0.30) pn.lengthtype = LengthType.Sixteenth;
                                    else if (division > 0.1125 && division < 0.1375) pn.lengthtype = LengthType.ThirtySecond;
                                    else if (division > 0.0620 && division < 0.0630) pn.lengthtype = LengthType.SixtyFourth;
                                    //Why hello there Beethoven!
                                    else if (division > 0.03120 && division < 0.03130) pn.lengthtype = LengthType.HundredTwentyEight;
                                    else pn.lengthtype = LengthType.Unknown;

                                    lists[lowestlist].Add(pn);
                                    break;
                                }
                        }
                    }
                    else if (ev.type == EventType.Meta)
                    {
                        switch (ev.metaType)
                        {
                            case MetaType.Tempo:
                                TempoChange tc = new TempoChange();
                                tc.time = currenttime[lowestlist] + TicksToMicroSeconds(ev.time, tempo, currenttime[lowestlist]);
                                tc.oldTempo = tempo;
                                newtempo = ConvertThreeByteInt(ev.data);
                                if (currenttime[lowestlist] == 0) this.tempo = newtempo;
                                tc.newTempo = newtempo;

                                tempoChanges.Add(tc);
                                this.tempoChanges = tempoChanges.ToArray();
                                break;
                        }
                    }

                    currenttime[lowestlist] += TicksToMicroSeconds(ev.time, tempo, currenttime[lowestlist]);
                    tempo = newtempo;
                    currentevent[lowestlist]++;
                }
            }

            for (int i = 0; i < tracks.Length; i++)
            {
                tracks[i].notes = lists[i].ToArray();
            }
            this.tempoChanges = tempoChanges.ToArray();
        }