示例#1
0
 public void HandleMidiEvent(MidiEvent me)
 {
     if (MidiEvent.IsNoteOn(me))
     {
         HandleNoteOn(((NoteOnEvent)me).NoteNumber);
     }
     else if (MidiEvent.IsNoteOff(me))
     {
         HandleNoteOff(((NoteEvent)me).NoteNumber);
     }
     else if (me.CommandCode == MidiCommandCode.PitchWheelChange)
     {
         HandlePitchWheelChange(((PitchWheelChangeEvent)me).Pitch);
     }
     else if (me.CommandCode == MidiCommandCode.ControlChange)
     {
         HandleControlChange(((ControlChangeEvent)me).Controller, ((ControlChangeEvent)me).ControllerValue);
     }
     else if (me.CommandCode == MidiCommandCode.MetaEvent)
     {
         Debug.Assert(me is MetaEvent);
         if (me is TempoEvent)
         {
             HandleTempoChange(((TempoEvent)me).MicrosecondsPerQuarterNote);
         }
     }
 }
示例#2
0
        /// <summary>
        /// MIDI in event handler.
        /// </summary>
        /// <param name="sender">Calling object.</param>
        /// <param name="e">Arguments passed.</param>
        private void MidiInDevice_messageHandler(object sender, MidiInMessageEventArgs e)
        {
            // Do nothing if we don't have any tones to play
            if (tonesAvailable == null || tonesAvailable.Length == 0)
            {
                return;
            }

            // Call ToggleTone on the UI thread using Invoke
            ToggleToneDelegate ttd = new ToggleToneDelegate(ToggleTone);

            Object[] args = new Object[2];

            if (MidiEvent.IsNoteOn(e.MidiEvent))
            {
                args[0] = ((NoteOnEvent)e.MidiEvent).NoteNumber;
                args[1] = Toggle.Play;
                Invoke(ttd, args);
            }
            else if (MidiEvent.IsNoteOff(e.MidiEvent))
            {
                args[0] = ((NoteEvent)e.MidiEvent).NoteNumber;
                args[1] = Toggle.Stop;
                Invoke(ttd, args);
            }
        }
示例#3
0
    private void ReadMidiFile(MidiFile midiFile, List <MidiNote> midiNotes)
    {
        if (midiFile.Tracks > 1)
        {
            Debug.LogWarning("Warning! Midi file has more than one track. Taking first track");
        }
        int totalMidiEvents = midiFile.Events[0].Count;

        for (int i = 0; i < totalMidiEvents; i++)
        {
            MidiEvent midiEvent = midiFile.Events[0][i];
            if (timeSignature is null)
            {
                try
                {
                    timeSignature = (TimeSignatureEvent)midiEvent;
                }
                catch (InvalidCastException e) when(e.Data != null)
                {
                }
            }
            if (!MidiEvent.IsNoteOff(midiEvent))
            {
                // Get the final tick of the song
                if (i == totalMidiEvents - 1)
                {
                    int eventTime = (int)midiEvent.AbsoluteTime;
                    if (eventTime > finalTick)
                    {
                        finalTick = eventTime;
                    }
                }
                // Ensure that the midievent is a note, and not metadata
                if (midiEvent.CommandCode.ToString() == "NoteOn")
                {
                    // Note length is retrieved from the next midiEvent's deltaTime
                    float noteLength = 0;

                    // Not at the end yet
                    if (i < totalMidiEvents)
                    {
                        MidiEvent nextMidievent = midiFile.Events[0][i + 1];
                        noteLength = ((float)nextMidievent.DeltaTime / ticksperQuarterNote);
                    }
                    Debug.Log(noteLength);
                    MidiNote note = GenerateMidiNote(midiEvent.AbsoluteTime, noteLength);
                    midiNotes.Add(note);
                }
            }
        }
    }
示例#4
0
 public void MidiEvent(MidiEvent midiEvent)
 {
     if (!NoteInputMode.IsMidi())
     {
         return;
     }
     if (midiEvent.IsNoteOn())
     {
         var pitch = MidiPitchMapping.Map(midiEvent.Cast <NoteEvent>());
         NoteSink.NoteOn(pitch);
     }
     else if (midiEvent.IsNoteOff())
     {
         var pitch = MidiPitchMapping.Map(midiEvent.Cast <NoteEvent>());
         NoteSink.NoteOff(pitch);
     }
 }
示例#5
0
    public string Describe(string fileName)
    {
        MidiFile mf = new MidiFile(fileName, false);

        StringBuilder sb = new StringBuilder();

        sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n",
                        mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote);


        var  timeSignature = mf.Events[0].OfType <NAudio.Midi.TimeSignatureEvent>().FirstOrDefault();
        bool found_BPM     = false;

        for (int n = 0; n < mf.Tracks; n++)
        {
            foreach (MidiEvent midiEvent in mf.Events[n])
            {
                if (!found_BPM)
                {
                    if (midiEvent.ToString().Contains("bpm"))
                    {
                        found_BPM = true;
                        String extractMPQ           = midiEvent.ToString();
                        int    index                = extractMPQ.LastIndexOf('m') + 3;
                        String intermediateString   = extractMPQ.Remove(0, index);
                        int    indexLastParanthesis = intermediateString.LastIndexOf(')');
                        String finalString          = intermediateString.Remove(indexLastParanthesis, 1);

                        int microsecPerQuartNote = Convert.ToInt32(finalString);
                        milliSecondsPerQuartNote = (float)((microsecPerQuartNote) / 1000.0);
                        //Debug.Log(milliSecondsPerQuartNote + " Milliseconds per quarter note");
                        //String finalMPQ = extractMPQ.Remove()
                        //Console.WriteLine("Just hit BPM");
                    }
                }
                if (!MidiEvent.IsNoteOff(midiEvent))
                {
                    currentMidiEvent = midiEvent;
                    sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature), midiEvent);
                }
            }
        }
        return(sb.ToString());
    }
        public bool Process(MidiEvent inEvent, EventRuleArgs args)
        {
            NoteOnEvent noteEvent = inEvent as NoteOnEvent;

            // filter note offs - they will be added by their note-on
            if (MidiEvent.IsNoteOff(inEvent))
            {
                return(false);
            }

            // if it is a note event, special processing
            if (noteEvent != null)
            {
                foreach (IEventRule rule in noteRules)
                {
                    if (rule.Apply(inEvent, args))
                    {
                        return(true);
                    }
                }
                // an unmatched note event
                // TODO: configure to have an option to retain these
                return(false);
            }

            // now see if we need to exclude this event
            foreach (IEventRule rule in excludeRules)
            {
                if (rule.Apply(inEvent, args))
                {
                    return(false);
                }
            }

            bool updatedEvent = false;

            foreach (IEventRule rule in eventRules)
            {
                updatedEvent |= rule.Apply(inEvent, args);
            }
            return(true); // updatedEvent;
        }
示例#7
0
        public string Describe(string fileName)
        {
            MidiFile mf = new MidiFile(fileName, false);

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n",
                            mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote);
            var timeSignature = mf.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault();

            for (int n = 0; n < mf.Tracks; n++)
            {
                foreach (MidiEvent midiEvent in mf.Events[n])
                {
                    if (!MidiEvent.IsNoteOff(midiEvent))
                    {
                        sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature), midiEvent);
                    }
                }
            }
            return(sb.ToString());
        }
示例#8
0
        public string Describe(string fileName)
        {
            MidiFile mf = new MidiFile(fileName, false);

            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("Format {0}, Tracks {1}, Delta Ticks Per Quarter Note {2}\r\n",
                            mf.FileFormat, mf.Tracks, mf.DeltaTicksPerQuarterNote);
            int beatsPerMeasure = FindBeatsPerMeasure(mf.Events[0]);

            for (int n = 0; n < mf.Tracks; n++)
            {
                foreach (MidiEvent midiEvent in mf.Events[n])
                {
                    if (!MidiEvent.IsNoteOff(midiEvent))
                    {
                        sb.AppendFormat("{0} {1}\r\n", ToMBT(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, beatsPerMeasure), midiEvent);
                    }
                }
            }
            return(sb.ToString());
        }
示例#9
0
        /// <summary>
        /// 通过Midi生成时间序列
        /// </summary>
        /// <param name="fileName">Midi文件路径</param>
        /// <param name="timeLine">时间序列</param>
        /// <param name="rate">播放速率(New BPM = BPM * rate)</param>
        /// <param name="synchroTick">节奏间隔(MidiTick),设置此项后将忽略播放速率</param>
        /// <returns>时间序列</returns>
        public TimeLine Serialize(string fileName, TimeLine timeLine, double rate = -1, int synchroTick = -1, ShowProgress showProgress = null)
        {
            try
            {
                if (timeLine == null)
                {
                    timeLine = new TimeLine();
                }
                var midiFile = new MidiFile(fileName, false);
                #region HeadParam
                timeLine.Param["MidiFileFormat"].Value  = midiFile.FileFormat;
                timeLine.Param["MidiTracksCount"].Value = midiFile.Tracks;
                timeLine.Param["MidiDeltaTicksPerQuarterNote"].Value = midiFile.DeltaTicksPerQuarterNote;
                #endregion
                #region Nodes
                //Public Event
                var    timeSignature = midiFile.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault();
                double bpm           = 0;
                timeLine.BeatsPerBar  = timeSignature == null ? 4 : timeSignature.Numerator;
                timeLine.TicksPerBar  = timeSignature == null ? midiFile.DeltaTicksPerQuarterNote * 4 : (timeSignature.Numerator * midiFile.DeltaTicksPerQuarterNote * 4) / (1 << timeSignature.Denominator);
                timeLine.TicksPerBeat = timeLine.TicksPerBar / timeLine.BeatsPerBar;
                #region MidiFile -> MidiNodes(Unordered)
                List <MidiNode> MidiNodes = new List <MidiNode>();
                //Foreach Events in MidiFile
                for (int i = 0; i < midiFile.Tracks; i++)
                {
                    //Track Events
                    var track      = "";
                    var instrument = "";
                    var vol        = -1;
                    var pan        = -1;
                    foreach (MidiEvent midiEvent in midiFile.Events[i])
                    {
                        //Event BPM
                        if (new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Success)
                        {
                            bpm = Int32.Parse(new Regex("(?<=SetTempo )\\d+(?=bpm \\(\\d+\\))").Match(midiEvent.ToString()).Value);
                            if (rate > 0)
                            {
                                bpm *= rate;
                            }
                            MidiNodes.Add(new MidiNode()
                            {
                                IsEvent = true, Param = new Dictionary <string, _Node_INT>()
                                {
                                    { "BeatPerMinute", new _Node_INT()
                                      {
                                          Value = (int)bpm
                                      } }, { "DeltaTickStart", new _Node_INT()
                                             {
                                                 Value = midiEvent.DeltaTime
                                             } }, { "MinecraftTickStart", new _Node_INT()
                                                    {
                                                        Value = 0
                                                    } }
                                }
                            });
                        }
                        //Event Track Name
                        if (new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            track = new Regex("(?<=SequenceTrackName ).+(?=$)").Match(midiEvent.ToString()).Value;
                        }
                        //Event Instrument Name
                        if (new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            instrument = new Regex("(?<=PatchChange Ch: \\d+ ).+(?=$)").Match(midiEvent.ToString()).Value;
                        }
                        //Event Track Volume
                        if (new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            Int32.TryParse(new Regex("(?<=MainVolume Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out vol);
                        }
                        //Event Track Pan
                        if (new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Success)
                        {
                            Int32.TryParse(new Regex("(?<=Pan Value )\\d*(?=$)").Match(midiEvent.ToString()).Value, out pan);
                        }
                        if (!MidiEvent.IsNoteOff(midiEvent))
                        {
                            //Get Param
                            var MBT           = GetMBT(midiEvent.AbsoluteTime, midiFile.DeltaTicksPerQuarterNote, timeSignature);
                            var EventAnalysis = AnalysisEvent(midiEvent, instrument);
                            //Write into MidiNodes
                            if (EventAnalysis != null)
                            {
                                var MidiNode = new MidiNode();
                                #region Param
                                //Time-related
                                MidiNode.Param["DeltaTickStart"].Value = (int)EventAnalysis.StartTick;
                                //MidiNode Starts Needs more Calculation
                                MidiNode.Param["DeltaTickDuration"].Value     = (int)EventAnalysis.Length;
                                MidiNode.Param["MinecraftTickDuration"].Value = (int)MinecraftTickDuration(EventAnalysis.Length, midiFile.DeltaTicksPerQuarterNote, timeSignature, (int)bpm);
                                MidiNode.Param["BeatPerMinute"].Value         = (int)bpm;
                                //Bar-related
                                MidiNode.Param["BarIndex"].Value     = (int)MBT[0];
                                MidiNode.Param["BeatDuration"].Value = (int)MBT[1];
                                //Note-related
                                MidiNode.Param["Channel"].Value  = (int)EventAnalysis.Channel;
                                MidiNode.Param["Pitch"].Value    = (int)EventAnalysis.Pitch;
                                MidiNode.Param["Velocity"].Value = (int)EventAnalysis.Velocity;
                                MidiNode.Param["Panning"].Value  = pan;
                                //Track-related
                                MidiNode.Instrument = EventAnalysis.Instrument;
                                MidiNode.TrackName  = track;
                                //PlaySound-related
                                MidiNode.PlaySound             = new PlaySoundInfo();
                                MidiNode.PlaySound.MandaVolume = (vol < 0) ? 100 : vol;
                                MidiNode.PlaySound.SetPan(pan);
                                //Generate Track & Instrument List
                                var currentTrack = timeLine.TrackList.AsEnumerable().FirstOrDefault(t => t.Name == track);
                                if (currentTrack == null)
                                {
                                    currentTrack = new TimeLine.MidiSettingInspector {
                                        Name = track, Type = TimeLine.MidiSettingType.Track, Enable = true
                                    }; timeLine.TrackList.Add(currentTrack);
                                }                                                                                                                                                                                            //Add new Track
                                var currentInstrument = timeLine.InstrumentList.AsEnumerable().FirstOrDefault(ins => ins.Name == EventAnalysis.Instrument);
                                if (currentInstrument == null)
                                {
                                    currentInstrument = new TimeLine.MidiSettingInspector {
                                        Name = EventAnalysis.Instrument, Type = TimeLine.MidiSettingType.Instrument, Enable = true
                                    }; timeLine.InstrumentList.Add(currentInstrument);
                                }                                                                                                                                                                                                                                        //Add new Instrument
                                if (!currentTrack.Instruments.Any(ins => ins.Name == EventAnalysis.Instrument))
                                {
                                    currentTrack.Instruments.Add(currentInstrument);
                                    currentTrack.InstrumentsUid.Add(currentInstrument.Uid);
                                }//Line Track
                                if (!currentInstrument.Tracks.Any(t => t.Name == track))
                                {
                                    currentInstrument.Tracks.Add(currentTrack);
                                    currentInstrument.TracksUid.Add(currentTrack.Uid);
                                }
                                #endregion
                                MidiNodes.Add(MidiNode);
                            }
                        }
                    }
                }
                #endregion
                #region MidiNodes in Order
                /* Set Total Progress */ timeLine.totalProgress = MidiNodes.Count * 2;
                bpm = 0;
                long bpm_key_t  = 0; //When BPM Changes
                long bpm_key_mt = 0;
                MidiNodes = (from n in MidiNodes
                             orderby n.Param["DeltaTickStart"].Value
                             select n).ToList();          //Make Nodes in Order
                int synchroCount = 0;
                for (int i = 0; i < MidiNodes.Count; i++) //Calculate Tick Start
                {
                    var n = MidiNodes[i];
                    if (n.IsEvent)
                    {
                        if (bpm != 0)
                        {
                            bpm_key_mt = MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt);
                        }
                        bpm       = n.Param["BeatPerMinute"].Value;
                        bpm_key_t = n.Param["DeltaTickStart"].Value;
                    }
                    else
                    {
                        n.Param["BeatPerMinute"].Value = (int)bpm;
                    }
                    if (synchroTick <= 0)
                    {
                        n.Param["MinecraftTickStart"].Value = (int)MinecraftTickStart(n.Param["DeltaTickStart"].Value, midiFile.DeltaTicksPerQuarterNote, timeSignature, bpm, bpm_key_t, bpm_key_mt);
                    }
                    else
                    { //Using synchroTick
                        n.Param["MinecraftTickStart"].Value = n.Param["DeltaTickStart"].Value / synchroTick;
                        if (n.Param["DeltaTickStart"].Value % synchroTick == 0)
                        {
                            synchroCount++;
                        }
                    }
                    /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0)
                    {
                        showProgress((double)timeLine.currentProgress / timeLine.totalProgress);
                    }
                }
                timeLine.SynchronousRate = (double)synchroCount / MidiNodes.Count;
                #endregion
                #region MidiNodes -> TickNodes
                //Creat and Set Lenth of TickNodes
                if (timeLine.TickNodes == null)
                {
                    timeLine.TickNodes = new List <TickNode>();
                }
                var maxTick = MidiNodes.Max(n => n.Param["MinecraftTickStart"].Value);
                if (maxTick >= timeLine.TickNodes.Count)
                {
                    var nowCount = timeLine.TickNodes.Count;
                    for (int i = 0; i < maxTick - nowCount + 1; i++)
                    {
                        timeLine.TickNodes.Add(new TickNode());
                    }
                }
                //MidiNodes -> TickNodes
                foreach (MidiNode node in MidiNodes)
                {
                    var index      = node.Param["MinecraftTickStart"].Value;
                    var track      = node.TrackName;
                    var instrument = node.Instrument;
                    if (timeLine.TickNodes[index].MidiTracks.ContainsKey(track) == false)
                    {
                        timeLine.TickNodes[index].MidiTracks.Add(track, new Dictionary <string, List <MidiNode> >());
                    }
                    if (timeLine.TickNodes[index].MidiTracks[track].ContainsKey(instrument) == false)
                    {
                        timeLine.TickNodes[index].MidiTracks[track].Add(instrument, new List <MidiNode>());
                    }
                    timeLine.TickNodes[index].MidiTracks[track][instrument].Add(node);
                    timeLine.TickNodes[index].BPM         = node.Param["BeatPerMinute"].Value;
                    timeLine.TickNodes[index].CurrentTick = index;
                    /* Update Current Progress */ timeLine.currentProgress++; if (showProgress != null && timeLine.totalProgress > 0)
                    {
                        showProgress((double)timeLine.currentProgress / timeLine.totalProgress);
                    }
                }
                #endregion
                timeLine.Param["TotalTicks"].Value = timeLine.TickNodes.Count;
                return(timeLine);

                //minecraft tick  = AbsoluteTime / (bpm * ticksPerBeat) * 1200
                #endregion
            }
            catch
            {
                return(null);
            }
        }
示例#10
0
    private List <decimal> CalculateMidiRealTime()
    {
        var strictMode = false;
        var mf         = new MidiFile("Assets/Audios/Midi Files/AgainYui.mid", strictMode);

        mf.Events.MidiFileType = 0;

        List <MidiEvent> midiEvents = new List <MidiEvent>();
        List <long>      beatsList  = new List <long>();

        for (int n = 0; n < mf.Tracks; n++)
        {
            foreach (var midiEvent in mf.Events[n])
            {
                if (!MidiEvent.IsNoteOff(midiEvent))
                {
                    var  timeSignature = mf.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault();
                    long beat          = GetBeat(midiEvent.AbsoluteTime, mf.DeltaTicksPerQuarterNote, timeSignature);
                    beatsList.Add(beat);
                    midiEvents.Add(midiEvent);
                    //Debug.Log("Beat: " + beat);

                    if (midiEvent is TempoEvent)
                    {
                        //Debug.Log("Absolute Time " + (midiEvent as TempoEvent).AbsoluteTime);
                    }
                }
            }
        }


        List <decimal> eventsTimesArr = new List <decimal>();


        decimal lastRealTime     = 0m;
        decimal lastAbsoluteTime = 0m;


        decimal currentMicroSecondsPerTick = 0m;

        for (int i = 0; i < midiEvents.Count; i++)
        {
            MidiEvent  midiEvent  = midiEvents[i];
            TempoEvent tempoEvent = midiEvent as TempoEvent;

            if (midiEvent.AbsoluteTime > lastAbsoluteTime)
            {
                lastRealTime += ((decimal)midiEvent.AbsoluteTime - lastAbsoluteTime) * currentMicroSecondsPerTick;
            }

            lastAbsoluteTime = midiEvent.AbsoluteTime;

            if (tempoEvent != null)
            {
                currentMicroSecondsPerTick = (decimal)tempoEvent.MicrosecondsPerQuarterNote / (decimal)mf.DeltaTicksPerQuarterNote;

                // Remove the tempo event to make events and timings match - index-wise
                // Do not add to the eventTimes
                midiEvents.RemoveAt(i);
                beatsList.RemoveAt(i);
                i--;
                continue;
            }

            // Add the time to the collection.
            eventsTimesArr.Add(lastRealTime / 1000000m);

            Debug.Log("Time: " + lastRealTime / 1000000m);
        }
        eventsBeatsArr = beatsList.ToArray();
        //Debug.Log("Length: " + eventsBeatsArr.Length);
        return(eventsTimesArr);
    }
示例#11
0
 public static bool IsNoteOff(this MidiEvent midiEvent) =>
 MidiEvent.IsNoteOff(midiEvent);
示例#12
0
        private static List <TimeSlice> ReadMidiFile(MidiFile mf, ICollection <int> tracksToSkip, double tempoRatio, bool skipDrums)
        {
            var timeSliceList = new List <TimeSlice>();

            var tempo = (int)Math.Round(120 * tempoRatio);

            Console.WriteLine("Default Tempo: {0}", tempo);

            var trackNumber = 0;

            foreach (var midiEventList in mf.Events)
            {
                Console.WriteLine("");
                Console.WriteLine("Track #{0}", trackNumber);
                Console.WriteLine("---------");

                if (tracksToSkip.Contains(trackNumber))
                {
                    trackNumber++;
                    continue;
                }

                Console.WriteLine("Track length: {0}", midiEventList.Count);

                var drumFilteredMidiEventList = midiEventList.Where(midiEvent => !skipDrums || (midiEvent.Channel != 10));

                foreach (var midiEvent in drumFilteredMidiEventList)
                {
                    if (midiEvent is TextEvent textEvent) // : MetaEvent
                    {
                        Console.WriteLine("{0}: {1}", textEvent.MetaEventType.ToString(), textEvent.Text);
                    }
                    else if (midiEvent is TimeSignatureEvent timeSignatureEvent) // : MetaEvent
                    {
                        //WriteWarningLine("TimeSignatureEvent", timeSignatureEvent.ToString());
                    }
                    else if (midiEvent is TrackSequenceNumberEvent trackSequenceNumberEvent) // : MetaEvent
                    {
                        WriteWarningLine("TrackSequenceNumberEvent", trackSequenceNumberEvent.ToString());
                    }
                    else if (midiEvent is KeySignatureEvent keySignatureEvent) // : MetaEvent
                    {
                        //WriteWarningLine("KeySignatureEvent", keySignatureEvent.ToString());
                    }
                    else if (midiEvent is TempoEvent tempoEvent) // : MetaEvent
                    {
                        tempo = (int)Math.Round(tempoEvent.Tempo * tempoRatio);
                        Console.WriteLine("Tempo: {0}", tempo);
                    }
                    else if (midiEvent is MetaEvent metaEvent)
                    {
                        if ((metaEvent.MetaEventType != MetaEventType.SequencerSpecific) && (metaEvent.MetaEventType != MetaEventType.EndTrack) && (metaEvent.MetaEventType != MetaEventType.MidiChannel) && (metaEvent.MetaEventType != MetaEventType.MidiPort))
                        {
                            WriteWarningLine("MetaEvent", metaEvent.ToString());
                        }
                    }
                    else if (midiEvent is ControlChangeEvent controlChangeEvent)
                    {
                        //WriteWarningLine("ControlChangeEvent", controlChangeEvent.ToString());
                    }
                    else if (midiEvent is PatchChangeEvent patchChangeEvent)
                    {
                        Console.WriteLine("Patch: {0}", PatchChangeEvent.GetPatchName(patchChangeEvent.Patch));

                        if (skipDrums && (patchChangeEvent.Patch >= 112))
                        {
                            Console.WriteLine("Skipping track...");
                            break;
                        }
                    }
                    else if (midiEvent is NoteOnEvent noteEvent1)
                    {
                        if (MidiEvent.IsNoteOff(noteEvent1) == false)
                        {
                            if (noteEvent1.OffEvent != null)
                            {
                                var ticksPerMinute      = mf.DeltaTicksPerQuarterNote * tempo;
                                var millisecondsPerTick = 60.0 * 1000.0 / ticksPerMinute;

                                var start = (int)Math.Round(noteEvent1.AbsoluteTime * millisecondsPerTick);
                                var stop  = (int)Math.Round(noteEvent1.OffEvent.AbsoluteTime * millisecondsPerTick);

                                timeSliceList.Add(new TimeSlice(start, stop, new Note(noteEvent1.NoteNumber, noteEvent1.Velocity)));
                            }
                            else
                            {
                                WriteWarningLine("NoteOnEvent", "No Corresponding Note Off Event");
                            }
                        }
                    }
                    else if (midiEvent is NoteEvent noteEvent)
                    {
                        if (noteEvent.CommandCode != MidiCommandCode.NoteOff)
                        {
                            WriteWarningLine("NoteEvent", noteEvent.ToString());
                        }
                    }
                    else
                    {
                        WriteWarningLine("MIDI Event Type", midiEvent.GetType().ToString());
                    }
                }

                trackNumber++;
            }

            timeSliceList.Sort(CompareTimeSlicesByStartTime);

            return(timeSliceList);
        }