public void ProcessMidiMessage(MidiEvent e) { var command = e.Command; var channel = e.Channel; var data1 = e.Data1; var data2 = e.Data2; switch (command) { case MidiEventTypeEnum.NoteOff: NoteOff(channel, data1); break; case MidiEventTypeEnum.NoteOn: if (data2 == 0) { NoteOff(channel, data1); } else { NoteOn(channel, data1, data2); } break; case MidiEventTypeEnum.NoteAftertouch: //synth uses channel after touch instead break; case MidiEventTypeEnum.Controller: switch ((ControllerTypeEnum)data1) { case ControllerTypeEnum.BankSelectCoarse: //Bank select coarse if (channel == MidiHelper.DrumChannel) { data2 += PatchBank.DrumBank; } if (SoundBank.IsBankLoaded(data2)) { _synthChannels[channel].BankSelect = (byte)data2; } else { _synthChannels[channel].BankSelect = (byte)((channel == MidiHelper.DrumChannel) ? PatchBank.DrumBank : 0); } break; case ControllerTypeEnum.ModulationCoarse: //Modulation wheel coarse _synthChannels[channel].ModRange.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentMod(); break; case ControllerTypeEnum.ModulationFine: //Modulation wheel fine _synthChannels[channel].ModRange.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentMod(); break; case ControllerTypeEnum.VolumeCoarse: //Channel volume coarse _synthChannels[channel].Volume.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentVolumeFromVolume(); break; case ControllerTypeEnum.VolumeFine: //Channel volume fine _synthChannels[channel].Volume.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentVolumeFromVolume(); break; case ControllerTypeEnum.PanCoarse: //Pan coarse _synthChannels[channel].Pan.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentPan(); break; case ControllerTypeEnum.PanFine: //Pan fine _synthChannels[channel].Pan.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentPan(); break; case ControllerTypeEnum.ExpressionControllerCoarse: //Expression coarse _synthChannels[channel].Expression.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentVolumeFromExpression(); break; case ControllerTypeEnum.ExpressionControllerFine: //Expression fine _synthChannels[channel].Expression.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentVolumeFromExpression(); break; case ControllerTypeEnum.HoldPedal: //Hold pedal if (_synthChannels[channel].HoldPedal && !(data2 > 63)) //if hold pedal is released stop any voices with pending release tags { ReleaseHoldPedal(channel); } _synthChannels[channel].HoldPedal = data2 > 63; break; case ControllerTypeEnum.LegatoPedal: //Legato Pedal _synthChannels[channel].LegatoPedal = data2 > 63; break; case ControllerTypeEnum.NonRegisteredParameterCourse: //NRPN Coarse Select //fix for invalid DataEntry after unsupported NRPN events _synthChannels[channel].Rpn.Combined = 0x3FFF; //todo implement NRPN break; case ControllerTypeEnum.NonRegisteredParameterFine: //NRPN Fine Select //fix for invalid DataEntry after unsupported NRPN events _synthChannels[channel].Rpn.Combined = 0x3FFF; //todo implement NRPN break; case ControllerTypeEnum.RegisteredParameterCourse: //RPN Coarse Select _synthChannels[channel].Rpn.Coarse = (byte)data2; break; case ControllerTypeEnum.RegisteredParameterFine: //RPN Fine Select _synthChannels[channel].Rpn.Fine = (byte)data2; break; case ControllerTypeEnum.AllNotesOff: //Note Off All NoteOffAll(false); break; case ControllerTypeEnum.DataEntryCoarse: //DataEntry Coarse switch (_synthChannels[channel].Rpn.Combined) { case 0: //change semitone, pitchwheel _synthChannels[channel].PitchBendRangeCoarse = (byte)data2; _synthChannels[channel].UpdateCurrentPitch(); break; case 1: //master fine tune coarse _synthChannels[channel].MasterFineTune.Coarse = (byte)data2; break; case 2: //master coarse tune coarse _synthChannels[channel].MasterCoarseTune = (short)(data2 - 64); break; } break; case ControllerTypeEnum.DataEntryFine: //DataEntry Fine switch (_synthChannels[channel].Rpn.Combined) { case 0: //change cents, pitchwheel _synthChannels[channel].PitchBendRangeFine = (byte)data2; _synthChannels[channel].UpdateCurrentPitch(); break; case 1: //master fine tune fine _synthChannels[channel].MasterFineTune.Fine = (byte)data2; break; } break; case ControllerTypeEnum.ResetControllers: //Reset All _synthChannels[channel].Expression.Combined = 0x3FFF; _synthChannels[channel].ModRange.Combined = 0; if (_synthChannels[channel].HoldPedal) { ReleaseHoldPedal(channel); } _synthChannels[channel].HoldPedal = false; _synthChannels[channel].LegatoPedal = false; _synthChannels[channel].Rpn.Combined = 0x3FFF; _synthChannels[channel].PitchBend.Combined = 0x2000; _synthChannels[channel].ChannelAfterTouch = 0; _synthChannels[channel].UpdateCurrentPitch(); //because pitchBend was reset _synthChannels[channel].UpdateCurrentVolumeFromExpression(); //because expression was reset break; default: return; } break; case MidiEventTypeEnum.ProgramChange: //Program Change _synthChannels[channel].Program = (byte)data1; break; case MidiEventTypeEnum.ChannelAftertouch: //Channel Aftertouch _synthChannels[channel].ChannelAfterTouch = (byte)data2; break; case MidiEventTypeEnum.PitchBend: //Pitch Bend _synthChannels[channel].PitchBend.Coarse = (byte)data2; _synthChannels[channel].PitchBend.Fine = (byte)data1; _synthChannels[channel].UpdateCurrentPitch(); break; } OnMidiEventProcessed(e); }