示例#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();
        }
示例#2
0
 protected abstract void ParseNextEvent(EventInfo info);
示例#3
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;
        }
示例#4
0
        bool ProcessEvent(EventInfo info, bool fireEvents = true)
        {
            if (info.Event == 0xF0)
            {
                // SysEx event
                // Check for trailing 0xF7 -- if present, remove it.
                if (fireEvents)
                {
                    if (info.Data[info.Data.Length - 1] == 0xF7)
                        MidiDriver.SysEx(info.Data, (ushort)(info.Data.Length - 1));
                    else
                        MidiDriver.SysEx(info.Data, (ushort)info.Data.Length);
                }
            }
            else if (info.Event == 0xFF)
            {
                // META event
                if (info.MetaType == 0x2F)
                {
                    // End of Track must be processed by us,
                    // as well as sending it to the output device.
                    if (_autoLoop)
                    {
                        JumpToTick(0);
                        ParseNextEvent(_nextEvent);
                    }
                    else
                    {
                        StopPlaying();
                        if (fireEvents)
                            MidiDriver.MetaEvent((byte)info.MetaType, info.Data, (ushort)info.Data.Length);
                    }
                    return false;
                }
                else if (info.MetaType == 0x51)
                {
                    if (info.Data.Length >= 3)
                    {
                        Tempo = (info.Data[0] << 16 | info.Data[1] << 8 | info.Data[2]);
                    }
                }
                if (fireEvents)
                    MidiDriver.MetaEvent((byte)info.MetaType, info.Data, (ushort)info.Data.Length);
            }
            else
            {
                if (fireEvents)
                    SendToDriver(info.Event, info.Param1, info.Param2);
            }

            return true;
        }
示例#5
0
 public EventInfo(EventInfo info)
 {
     Start = info.Start;
     Delta = info.Delta;
     Event = info.Event;
     Param1 = info.Param1;
     Param2 = info.Param2;
     MetaType = info.MetaType;
     Data = info.Data;
 }