예제 #1
0
        void Dispatch(MidiEvent ev)
        {
            switch (miv.type)
            {
            case MidiEvent.Type.Controller:
                switch (ev.p1)
                {
                case 0x63:         // depth control
                                   // TD: implement
                    break;

                case 0x66:         // song marker
                                   // This can be used to notify the music player that a certain point
                                   // in a song has been reached, or to trigger some kind of action in
                                   // time with the music.
                    break;

                case 0x67:         // control rhythm mode
                    rhythmMode = ev.p2 > 0;

                    if (rhythmMode)
                    {
                        regbd = 1 << 5;
                        adlib.Poke(0xBD, regbd);
                    }
                    else
                    {
                        regbd = 0;
                        adlib.Poke(0xBD, regbd);
                    }
                    break;

                case 0x68:         // transpose up
                                   // TD: implement
                    break;

                case 0x69:         // transpose down
                                   // TD: implement
                    break;
                }
                break;

            case MidiEvent.Type.ProgramChange:
                if (rhythmMode && ev.channel >= 11)
                {
                    LoadRhythm(adlib, ev.channel, cmfFile.instruments[ev.p1]);
                }
                else
                {
                    LoadInstrument(adlib, ev.channel, cmfFile.instruments[ev.p1]);
                }
                break;

            case MidiEvent.Type.NoteOn:
                if (ev.p2 > 0)
                {
                    if (channels[ev.channel].midiNote != -1)
                    {
                        SetGate(ev.channel, false);
                    }

                    channels[ev.channel].midiNote = ev.p1;


                    if (rhythmMode && ev.channel >= 11)
                    {
                        if (ev.channel == 11)    // bassdrum
                        {
                            SetChannelPitch(6, ev.p1);
                        }

                        SetRhythmGate(ev.channel, true);
                        SetRhythmVelocity(ev.channel, ev.p2 / 127f);

                        switch (ev.channel)
                        {
                        case 11:         // bassdrum
                            ChannelActivity?.Invoke(time, 6, ev.p2 / 127f);
                            break;

                        case 12:         // snare
                        case 13:         // tom
                            ChannelActivity?.Invoke(time, 7, ev.p2 / 127f);
                            break;

                        case 14:         // cymbal
                        case 15:         // hat
                            ChannelActivity?.Invoke(time, 8, ev.p2 / 127f);
                            break;
                        }
                    }
                    else
                    {
                        SetChannelPitch(ev.channel, ev.p1);
                        SetChannelVelocity(ev.channel, ev.p2 / 127f);
                        SetGate(ev.channel, true);

                        ChannelActivity?.Invoke(time, ev.channel, ev.p2 / 127f);
                    }
                }
                else
                {
                    if (channels[ev.channel].midiNote == ev.p1)
                    {
                        channels[ev.channel].midiNote = -1;

                        if (rhythmMode && ev.channel >= 11)
                        {
                            SetRhythmGate(ev.channel, false);
                        }
                        else
                        {
                            SetGate(ev.channel, false);
                        }
                    }
                }
                break;

            case MidiEvent.Type.NoteOff:
                if (channels[ev.channel].midiNote == ev.p1)
                {
                    if (rhythmMode && ev.channel >= 11)
                    {
                        SetRhythmGate(ev.channel, false);
                    }
                    else
                    {
                        SetGate(ev.channel, false);
                    }
                }
                break;
            }
        }
예제 #2
0
        public MidiEvent ReadEvent()
        {
            var ev = new MidiEvent();

            ev.delta = RVlen(f);
            int b = f.ReadByte();
            int type;

            if (b < 128)
            {
                if (rstatus == -1)
                {
                    throw new Exception("read error");
                }
                type = rstatus;
                f.Position--;
            }
            else
            {
                type    = b;
                rstatus = type;
            }
            switch (type & 0xF0)
            {
            case 0x80:
            case 0x90:
            case 0xA0:
            case 0xB0:
            case 0xE0:
                ev.channel = (type & 0xF);
                type     >>= 4;
                ev.p1      = f.ReadByte();
                ev.p2      = f.ReadByte();
                break;

            case 0xC0:
            case 0xD0:
                ev.channel = type & 0xF;
                type     >>= 4;
                ev.p1      = f.ReadByte();
                break;

            case 0xF0:
                if (type == 0xFF)
                {
                    ev.metaType = f.ReadByte();
                    if (ev.metaType == 0x2F)
                    {
                        end = true;
                    }
                }
                type  >>= 4;
                ev.data = new byte[RVlen(f)];
                f.Read(ev.data, 0, ev.data.Length);
                break;

            default:
                throw new Exception("bad event x" + type.ToString("X2").ToUpper());
            }
            ev.type = (MidiEvent.Type)type;
            return(ev);
        }