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;
}
FireMidiMessageProcessed(e);
}