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; } }
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); }