Example #1
0
        protected MidiParser()
        {
            ActiveNotes = new ushort[128];
            HangingNotes = new NoteTimer[32];
            for (int i = 0; i < HangingNotes.Length; i++)
            {
                HangingNotes[i] = new NoteTimer();
            }
            Tracks = new Track[120];

            TimerRate = 0x4A0000;
            _ppqn = 96;
            tempo = 500000;
            _psecPerTick = 5208;// 500000 / 96
            _nextEvent = new EventInfo();
            _nextEvent.Start = 0;
            _nextEvent.Delta = 0;
            _nextEvent.Event = 0;
            Position = new Tracker();
        }
Example #2
0
        public bool JumpToTick(uint tick, bool fireEvents = false, bool stopNotes = true, bool dontSendNoteOn = false)
        {
            if (ActiveTrack >= NumTracks)
                return false;

            Debug.Assert(!_jumpingToTick); // This function is not re-entrant
            _jumpingToTick = true;

            Tracker currentPos = new Tracker(Position);
            var currentEvent = new EventInfo(_nextEvent);

            ResetTracking();
            Position.PlayPos = Tracks[ActiveTrack].Position;
            ParseNextEvent(_nextEvent);
            if (tick > 0)
            {
                while (true)
                {
                    EventInfo info = _nextEvent;
                    if (Position.LastEventTick + info.Delta >= tick)
                    {
                        Position.PlayTime += (int)(tick - Position.LastEventTick) * _psecPerTick;
                        Position.PlayTick = (int)tick;
                        break;
                    }

                    Position.LastEventTick += info.Delta;
                    Position.LastEventTime += (int)info.Delta * _psecPerTick;
                    Position.PlayTick = (int)Position.LastEventTick;
                    Position.PlayTime = Position.LastEventTime;

                    // Some special processing for the fast-forward case
                    if (info.Command == 0x9 && dontSendNoteOn)
                    {
                        // Don't send note on; doing so creates a "warble" with
                        // some instruments on the MT-32. Refer to patch #3117577
                    }
                    else if (info.Event == 0xFF && info.MetaType == 0x2F)
                    {
                        // End of track
                        // This means that we failed to find the right tick.
                        Position = currentPos;
                        _nextEvent = currentEvent;
                        _jumpingToTick = false;
                        return false;
                    }
                    else
                    {
                        ProcessEvent(info, fireEvents);
                    }

                    ParseNextEvent(_nextEvent);
                }
            }

            if (stopNotes)
            {
                if (_smartJump || currentPos.PlayPos == 0)
                {
                    AllNotesOff();
                }
                else
                {
                    var targetEvent = new EventInfo(_nextEvent);
                    var targetPosition = new Tracker(Position);

                    Position = currentPos;
                    _nextEvent = currentEvent;
                    HangAllActiveNotes();

                    _nextEvent = targetEvent;
                    Position = targetPosition;
                }
            }

            AbortParse = true;
            _jumpingToTick = false;
            return true;
        }