Beispiel #1
0
        public int CalculateNextPosEvents(double timeFromStartMS)
        {
            if (MidiSorted != null)
            {
                CurrentTick = MPTK_ConvertTimeToTick(timeFromStartMS);
                //Debug.Log(">>> CalculateNextPosEvents - CurrentPulse:" + CurrentTick + " CurrentNextPosEvent:" + NextPosEvent + " LastTimeFromStartMS:" + LastTimeFromStartMS + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                if (CurrentTick == 0)
                {
                    NextPosEvent        = 0;
                    LastTimeFromStartMS = 0;
                }
                else
                {
                    LastTimeFromStartMS = timeFromStartMS;
                    for (int currentPosEvent = 0; currentPosEvent < MidiSorted.Count; currentPosEvent++)
                    {
                        TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                        //Debug.Log("CurrentPulse:" + CurrentPulse + " trackEvent:" + trackEvent.AbsoluteQuantize);

                        if (trackEvent.Event.AbsoluteTime > CurrentTick)// && CurrentPulse < nexttrackEvent.Event.AbsoluteTime )
                        {
                            NextPosEvent = currentPosEvent;
                            //Debug.Log("     CalculateNextPosEvents - NextPosEvent:" + NextPosEvent + " trackEvent:" + trackEvent.Event.AbsoluteTime + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                            //Debug.Log("NextPosEvent:" + NextPosEvent);
                            break;
                        }
                        //if (currentPosEvent == MidiSorted.Count - 1) Debug.Log("Last CalculateNextPosEvents - currentPosEvent:" + currentPosEvent + " trackEvent:" + trackEvent.Event.AbsoluteTime + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                    }
                }
                //Debug.Log("<<< CalculateNextPosEvents NextPosEvent:" + NextPosEvent);
            }
            return(NextPosEvent);
        }
Beispiel #2
0
        private MPTKEvent CreateNoteOffForNote(List <MPTKEvent> mptkEvents, TrackMidiEvent trackEvent)
        {
            MPTKEvent midievent;
            NoteEvent noteoff = (NoteEvent)trackEvent.Event;

            //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
            midievent = new MPTKEvent()
            {
                Tick     = trackEvent.AbsoluteQuantize,
                Command  = MPTKCommand.NoteOff,
                Value    = noteoff.NoteNumber,
                Channel  = trackEvent.Event.Channel - 1,
                Velocity = noteoff.Velocity,
                Duration = 0,
                Length   = 0,
            };
            //mptkEvents.Add(midievent);
            // if (LogEvents)
            // {
            //      string notename = (midievent.Channel != 9) ?
            //          String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
            //      Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3:000}\t{1,-4}\tLenght:{2}", midievent.Value, notename, " Note Off"));
            //  }

            if (midievent.Channel == selectedChannel)
            {
                Kbd_PKeyGen.instance.ShowMidiNoteOff(noteoff.NoteNumber);
            }

            return(midievent);
        }
Beispiel #3
0
        private string BuildInfoTrack(TrackMidiEvent e)
        {
#if !DEBUG_LOGEVENT
            return(string.Format("[A:{0,5:00000} Q:{1,5:00000} P:{2,5:00000}] [T:{3,2:00} C:{4,2:00}] ",
                                 e.Event.AbsoluteTime, e.AbsoluteQuantize, cur_ticks, e.IndexTrack, e.Event.Channel));
#else
            return(string.Format("[A:{0,5:00000} D:{1,4:0000} Q:{2,5:00000} CurrentTick:{3,5:00000}] [Track:{4,2:00} Channel:{5,2:00}] ",
                                 e.Event.AbsoluteTime, e.Event.DeltaTime, e.AbsoluteQuantize, cur_ticks, e.IndexTrack, e.Event.Channel));
#endif
        }
Beispiel #4
0
        private void AnalyzeTimeSignature(MetaEvent meta, TrackMidiEvent trackEvent = null)
        {
            TimeSignatureEvent timesig = (TimeSignatureEvent)meta;

            // Numerator: counts the number of beats in a measure.
            // For example a numerator of 4 means that each bar contains four beats.
            MPTK_TimeSigNumerator = timesig.Numerator;
            // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc.
            MPTK_TimeSigDenominator       = timesig.Denominator;
            MPTK_NumberBeatsMeasure       = timesig.Numerator;
            MPTK_NumberQuarterBeat        = System.Convert.ToInt32(Mathf.Pow(2f, timesig.Denominator));
            MPTK_TicksInMetronomeClick    = timesig.TicksInMetronomeClick;
            MPTK_No32ndNotesInQuarterNote = timesig.No32ndNotesInQuarterNote;
            if (LogEvents && trackEvent != null)
            {
                Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta     {0,-15} Numerator:{1} Denominator:{2}", meta.MetaEventType, timesig.Numerator, timesig.Denominator));
            }
        }
Beispiel #5
0
        public void CalculateNextPosEvents(double timeFromStartMS)
        {
            if (MidiSorted != null)
            {
                CurrentPulse = Convert.ToInt64(timeFromStartMS / PulseLengthMs);
                //Debug.Log(">>> CalculateNextPosEvents - CurrentPulse:" + CurrentPulse + " CurrentNextPosEvent:" + NextPosEvent + " LastTimeFromStartMS:" + LastTimeFromStartMS + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                if (CurrentPulse == 0)
                {
                    NextPosEvent        = 0;
                    LastTimeFromStartMS = 0;
                }
                else
                {
                    LastTimeFromStartMS = timeFromStartMS;
                    // From the last position played
                    for (int currentPosEvent = 0; currentPosEvent < MidiSorted.Count; currentPosEvent++)
                    {
                        TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                        //if (currentPosEvent + 1 < MidiSorted.Count)
                        {
                            //TrackMidiEvent nexttrackEvent = MidiSorted[currentPosEvent + 1];
                            //Debug.Log("CurrentPulse:" + CurrentPulse+ " trackEvent:" + trackEvent.AbsoluteQuantize+ " nexttrackEvent:" + nexttrackEvent.AbsoluteQuantize);

                            if (trackEvent.Event.AbsoluteTime > CurrentPulse)// && CurrentPulse < nexttrackEvent.Event.AbsoluteTime )
                            {
                                NextPosEvent = currentPosEvent;
                                //Debug.Log("     CalculateNextPosEvents - NextPosEvent:" + NextPosEvent + " trackEvent:" + trackEvent.Event.AbsoluteTime + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                                //Debug.Log("NextPosEvent:" + NextPosEvent);
                                break;
                            }
                            //if (currentPosEvent == MidiSorted.Count - 1) Debug.Log("Last CalculateNextPosEvents - currentPosEvent:" + currentPosEvent + " trackEvent:" + trackEvent.Event.AbsoluteTime + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS));
                        }
                    }
                }
                //Debug.Log("<<< CalculateNextPosEvents NextPosEvent:" + NextPosEvent);
            }
        }
Beispiel #6
0
 private string BuildInfoTrack(TrackMidiEvent e)
 {
     return(string.Format("[A:{0,5:00000} Q:{1,5:00000} P:{2,5:00000}] [T:{3,2:00} C:{4,2:00}] ", e.Event.AbsoluteTime, e.AbsoluteQuantize, CurrentPulse, e.IndexTrack, e.Event.Channel));
 }
Beispiel #7
0
        public List <MidiNote> ReadMidiEvents(double timeFromStartMS)
        {
            List <MidiNote> notes = null;

            try
            {
                EndMidiEvent = false;
                if (midifile != null)
                {
                    if (NextPosEvent < MidiSorted.Count)
                    {
                        // The BPM measures how many quarter notes happen in a minute. To work out the length of each pulse we can use the following formula:
                        // Pulse Length = 60 / (BPM * PPQN)
                        // Calculate current pulse to play
                        CurrentPulse += Convert.ToInt64((timeFromStartMS - LastTimeFromStartMS) / PulseLengthMs);

                        LastTimeFromStartMS = timeFromStartMS;

                        // From the last position played
                        for (int currentPosEvent = NextPosEvent; currentPosEvent < MidiSorted.Count; currentPosEvent++)
                        {
                            TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                            if (Quantization != 0)
                            {
                                trackEvent.AbsoluteQuantize = ((trackEvent.Event.AbsoluteTime + Quantization / 2) / Quantization) * Quantization;
                            }
                            else
                            {
                                trackEvent.AbsoluteQuantize = trackEvent.Event.AbsoluteTime;
                            }

                            //Debug.Log("ReadMidiEvents - timeFromStartMS:" + Convert.ToInt32(timeFromStartMS) + " LastTimeFromStartMS:" + Convert.ToInt32(LastTimeFromStartMS) + " CurrentPulse:" + CurrentPulse + " AbsoluteQuantize:" + trackEvent.AbsoluteQuantize);

                            if (trackEvent.AbsoluteQuantize <= CurrentPulse)
                            {
                                NextPosEvent = currentPosEvent + 1;

                                if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOn)
                                {
                                    if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                                    {
                                        NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                                        // if (noteon.OffEvent != null)
                                        {
                                            if (notes == null)
                                            {
                                                notes = new List <MidiNote>();
                                            }

                                            //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                                            MidiNote note = new MidiNote()
                                            {
                                                AbsoluteQuantize = trackEvent.AbsoluteQuantize,
                                                Midi             = noteon.NoteNumber,
                                                Channel          = trackEvent.Event.Channel,
                                                Velocity         = noteon.Velocity,
                                                Duration         = noteon.NoteLength * PulseLengthMs,
                                                Length           = noteon.NoteLength,
                                                Patch            = PatchChanel[trackEvent.Event.Channel - 1],
                                                Drum             = (trackEvent.Event.Channel == 10),
                                                Delay            = 0,
                                                Pan = EnablePanChange ? PanChanel[trackEvent.Event.Channel - 1] : -1,
                                            };
                                            if (VolumeChanel[note.Channel - 1] != 127)
                                            {
                                                note.Velocity = Mathf.RoundToInt(((float)note.Velocity) * ((float)VolumeChanel[trackEvent.Event.Channel - 1]) / 127f);
                                            }
                                            notes.Add(note);
                                            if (LogEvents)
                                            {
                                                Debug.Log(BuildInfoTrack(trackEvent) + string.Format("{0,-4} {1,3:000} Lenght:{2} {3} Veloc:{4}",
                                                                                                     noteon.NoteName, noteon.NoteNumber, noteon.NoteLength, NoteLength(note), noteon.Velocity));
                                            }
                                        }
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOff)
                                {
                                    // no need, noteoff are associated with noteon
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.ControlChange)
                                {
                                    ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                                    if (controlchange.Controller == MidiController.Expression)
                                    {
                                        VolumeChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    else if (controlchange.Controller == MidiController.MainVolume)
                                    {
                                        VolumeChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    else if (controlchange.Controller == MidiController.Pan)
                                    {
                                        PanChanel[trackEvent.Event.Channel - 1] = controlchange.ControllerValue;
                                    }
                                    // Other midi event
                                    if (LogEvents)
                                    {
                                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.PatchChange)
                                {
                                    PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                                    PatchChanel[trackEvent.Event.Channel - 1] = trackEvent.Event.Channel == 10 ? 0 : change.Patch;
                                    if (LogEvents)
                                    {
                                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                                    }
                                }
                                else if (trackEvent.Event.CommandCode == MidiCommandCode.MetaEvent)
                                {
                                    MetaEvent meta = (MetaEvent)trackEvent.Event;
                                    switch (meta.MetaEventType)
                                    {
                                    case MetaEventType.SetTempo:
                                        if (EnableChangeTempo)
                                        {
                                            TempoEvent tempo = (TempoEvent)meta;
                                            //NewQuarterPerMinuteValue = tempo.Tempo;
                                            ChangeTempo(tempo.Tempo);
                                            //if (LogEvents)Debug.Log(BuildInfoTrack(trackEvent) + string.Format("SetTempo   {0} MicrosecondsPerQuarterNote:{1}", tempo.Tempo, tempo.MicrosecondsPerQuarterNote));
                                        }
                                        break;

                                    case MetaEventType.SequenceTrackName:
                                        if (!string.IsNullOrEmpty(SequenceTrackName))
                                        {
                                            SequenceTrackName += "\n";
                                        }
                                        SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, ((TextEvent)meta).Text);
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence   '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.ProgramName:
                                        ProgramName += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Program   '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.TrackInstrumentName:
                                        if (!string.IsNullOrEmpty(TrackInstrumentName))
                                        {
                                            TrackInstrumentName += "\n";
                                        }
                                        TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, ((TextEvent)meta).Text);
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Text      '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.TextEvent:
                                        TextEvent += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence  '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.Copyright:
                                        Copyright += ((TextEvent)meta).Text + " ";
                                        if (LogEvents)
                                        {
                                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Copyright '{0}'", ((TextEvent)meta).Text));
                                        }
                                        break;

                                    case MetaEventType.Lyric:     // lyric
                                    case MetaEventType.Marker:    // marker
                                    case MetaEventType.CuePoint:  // cue point
                                    case MetaEventType.DeviceName:
                                        break;
                                    }
                                    //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                                }
                                else
                                {
                                    // Other midi event
                                    //Debug.Log(string.Format("Track:{0} Channel:{1,2:00} CommandCode:{2,3:000} AbsoluteTime:{3,6:000000}", track, e.Channel, e.CommandCode.ToString(), e.AbsoluteTime));
                                }
                            }
                            else
                            {
                                // Out of time, exit for loop
                                break;
                            }
                        }

                        if (notes != null)
                        {
                            //if (CancelNextReadEvents)
                            //{
                            //    notes = null;
                            //    //Debug.Log("CancelNextReadEvents");
                            //    CancelNextReadEvents = false;
                            //}
                            //else
                            //if (notes.Count > 3 && (notes[notes.Count - 1].AbsoluteQuantize - notes[0].AbsoluteQuantize) > midifile.DeltaTicksPerQuarterNote * 8)
                            //{
                            //    //notes.RemoveRange(0, notes.Count - 1);
                            //    Debug.Log("--> Too much notes " + notes.Count + " timeFromStartMS:" + Convert.ToInt32(timeFromStartMS) + " Start:" + notes[0].AbsoluteQuantize + " Ecart:" + (notes[notes.Count - 1].AbsoluteQuantize - notes[0].AbsoluteQuantize) + " CurrentPulse:" + CurrentPulse);
                            //    //notes = null;
                            //}
                        }
                    }
                    else
                    {
                        // End of midi events
                        EndMidiEvent = true;
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(notes);
        }
Beispiel #8
0
 private static string BuildInfoTrack(TrackMidiEvent e)
 {
     return(string.Format("[{0,5:000000}] [T:{1,2:00} C:{2,2:00}] ", e.Event.AbsoluteTime, e.IndexTrack, e.Event.Channel));
 }
Beispiel #9
0
        /// <summary>
        /// Read midi event Tempo and Patch change from start
        /// </summary>
        /// <param name="timeFromStartMS"></param>
        /// <returns></returns>
        public List <MPTKEvent> ReadChangeFromStart(int position)
        {
            List <MPTKEvent> midievents = new List <MPTKEvent>();;

            try
            {
                if (midifile != null)
                {
                    if (position < 0 || position >= MidiSorted.Count)
                    {
                        position = MidiSorted.Count - 1;
                    }

                    for (int currentPosEvent = 0; currentPosEvent < position; currentPosEvent++)
                    {
                        TrackMidiEvent trackEvent = MidiSorted[currentPosEvent];
                        MPTKEvent      midievent  = null;
                        switch (trackEvent.Event.CommandCode)
                        {
                        case MidiCommandCode.ControlChange:
                            ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                            midievent = new MPTKEvent()
                            {
                                Tick       = trackEvent.AbsoluteQuantize,
                                Command    = MPTKCommand.ControlChange,
                                Channel    = trackEvent.Event.Channel - 1,
                                Controller = (MPTKController)controlchange.Controller,
                                Value      = controlchange.ControllerValue,
                            };
                            break;

                        case MidiCommandCode.PatchChange:
                            PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                            midievent = new MPTKEvent()
                            {
                                Tick    = trackEvent.AbsoluteQuantize,
                                Command = MPTKCommand.PatchChange,
                                Channel = trackEvent.Event.Channel - 1,
                                Value   = change.Patch,
                            };
                            break;

                        case MidiCommandCode.MetaEvent:
                            MetaEvent meta = (MetaEvent)trackEvent.Event;
                            if (meta.MetaEventType == MetaEventType.SetTempo)
                            {
                                TempoEvent tempo = (TempoEvent)meta;
                                midievent = new MPTKEvent()
                                {
                                    Tick     = trackEvent.AbsoluteQuantize,
                                    Command  = MPTKCommand.MetaEvent,
                                    Channel  = trackEvent.Event.Channel - 1,
                                    Meta     = (MPTKMeta)meta.MetaEventType,
                                    Duration = tempo.Tempo,
                                };
                            }
                            break;
                        }
                        if (midievent != null)
                        {
                            midievents.Add(midievent);
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(midievents);
        }
Beispiel #10
0
        /// <summary>
        /// Add a TrackMidiEvent to a list of MPTKEvent.
        /// </summary>
        /// <param name="mptkEvents">Must be alloc before the call</param>
        /// <param name="trackEvent"></param>
        /// <returns></returns>

        private bool ConvertToEventForNote(List <MPTKEvent> mptkEvents, TrackMidiEvent trackEvent)
        {
            bool      exitLoop  = false;
            MPTKEvent midievent = null;

            switch (trackEvent.Event.CommandCode)
            {
            case MidiCommandCode.NoteOn:

                if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
                {
                    NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                    //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                    if (noteon.NoteLength > 0)
                    {
                        midievent = new MPTKEvent()
                        {
                            Tick     = trackEvent.AbsoluteQuantize,
                            Command  = MPTKCommand.NoteOn,
                            Value    = noteon.NoteNumber,
                            Channel  = trackEvent.Event.Channel - 1,
                            Velocity = noteon.Velocity,
                            Duration = noteon.NoteLength * TickLengthMs,
                            Length   = noteon.NoteLength,
                        };
                        //mptkEvents.Add(midievent);

                        // show playing note
                        //Debug.Log(midievent.Channel);
                        if (midievent.Channel == selectedChannel)
                        {
                            Kbd_PKeyGen.instance.ShowMidiNoteOn(noteon.NoteNumber);
                        }

                        if (LogEvents)
                        {
                            string notename = (midievent.Channel != 9) ?
                                              String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOn  {0,3:000}\t{1,-4}\tLenght:{2,5}\t{3}\tVeloc:{4,3}",
                                                                                 midievent.Value, notename, noteon.NoteLength, NoteLength(midievent), noteon.Velocity));
                        }
                    }
                    else if (KeepNoteOff)
                    {
                        midievent = CreateNoteOffForNote(mptkEvents, trackEvent);
                    }
                }
                break;

            case MidiCommandCode.NoteOff:
                midievent = CreateNoteOffForNote(mptkEvents, trackEvent);
                break;

            case MidiCommandCode.ControlChange:

                ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick       = trackEvent.AbsoluteQuantize,
                    Command    = MPTKCommand.ControlChange,
                    Channel    = trackEvent.Event.Channel - 1,
                    Controller = (MPTKController)controlchange.Controller,
                    Value      = controlchange.ControllerValue,
                };
                mptkEvents.Add(midievent);

                // Other midi event
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                }

                break;

            case MidiCommandCode.PatchChange:
                PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PatchChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = change.Patch,
                };
                mptkEvents.Add(midievent);
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                }
                break;

            case MidiCommandCode.MetaEvent:
                MetaEvent meta = (MetaEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.MetaEvent,
                    Channel = trackEvent.Event.Channel - 1,
                    Meta    = (MPTKMeta)meta.MetaEventType,
                };

                switch (meta.MetaEventType)
                {
                case MetaEventType.TimeSignature:
                    AnalyzeTimeSignature(meta);
                    break;

                case MetaEventType.SetTempo:
                    TempoEvent tempo = (TempoEvent)meta;
                    // Tempo change will be done in MidiFilePlayer
                    midievent.Duration = tempo.Tempo;
                    MPTK_MicrosecondsPerQuarterNote = tempo.MicrosecondsPerQuarterNote;
                    // Force exit loop
                    exitLoop = true;
                    break;

                case MetaEventType.SequenceTrackName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(SequenceTrackName))
                    {
                        SequenceTrackName += "\n";
                    }
                    SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence   '{0}'", note.Info));
                    break;

                case MetaEventType.ProgramName:
                    midievent.Info = ((TextEvent)meta).Text;
                    ProgramName   += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Program   '{0}'", note.Info));
                    break;

                case MetaEventType.TrackInstrumentName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(TrackInstrumentName))
                    {
                        TrackInstrumentName += "\n";
                    }
                    TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Text      '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.TextEvent:
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Sequence  '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.Copyright:
                    midievent.Info = ((TextEvent)meta).Text;
                    Copyright     += midievent.Info + " ";
                    //if (LogEvents) Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Copyright '{0}'", ((TextEvent)meta).Text));
                    break;

                case MetaEventType.Lyric:         // lyric
                    midievent.Info = ((TextEvent)meta).Text;
                    break;

                case MetaEventType.Marker:         // marker
                case MetaEventType.CuePoint:       // cue point
                case MetaEventType.DeviceName:
                    break;
                }

                if (LogEvents && !string.IsNullOrEmpty(midievent.Info))
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta    {0,15} '{1}'", midievent.Meta, midievent.Info));
                }

                mptkEvents.Add(midievent);
                //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                break;

            default:
                // Other midi event
                if (LogEvents)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Other   {0,15} Not handle by MPTK", trackEvent.Event.CommandCode));
                }
                break;
            }

            return(exitLoop);
        }
Beispiel #11
0
        /// <summary>
        /// Read a list of midi event available for the current time
        /// </summary>
        /// <param name="timeFromStartMS"></param>
        /// <returns></returns>

        public List <MPTKEvent> ReadMidiEventsForNote(double timeFromStartMS)
        {
            List <MPTKEvent> midievents = null;

            try
            {
                EndMidiEvent = false;
                if (midifile != null)
                {
                    if (NextPosEvent < MidiSortedForNote.Count)
                    {
                        // The BPM measures how many quarter notes happen in a minute. To work out the length of each pulse we can use the following formula:
                        // Pulse Length = 60 / (BPM * PPQN)
                        // Calculate current pulse to play
                        CurrentTick += Convert.ToInt64((timeFromStartMS - LastTimeFromStartMS) / TickLengthMs);

                        LastTimeFromStartMS = timeFromStartMS;
                        // From the last position played
                        for (int currentPosEvent = NextPosEvent; currentPosEvent < MidiSortedForNote.Count; currentPosEvent++)
                        {
                            TrackMidiEvent trackEvent = MidiSortedForNote[currentPosEvent];
                            if (Quantization != 0)
                            {
                                trackEvent.AbsoluteQuantize = ((trackEvent.Event.AbsoluteTime + Quantization / 2) / Quantization) * Quantization;
                            }
                            else
                            {
                                trackEvent.AbsoluteQuantize = trackEvent.Event.AbsoluteTime;
                            }

                            //Debug.Log("ReadMidiEvents - timeFromStartMS:" + Convert.ToInt32(timeFromStartMS) + " LastTimeFromStartMS:" + Convert.ToInt32(LastTimeFromStartMS) + " CurrentPulse:" + CurrentPulse + " AbsoluteQuantize:" + trackEvent.AbsoluteQuantize);

                            //Kbd_PKeyGen.instance.ShowMidiNoteOn(trackEvent.Event.AbsoluteTime);
                            // Kbd_PKeyGen.instance.ShowMidiNoteOn(62);

                            if (trackEvent.AbsoluteQuantize <= CurrentTick)
                            {
                                NextPosEvent = currentPosEvent + 1;
                                if (midievents == null)
                                {
                                    midievents = new List <MPTKEvent>();
                                }
                                if (ConvertToEventForNote(midievents, trackEvent))
                                {
                                    break;
                                }
                                ;
                            }
                            else
                            {
                                // Out of time, exit for loop
                                break;
                            }
                        }
                    }
                    else
                    {
                        // End of midi events
                        EndMidiEvent = true;
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }

            if (midievents != null && midievents.Count > 0)
            {
                MPTK_TickCurrent = midievents.Last().Tick;
            }


            return(midievents);
        }
Beispiel #12
0
        /// <summary>
        /// Add a TrackMidiEvent to a list of MPTKEvent.
        /// </summary>
        /// <param name="mptkEvents">Must be alloc before the call</param>
        /// <param name="trackEvent"></param>
        /// <returns></returns>
        private void ConvertToEvent(List <MPTKEvent> mptkEvents, TrackMidiEvent trackEvent)
        {
            MPTKEvent midievent = null;

            switch (trackEvent.Event.CommandCode)
            {
            case MidiCommandCode.NoteOn:
                //if (((NoteOnEvent)trackEvent.Event).OffEvent != null)
            {
                NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event;
                //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                if (noteon.OffEvent != null)
                {
                    midievent = new MPTKEvent()
                    {
                        Track    = trackEvent.IndexTrack,
                        Tick     = trackEvent.AbsoluteQuantize,
                        Command  = MPTKCommand.NoteOn,
                        Value    = noteon.NoteNumber,
                        Channel  = trackEvent.Event.Channel - 1,
                        Velocity = noteon.Velocity,
                        Duration = Convert.ToInt64(noteon.NoteLength * MPTK_PulseLenght),
                        Length   = noteon.NoteLength,
                    };
                    mptkEvents.Add(midievent);
                    if (LogEvents && seek_ticks < 0)
                    {
                        string notename = (midievent.Channel != 9) ?
                                          String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOn  {0,3:000}\t{1,-4}\tLenght:{2,5}\t{3}\tVeloc:{4,3}",
                                                                             midievent.Value, notename, noteon.NoteLength, NoteLength(midievent), noteon.Velocity));
                    }
                }
                else         // It's a noteoff
                {
                    if (KeepNoteOff)
                    {
                        midievent = new MPTKEvent()
                        {
                            Track    = trackEvent.IndexTrack,
                            Tick     = trackEvent.AbsoluteQuantize,
                            Command  = MPTKCommand.NoteOff,
                            Value    = noteon.NoteNumber,
                            Channel  = trackEvent.Event.Channel - 1,
                            Velocity = noteon.Velocity,
                            Duration = Convert.ToInt64(noteon.NoteLength * MPTK_PulseLenght),
                            Length   = noteon.NoteLength,
                        };
                        mptkEvents.Add(midievent);

                        if (LogEvents && seek_ticks < 0)
                        {
                            string notename = (midievent.Channel != 9) ?
                                              String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3:000}\t{1,-4}\tLenght:{2}", midievent.Value, notename, " Note Off"));
                        }
                    }
                }
            }
            break;

            case MidiCommandCode.NoteOff:
                if (KeepNoteOff)
                {
                    NoteEvent noteoff = (NoteEvent)trackEvent.Event;
                    //Debug.Log(string.Format("Track:{0} NoteNumber:{1,3:000} AbsoluteTime:{2,6:000000} NoteLength:{3,6:000000} OffDeltaTime:{4,6:000000} ", track, noteon.NoteNumber, noteon.AbsoluteTime, noteon.NoteLength, noteon.OffEvent.DeltaTime));
                    midievent = new MPTKEvent()
                    {
                        Track    = trackEvent.IndexTrack,
                        Tick     = trackEvent.AbsoluteQuantize,
                        Command  = MPTKCommand.NoteOff,
                        Value    = noteoff.NoteNumber,
                        Channel  = trackEvent.Event.Channel - 1,
                        Velocity = noteoff.Velocity,
                        Duration = 0,
                        Length   = 0,
                    };

                    mptkEvents.Add(midievent);

                    if (LogEvents && seek_ticks < 0)
                    {
                        string notename = (midievent.Channel != 9) ?
                                          String.Format("{0}{1}", NoteNames[midievent.Value % 12], midievent.Value / 12) : "Drum";
                        Debug.Log(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3:000}\t{1,-4}\tLenght:{2}", midievent.Value, notename, " Note Off"));
                    }
                }
                break;

            case MidiCommandCode.PitchWheelChange:
                PitchWheelChangeEvent pitch = (PitchWheelChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PitchWheelChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = pitch.Pitch,    // Pitch Wheel Value 0 is minimum, 0x2000 (8192) is default, 0x3FFF (16383) is maximum
                };
                mptkEvents.Add(midievent);
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("PitchWheelChange {0}", pitch.Pitch));
                }
                break;

            case MidiCommandCode.ControlChange:
                ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track      = trackEvent.IndexTrack,
                    Tick       = trackEvent.AbsoluteQuantize,
                    Command    = MPTKCommand.ControlChange,
                    Channel    = trackEvent.Event.Channel - 1,
                    Controller = (MPTKController)controlchange.Controller,
                    Value      = controlchange.ControllerValue,
                };

                //if ((MPTKController)controlchange.Controller != MPTKController.Sustain)
                mptkEvents.Add(midievent);

                // Other midi event
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Control {0} {1}", controlchange.Controller, controlchange.ControllerValue));
                }

                break;

            case MidiCommandCode.PatchChange:
                PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.PatchChange,
                    Channel = trackEvent.Event.Channel - 1,
                    Value   = change.Patch,
                };
                mptkEvents.Add(midievent);
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Patch   {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)));
                }
                break;

            case MidiCommandCode.MetaEvent:
                MetaEvent meta = (MetaEvent)trackEvent.Event;
                midievent = new MPTKEvent()
                {
                    Track   = trackEvent.IndexTrack,
                    Tick    = trackEvent.AbsoluteQuantize,
                    Command = MPTKCommand.MetaEvent,
                    Channel = trackEvent.Event.Channel - 1,
                    Meta    = (MPTKMeta)meta.MetaEventType,
                };

                switch (meta.MetaEventType)
                {
                case MetaEventType.EndTrack:
                    midievent.Info = "End Track";
                    break;

                case MetaEventType.TimeSignature:
                    AnalyzeTimeSignature(meta, trackEvent);
                    break;

                case MetaEventType.SetTempo:
                    if (EnableChangeTempo)
                    {
                        TempoEvent tempo = (TempoEvent)meta;
                        // Tempo change will be done in MidiFilePlayer
                        midievent.Duration = (long)tempo.Tempo;
                        MPTK_MicrosecondsPerQuarterNote = tempo.MicrosecondsPerQuarterNote;
                        fluid_player_set_midi_tempo(tempo.MicrosecondsPerQuarterNote);

                        // Force exit loop
                        if (LogEvents && seek_ticks < 0)
                        {
                            Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta     {0,-15} Tempo:{1} MicrosecondsPerQuarterNote:{2}", meta.MetaEventType, tempo.Tempo, tempo.MicrosecondsPerQuarterNote));
                        }
                    }
                    break;

                case MetaEventType.SequenceTrackName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(SequenceTrackName))
                    {
                        SequenceTrackName += "\n";
                    }
                    SequenceTrackName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    break;

                case MetaEventType.ProgramName:
                    midievent.Info = ((TextEvent)meta).Text;
                    ProgramName   += midievent.Info + " ";
                    break;

                case MetaEventType.TrackInstrumentName:
                    midievent.Info = ((TextEvent)meta).Text;
                    if (!string.IsNullOrEmpty(TrackInstrumentName))
                    {
                        TrackInstrumentName += "\n";
                    }
                    TrackInstrumentName += string.Format("T{0,2:00} {1}", trackEvent.IndexTrack, midievent.Info);
                    break;

                case MetaEventType.TextEvent:
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.Copyright:
                    midievent.Info = ((TextEvent)meta).Text;
                    Copyright     += midievent.Info + " ";
                    break;

                case MetaEventType.Lyric:         // lyric
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.Marker:         // marker
                    midievent.Info = ((TextEvent)meta).Text;
                    TextEvent     += midievent.Info + " ";
                    break;

                case MetaEventType.CuePoint:         // cue point
                case MetaEventType.DeviceName:
                    break;
                }

                if (LogEvents && !string.IsNullOrEmpty(midievent.Info) && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta     {0,-15} '{1}'", midievent.Meta, midievent.Info));
                }

                mptkEvents.Add(midievent);
                //Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0} {1}", meta.MetaEventType, meta.ToString()));
                break;

            default:
                // Other midi event
                if (LogEvents && seek_ticks < 0)
                {
                    Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Other    {0,-15} Not handle by MPTK", trackEvent.Event.CommandCode));
                }
                break;
            }
        }
Beispiel #13
0
        public List <MPTKEvent> fluid_player_callback(int msec)
        {
            List <MPTKEvent> midievents = null;

            try
            {
                if (midifile != null && next_event >= 0)
                {
                    cur_msec  = msec;
                    cur_ticks = start_ticks + (int)(((double)(cur_msec - start_msec) / MPTK_PulseLenght) + 0.5d);

                    //Debug.Log("fluid_player_callback: cur_ticks:" + cur_ticks + " msec:" + cur_msec + " start_msec:" + start_msec + " start_ticks:" + start_ticks + " MPTK_PulseLenght:" + MPTK_PulseLenght + " seek_ticks:" + seek_ticks);

                    //if (seek_ticks >= 0)
                    //{
                    //    fluid_synth_all_sounds_off(synth, -1); /* avoid hanging notes */
                    //}

                    //----- midievents = fluid_send_events(midievents, cur_ticks);
                    int ticks = cur_ticks;

                    if (seek_ticks >= 0)
                    {
                        ticks = seek_ticks; /* update target ticks */
                        if (MPTK_TickCurrent > ticks)
                        {
                            // reset track if seeking backwards
                            next_event = 0;
                        }
                    }

                    // From the last position played
                    while (true)
                    {
                        if (next_event >= MPTK_MidiEvents.Count)
                        {
                            next_event = -1;
                            break;
                        }

                        TrackMidiEvent trackEvent = MPTK_MidiEvents[next_event];
                        trackEvent.AbsoluteQuantize = Quantization != 0 ?
                                                      ((trackEvent.Event.AbsoluteTime + Quantization / 2) / Quantization) * Quantization :
                                                      trackEvent.AbsoluteQuantize = trackEvent.Event.AbsoluteTime;

                        //Debug.Log("   fluid_track_send_events: Next:" + Next + " Ticks:" + Ticks + " ticks:" + ticks + " EventDeltaTime:" + trackEvent.Event.DeltaTime);

                        if (trackEvent.AbsoluteQuantize > ticks)
                        {
                            break;
                        }
                        //Debug.Log("   fluid_track_send_events: process this event " + trackEvent.Event.CommandCode + " at track.ticks:" + track.ticks);
                        //Debug.Log("   fluid_track_send_events: new at track.ticks:" + track.ticks);
                        if (seek_ticks >= 0 &&
                            (trackEvent.Event.CommandCode == MidiCommandCode.NoteOn ||
                             trackEvent.Event.CommandCode == MidiCommandCode.NoteOff ||
                             (trackEvent.Event.CommandCode == MidiCommandCode.MetaEvent && ((MetaEvent)trackEvent.Event).MetaEventType != MetaEventType.SetTempo)))
                        {
                            /* skip on/off messages */
                            //Debug.Log(BuildInfoTrack(trackEvent) + string.Format(" Skip {0} seek_ticks:{1}", trackEvent.Event.CommandCode, seek_ticks));
                        }
                        else
                        {
                            // send event to synth fluid_player_callback(evt);
                            if (midievents == null)
                            {
                                midievents = new List <MPTKEvent>();
                            }
                            ConvertToEvent(midievents, trackEvent);
                            //Debug.Log(BuildInfoTrack(trackEvent) + string.Format(" Add {0} seek_ticks:{1}", trackEvent.Event.CommandCode, seek_ticks));

                            MPTK_TickCurrent = trackEvent.Event.AbsoluteTime;
                        }
                        next_event++;
                    }
                    //------ end fluid_send_events
                    if (seek_ticks >= 0)
                    {
                        //Debug.Log("fluid_player_callback Seek Ticks : cur_ticks:" + cur_ticks + " seek_ticks:" + seek_ticks);
                        start_ticks = seek_ticks; /* tick position of last tempo value (which is now) */ /* the number of tempo ticks passed at the last tempo change */
                        cur_ticks   = seek_ticks; /* the number of tempo ticks passed */
                        //begin_msec = msec;      /* only used to calculate the duration of playing */
                        start_msec = msec;        /* should be the (synth)-time of the last tempo change */
                        seek_ticks = -1;          /* clear seek_ticks */
                    }

                    if (next_event < 0)
                    {
                        EndMidiEvent = true;
                    }
                }
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }

            return(midievents);
        }
Beispiel #14
0
        private List <TrackMidiEvent> GetMidiEvents()
        {
            //Debug.Log("GetEvents");
            try
            {
                MPTK_TickLast = -1;
                int countTracks = 0;
                List <TrackMidiEvent> events = new List <TrackMidiEvent>();
                foreach (IList <MidiEvent> track in midifile.Events)
                {
                    countTracks++;
                    foreach (MidiEvent e in track)
                    {
                        try
                        {
                            //bool keepEvent = false;
                            if (e.AbsoluteTime > MPTK_TickLast)
                            {
                                MPTK_TickLast = e.AbsoluteTime;
                            }

                            switch (e.CommandCode)
                            {
                            case MidiCommandCode.NoteOn:
                                //Debug.Log("NoteOn "+ KeepNoteOff);
                                if (e.AbsoluteTime < MPTK_TickFirstNote || MPTK_TickFirstNote == -1)
                                {
                                    //Debug.Log("NoteOn MPTK_TickFirstNote" + e.AbsoluteTime);
                                    MPTK_TickFirstNote = e.AbsoluteTime;
                                }
                                //keepEvent = true;
                                break;
                            //case MidiCommandCode.NoteOff:
                            //    //Debug.Log("NoteOff "+ KeepNoteOff);
                            //    //keepEvent = true;
                            //    break;
                            //case MidiCommandCode.ControlChange:
                            //    //ControlChangeEvent ctrl = (ControlChangeEvent)e;
                            //    //Debug.Log("NoteOff");
                            //    keepEvent = true;
                            //    break;
                            //case MidiCommandCode.PatchChange:
                            //    keepEvent = true;
                            //    break;

                            case MidiCommandCode.MetaEvent:
                                MetaEvent meta = (MetaEvent)e;
                                switch (meta.MetaEventType)
                                {
                                case MetaEventType.SetTempo:
                                    TempoEvent tempo = (TempoEvent)meta;
                                    // Calculate the real duration
                                    if (EnableChangeTempo)
                                    {
                                        MPTK_DurationMS += ((e.AbsoluteTime - timeLastSegment) * (float)MPTK_PulseLenght);
                                        timeLastSegment  = e.AbsoluteTime;
                                    }
                                    fluid_player_set_midi_tempo(tempo.MicrosecondsPerQuarterNote);
                                    // Set the first tempo value find
                                    if (MPTK_InitialTempo < 0)
                                    {
                                        MPTK_InitialTempo = tempo.Tempo;
                                    }
                                    if (MPTK_MicrosecondsPerQuarterNote == 0)
                                    {
                                        MPTK_MicrosecondsPerQuarterNote = tempo.MicrosecondsPerQuarterNote;
                                    }
                                    //Debug.Log("Partial at: " + timeLastSegment + " " + MPTK_RealDuration + " " + Math.Round(TickLengthMs, 2) + " " + Math.Round(QuarterPerMinuteValue, 2));
                                    //Debug.Log("Tempo: " + ((TempoEvent)e).Tempo + " MPTK_InitialTempo:" + MPTK_InitialTempo);
                                    break;

                                case MetaEventType.TimeSignature:
                                    AnalyzeTimeSignature(meta);
                                    break;
                                }
                                //keepEvent = true;
                                break;
                            }

                            //if (keepEvent)
                            //{
                            TrackMidiEvent tmidi = new TrackMidiEvent()
                            {
                                IndexTrack = countTracks,
                                Event      = e//.Clone()
                            };

                            events.Add(tmidi);
                            //}
                        }
                        catch (System.Exception ex)
                        {
                            MidiPlayerGlobal.ErrorDetail(ex);
                            return(null);
                        }
                    }
                }
                //DebugMidiSorted(events);

                MPTK_TrackCount = countTracks;
                List <TrackMidiEvent> midievents = events.OrderBy(o => o.Event.AbsoluteTime).ToList();
                if (midievents.Count > 0)
                {
                    long lastAbsoluteTime = midievents[midievents.Count - 1].Event.AbsoluteTime;
                    MPTK_TickLast = lastAbsoluteTime;
                    //Debug.Log("End at: " + lastAbsoluteTime + " " + MPTK_RealDuration + " " + Math.Round(TickLengthMs, 2) + " " + Math.Round(QuarterPerMinuteValue, 2));
                }
                else
                {
                    MPTK_TickLast = 0;
                }

                if (MPTK_TickLast > 0 && EnableChangeTempo)
                {
                    // Calculate the real duration, cumul all segments with tempo change
                    MPTK_DurationMS += ((MPTK_TickLast - timeLastSegment) * (float)MPTK_PulseLenght);
                }
                return(midievents);
            }
            catch (System.Exception ex)
            {
                MidiPlayerGlobal.ErrorDetail(ex);
            }
            return(null);
        }