예제 #1
0
        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);
        }