예제 #1
0
        private void MidiInPort_MessageReceived(MidiInPort sender, MidiMessageReceivedEventArgs args)
        {
            IMidiMessage receivedMidiMessage = args.Message;

            System.Diagnostics.Debug.WriteLine(receivedMidiMessage.Timestamp.ToString());

            if (receivedMidiMessage.Type == MidiMessageType.NoteOn)
            {
                byte channel     = ((MidiNoteOnMessage)receivedMidiMessage).Channel;
                byte note        = ((MidiNoteOnMessage)receivedMidiMessage).Note;
                byte velocity    = ((MidiNoteOnMessage)receivedMidiMessage).Velocity;
                int  octave      = note / 12;
                int  fundamental = note % 12;
                System.Diagnostics.Debug.WriteLine(channel);
                System.Diagnostics.Debug.WriteLine(note);
                System.Diagnostics.Debug.WriteLine(velocity);
                System.Diagnostics.Debug.WriteLine(octave);
                System.Diagnostics.Debug.WriteLine(fundamental);


                IMidiMessage message = new MidiNoteOnMessage(channel, note, velocity);
                midiOutPort.SendMessage(message);
            }
            else if (receivedMidiMessage.Type == MidiMessageType.NoteOff)
            {
                byte         channel  = ((MidiNoteOffMessage)receivedMidiMessage).Channel;
                byte         note     = ((MidiNoteOffMessage)receivedMidiMessage).Note;
                byte         velocity = ((MidiNoteOffMessage)receivedMidiMessage).Velocity;
                IMidiMessage message  = new MidiNoteOffMessage(channel, note, velocity);
                midiOutPort.SendMessage(message);
            }
        }
예제 #2
0
        public void Transmit(byte[] notes)
        {
            if (transmitted.Count == 0)
            {
                if (transmit.Count > 0)
                {
                    byte[] prefer = transmit.Dequeue();

                    foreach (byte note in prefer)
                    {
                        midiOutPort.SendMessage(new MidiNoteOnMessage(0, note, 127));
                        transmitted.Enqueue(note);
                    }

                    transmit.Enqueue(notes);
                }
                else
                {
                    foreach (byte note in notes)
                    {
                        midiOutPort.SendMessage(new MidiNoteOnMessage(0, note, 127));
                        transmitted.Enqueue(note);
                    }
                }
            }
            else // Wait upon closing the transmitted notes
            {
                transmit.Enqueue(notes);
            }
        }
예제 #3
0
        private async Task PlayNoteAsync(byte noteNumber, int duration = Skip, byte velocity = 127)
        {
            _currentDevice?.SendMessage(new MidiNoteOnMessage(0, noteNumber, velocity));
            await Task.Delay(duration);

            _currentDevice?.SendMessage(new MidiNoteOffMessage(0, noteNumber, velocity));
        }
        public override async void PlayElement(MusicalSymbol element)
        {
            var note = element as Note;

            if (note == null || currentMidiOutputDevice == null)
            {
                return;
            }

            var firstNoteInMeasure = element.Measure.Elements.IndexOf(note) == 0;

            var channelNumber       = GetChannelNumber(Score.Staves.IndexOf(note.Staff));
            var actualChannelNumber = (pitchesPlaying[channelNumber].Contains(note.MidiPitch)) ? channelNumber + 1 : channelNumber;

            if (!pitchesPlaying[channelNumber].Contains(note.MidiPitch))
            {
                pitchesPlaying[channelNumber].Add(note.MidiPitch);
            }
            var midiMessageToSend = new MidiNoteOnMessage((byte)actualChannelNumber, (byte)note.Pitch.MidiPitch, firstNoteInMeasure ? (byte)127 : (byte)100);

            currentMidiOutputDevice.SendMessage(midiMessageToSend);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
            Task.Delay(note.BaseDuration.ToTimeSpan(Tempo)).ContinueWith((t, o) =>
            {
                var midiOffMessage = new MidiNoteOffMessage((byte)actualChannelNumber, (byte)note.Pitch.MidiPitch, 127);
                currentMidiOutputDevice.SendMessage(midiOffMessage);
                if (pitchesPlaying[channelNumber].Contains(note.MidiPitch))
                {
                    pitchesPlaying[channelNumber].Remove(note.MidiPitch);
                }
            }, null);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
        }
예제 #5
0
        private void MVolTimer_Tick(object sender, object e)
        {
            if (!mIsInited)
            {
                return;
            }
            byte vol = mArduino.ReadVol();

            vol = (byte)(vol / 2);

            MIDIPort.SendMessage(new MidiControlChangeMessage(0, 11, vol));
        }
예제 #6
0
        private async void midiOutPortListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var deviceInformationCollection = outputDeviceWatcher.DeviceInformationCollection;

            if (deviceInformationCollection == null)
            {
                return;
            }

            DeviceInformation devInfo = deviceInformationCollection[midiOutPortListBox.SelectedIndex];

            if (devInfo == null)
            {
                return;
            }

            midiOutPort = await MidiOutPort.FromIdAsync(devInfo.Id);

            if (midiOutPort == null)
            {
                System.Diagnostics.Debug.WriteLine("Unable to create MidiOutPort from output device");
                return;
            }

            else
            {
                byte         channel           = 0;
                byte         note              = 60;
                byte         velocity          = 127;
                IMidiMessage midiMessageToSend = new MidiNoteOnMessage(channel, note, velocity);

                midiOutPort.SendMessage(midiMessageToSend);
            }
        }
예제 #7
0
        private void ResetKnob(byte controller)
        {
            byte         channel           = 10; // Seems to always be channel 10 on the X-Touch Mini? TODO: If it isn't, fix this.
            byte         controlValue      = KNOB_CENTER;
            IMidiMessage midiMessageToSend = new MidiControlChangeMessage(channel, controller, controlValue);

            midiOutPort.SendMessage(midiMessageToSend);
        }
예제 #8
0
        /// <summary>
        /// Method to enumrate all MIDI output devices connected and to setup the the first MIDI output device found.
        /// </summary>
        /// <returns></returns>
        private async Task EnumerateMidiOutputDevices()
        {
            // Create the query string for finding all MIDI output devices using MidiOutPort.GetDeviceSelector()
            string midiOutportQueryString = MidiOutPort.GetDeviceSelector();

            // Find all MIDI output devices and collect it in a DeviceInformationCollection using FindAllAsync
            DeviceInformationCollection midiOutputDevices = await DeviceInformation.FindAllAsync(midiOutportQueryString);

            // If the size of the midiOutputDevice colloction is xero,
            // set the StatusTextBlock foreground color to red and the text property to "No MIDI output devices found"
            // and return.
            // Else set the StatusTextBlock foreground color to green and the text property to midiOutputdevices[0].Name
            if (midiOutputDevices.Count == 0)
            {
                // Set the StatusTextBlock foreground color to red
                StatusTextBlock.Foreground = new SolidColorBrush(Colors.Red);

                // Set the StatusTextBlock text to "No MIDI output devices found"
                StatusTextBlock.Text = "No MIDI output devices found";
                return;
            }
            else
            {
                // Set the StatusTextBlock foreground color to green
                StatusTextBlock.Foreground = new SolidColorBrush(Colors.Green);

                // Set the StatusTextBlock text to the name of the first item in midiOutputDevices collection
                //StatusTextBlock.Text = midiOutputDevices[0].Name;
            }

            // Create an instance of DeviceInformation and set it to the first midi device in DeviceInformationCollection, midiOutputDevices
            DeviceInformation devInfo = midiOutputDevices[0];

            // Return if DeviceInformation, devInfo, is null
            if (devInfo == null)
            {
                // Set the midi status TextBlock
                StatusTextBlock.Foreground = new SolidColorBrush(Colors.Red);
                StatusTextBlock.Text       = "No device information of MIDI output";
                return;
            }

            // Set the IMidiOutPort for the output midi device by calling MidiOutPort.FromIdAsync passing the Id property of the DevicInformation
            midiOutPort = await MidiOutPort.FromIdAsync(devInfo.Id);

            // Return if midiOutPort is null
            if (midiOutPort == null)
            {
                // Set the midi status TextBlock
                StatusTextBlock.Foreground = new SolidColorBrush(Colors.Red);
                StatusTextBlock.Text       = "Unable to create MidiOutPort from output device";
                return;
            }

            // Send the Program Change midi message to port of the output midi device
            // to set the initial instrument to Acoustic Grand Piano.
            midiOutPort.SendMessage(instrumentChange);
        }
예제 #9
0
        public void Send(byte [] mevent, int offset, int length, long timestamp)
        {
            var events = Convert(mevent, offset, length, timestamp);

            foreach (var e in events)
            {
                output.SendMessage(e);
            }
        }
예제 #10
0
        // </SnippetOutPortSelectionChanged>
        private void SendMidiMessage()
        {
            // <SnippetSendMessage>
            byte         channel           = 0;
            byte         note              = 60;
            byte         velocity          = 127;
            IMidiMessage midiMessageToSend = new MidiNoteOnMessage(channel, note, velocity);

            midiOutPort.SendMessage(midiMessageToSend);
            // </SnippetSendMessage>
        }
예제 #11
0
        /// <summary>
        /// KeyTapped event passed from Keyboard object for when user taps key on screen
        /// </summary>
        /// <param name="sender">MidiNoteOnMessage containing MIDI Note of selected key</param>
        /// <param name="e"></param>
        private void KB_K_KeyTapped(object sender, RoutedEventArgs e)
        {
            // If we weren't sent a valid Key, or there's no output device selected, or we're scrolling, do nothing
            if (sender == null || midiOutPort == null || ScrollViewScrollLocked == false)
            {
                return;
            }

            // Key colour change on press handled by actual key
            midiOutPort.SendMessage((MidiNoteOnMessage)sender);
        }
        /// <summary>
        /// Sends the control change currently being composed. A control number
        /// and value must be set before sending the event.
        /// </summary>
        /// <returns>The currently selected <see cref="IMidiOutputDevice"/>.</returns>
        /// <exception cref="System.InvalidOperationException">Thrown if the control
        /// number or value have not been set yet.</exception>
        public async Task <IMidiOutputDevice> SendAsync()
        {
            if (this._controlNumber == null || this._value == null)
            {
                throw new InvalidOperationException("Both a control number and a value are required.");
            }

            IMidiOutPort port = await MidiOutPort.FromIdAsync(this._device.DeviceId);

            port.SendMessage(new MidiControlChangeMessage(this._channel, this._controlNumber.Value, this._value.Value));

            return(this._device);
        }
        /// <summary>
        /// Sends the patch change currently being composed. A patch number must be set
        /// before the sending the event.
        /// </summary>
        /// <returns>The currently selected <see cref="IMidiOutputDevice"/>.</returns>
        /// <exception cref="System.InvalidOperationException">Thrown if the control
        /// number or value have not been set yet.</exception>
        public async Task <IMidiOutputDevice> SendAsync()
        {
            if (this._patchNumber == null)
            {
                throw new InvalidOperationException("A patch number is required");
            }

            IMidiOutPort port = await MidiOutPort.FromIdAsync(this._device.DeviceId);

            port.SendMessage(new MidiProgramChangeMessage(this._channel, this._patchNumber.Value));

            return(this._device);
        }
예제 #14
0
        public void PlayMessageList(IMidiOutPort midiOutPort)
        {
            int numRows = MessageList.Count;

            for (int i = 0; i < numRows; i++)
            {
                var msg = MessageList[i];
                if (msg.Number != 0)
                {
                    var noteMessage = new MidiNoteOnMessage(msg.Channel, msg.Number, msg.Velocity);
                    midiOutPort.SendMessage(noteMessage);
                }
            }
        }
예제 #15
0
        public bool PlayCurrentColumn(IMidiOutPort midiOutPort)
        {
            var start = (CurrentColumn * _rows);
            var end   = start + _cols;

            for (int i = start; i < end; i++)
            {
                var msg = MessageBlock[i];
                if (msg.Number != 0)
                {
                    var noteMessage = new MidiNoteOnMessage(msg.Channel, msg.Number, msg.Velocity);
                    midiOutPort.SendMessage(noteMessage);
                }
            }
            CurrentColumn++;
            if (CurrentColumn >= _cols)
            {
                CurrentColumn = 0;
                return(true);
            }
            return(false);
        }
예제 #16
0
        private void MidiInPort_MessageReceived(MidiInPort sender, MidiMessageReceivedEventArgs args)
        {
            IMidiMessage receivedMidiMessage = args.Message;

            System.Diagnostics.Debug.WriteLine(receivedMidiMessage.Timestamp.ToString());

            if (receivedMidiMessage.Type == MidiMessageType.NoteOn)
            {
                System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Channel);
                System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Note);
                System.Diagnostics.Debug.WriteLine(((MidiNoteOnMessage)receivedMidiMessage).Velocity);

                byte         channel           = ((MidiNoteOnMessage)receivedMidiMessage).Channel;
                byte         note              = ((MidiNoteOnMessage)receivedMidiMessage).Note;
                byte         velocity          = ((MidiNoteOnMessage)receivedMidiMessage).Velocity;
                IMidiMessage midiMessageToSend = new MidiNoteOnMessage(channel, note, velocity);

                midiOutPort.SendMessage(midiMessageToSend);
            }
        }
예제 #17
0
        public static void vol_value(int x, int v)
        {
            IMidiMessage midiMessageToSend = new MidiControlChangeMessage((byte)x, 7, (byte)v);

            midiOutPort.SendMessage(midiMessageToSend);
        }
예제 #18
0
        /// <summary>
        /// Eventhandler for key released at the keyboard.
        /// The specific key is extracted and the according pitch is found.
        /// A MIDI message Note Off is created from the channel field and velocity field.
        /// The Note Off message is send to the MIDI output device
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Key_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            // Field to hold the pitch of the note
            byte note;

            // Extract the key being pressed
            Rectangle keyPressed = (Rectangle)sender;

            // Get the name of the key and store it in a string, keyPressedName
            string keyPressedName = keyPressed.Name;

            if (keyPressedName.Length != 4)
            {
                keyPressed.Fill = new SolidColorBrush(Color.FromArgb(220, 0, 0, 0));
            }
            else
            {
                keyPressed.Fill = new SolidColorBrush(Color.FromArgb(220, 255, 255, 255));
            }

            // Switch/Case to set the pitch depending of the key pressed
            switch (keyPressedName)
            {
            case "AKey":
                note = (byte)(60 + (octaveInterval * 12));
                break;

            case "ASharpKey":
                note = (byte)(61 + (octaveInterval * 12));
                break;

            case "BKey":
                note = (byte)(62 + (octaveInterval * 12));
                break;

            case "BSharpKey":
                note = (byte)(63 + (octaveInterval * 12));
                break;

            case "CKey":
                note = (byte)(64 + (octaveInterval * 12));
                break;

            case "CSharpKey":
                note = (byte)(65 + (octaveInterval * 12));
                break;

            case "DKey":
                note = (byte)(66 + (octaveInterval * 12));
                break;

            case "DSharpKey":
                note = (byte)(67 + (octaveInterval * 12));
                break;

            case "EKey":
                note = (byte)(68 + (octaveInterval * 12));
                break;

            case "ESharpKey":
                note = (byte)(69 + (octaveInterval * 12));
                break;

            default:
                note = (byte)(60 + (octaveInterval * 12));
                break;
            }

            // Create the Note Off message to send to the MIDI output device
            IMidiMessage midiMessageToSend = new MidiNoteOffMessage(channel, note, velocity);

            // Send the Note Off MIDI message to the midiOutPort
            midiOutPort.SendMessage(midiMessageToSend);
        }
예제 #19
0
 public void NoteOn(byte currentChannel, byte noteNumber, byte velocity)
 {
     if (midiOutPort != null)
     {
         IMidiMessage midiMessageToSend = new MidiNoteOnMessage(currentChannel, noteNumber, velocity);
         midiOutPort.SendMessage(midiMessageToSend);
     }
 }
예제 #20
0
파일: SMFPlayer.cs 프로젝트: mmitti/midi_pi
        private async void _PlayTask(CancellationToken t)
        {
            int   event_count   = 0;
            int   message_count = 0;
            uint  beat          = 0;
            uint  tick          = 0;
            ulong difftime      = 0;
            long  last_ms       = 0;
            uint  tickperbeat   = mSMF.TimeMode;

            Meter meter = new MeterEvent(0, 0, 4, 2, 0x18, 8);    //4/4
            Key   key   = new KeyEvent(0, 0, 0, 0);
            Tempo tempo = new TempoEvent(0, 0, 0x07, 0xA1, 0x20); //120


            Stopwatch s      = new Stopwatch();
            ulong     tickus = (ulong)(tempo.TempoUS / tickperbeat);

            s.Start();
            if (OnBarBeatChanged != null)
            {
                OnBarBeatChanged(0, 0);
            }
            while (true)
            {
                long em = s.ElapsedMilliseconds;
                difftime += (ulong)(em - last_ms) * 1000;
                last_ms   = em;
                if (difftime > tickus)
                {
                    tick       += (uint)(difftime / tickus);
                    mTotalTick += (uint)(difftime / tickus);
                    difftime    = difftime % tickus;
                    if (tick >= tickperbeat)
                    {
                        beat += (uint)(tick / tickperbeat);
                        tick  = (uint)(tick % tickperbeat);
                        if (OnBarBeatChanged != null)
                        {
                            OnBarBeatChanged(beat / 4, (byte)(beat % 4));
                        }
                        mBar  = (uint)(beat / 4);
                        mBeat = (byte)(beat % 4 + 1);
                    }
                    mTick = tick;
                }
                while (message_count < mSMF.MidiMessages.Count &&
                       mSMF.MidiMessages[message_count].Beat * tickperbeat + mSMF.MidiMessages[message_count].Tick < beat * tickperbeat + tick)
                {
                    mMidi.SendMessage(mSMF.MidiMessages[message_count].Message);
                    message_count++;
                }
                while (event_count < mSMF.SystemEvents.Count &&
                       mSMF.SystemEvents[event_count].Beat * tickperbeat + mSMF.SystemEvents[event_count].Tick < beat * tickperbeat + tick)
                {
                    var ev = mSMF.SystemEvents[event_count];
                    if (ev is MeterEvent)
                    {
                        meter = (MeterEvent)ev;
                    }
                    else if (ev is TempoEvent)
                    {
                        tempo  = (TempoEvent)ev;
                        tickus = (ulong)(tempo.TempoUS / tickperbeat);
                        if (OnTempoChanged != null)
                        {
                            OnTempoChanged((uint)Math.Round((double)60 * 1000 * 1000 / tempo.TempoUS));
                        }
                    }
                    else if (ev is KeyEvent)
                    {
                        key = (KeyEvent)ev;
                    }
                    else if (ev is LEDEvent)
                    {
                        if (OnLED != null)
                        {
                            OnLED(((LEDEvent)ev).LED);
                        }
                    }
                    event_count++;
                }
                if (t.IsCancellationRequested)
                {
                    //終了
                    break;
                }
            }
        }
예제 #21
0
        private void Pad1_Click(object sender, RoutedEventArgs e)
        {
            if (ValidateMidiPort() && ValidateMidiChannel())
            {
                _port.SendMessage(new MidiControlChangeMessage(GetMidiChannel(), BankSelectMsbControllerNumber, 0));
                _port.SendMessage(new MidiControlChangeMessage(GetMidiChannel(), BankSelectLsbControllerNumber, 0));
                _port.SendMessage(new MidiProgramChangeMessage(GetMidiChannel(), 0));

                //_port.SendMessage(new MidiNoteOnMessage(GetMidiChannel(), 0x24, 0));
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Invalid channel entry and/or MIDI output port not selected.");
            }
        }
예제 #22
0
        /// <summary>
        /// Create a new MIDI message based on the message type and parameter(s) values,
        /// and send it to the chosen output device
        /// </summary>
        /// <param name="sender">Element that fired the event</param>
        /// <param name="e">Event arguments</param>
        private void sendButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            IMidiMessage midiMessageToSend = null;

            switch (_currentMessageType)
            {
            case MidiMessageType.NoteOff:
                midiMessageToSend = new MidiNoteOffMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)), Convert.ToByte(GetParameterValue(parameter3)));
                break;

            case MidiMessageType.NoteOn:
                midiMessageToSend = new MidiNoteOnMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)), Convert.ToByte(GetParameterValue(parameter3)));
                break;

            case MidiMessageType.PolyphonicKeyPressure:
                midiMessageToSend = new MidiPolyphonicKeyPressureMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)), Convert.ToByte(GetParameterValue(parameter3)));
                break;

            case MidiMessageType.ControlChange:
                midiMessageToSend = new MidiControlChangeMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)), Convert.ToByte(GetParameterValue(parameter3)));
                break;

            case MidiMessageType.ProgramChange:
                midiMessageToSend = new MidiProgramChangeMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)));
                break;

            case MidiMessageType.ChannelPressure:
                midiMessageToSend = new MidiChannelPressureMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)));
                break;

            case MidiMessageType.PitchBendChange:
                midiMessageToSend = new MidiPitchBendChangeMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToUInt16(GetParameterValue(parameter2)));
                break;

            case MidiMessageType.SystemExclusive:
                var dataWriter         = new DataWriter();
                var sysExMessage       = sysExMessageContent.Text;
                var sysExMessageLength = sysExMessage.Length;

                // Do not send a blank SysEx message
                if (sysExMessageLength == 0)
                {
                    return;
                }

                // SysEx messages are two characters long with 1-character space in between them
                // So we add 1 to the message length, so that it is perfectly divisible by 3
                // The loop count tracks the number of individual message pieces
                int loopCount = (sysExMessageLength + 1) / 3;

                // Expecting a string of format "F0 NN NN NN NN.... F7", where NN is a byte in hex
                for (int i = 0; i < loopCount; i++)
                {
                    var messageString = sysExMessage.Substring(3 * i, 2);
                    var messageByte   = Convert.ToByte(messageString, 16);
                    dataWriter.WriteByte(messageByte);
                }
                midiMessageToSend = new MidiSystemExclusiveMessage(dataWriter.DetachBuffer());
                break;

            case MidiMessageType.MidiTimeCode:
                midiMessageToSend = new MidiTimeCodeMessage(Convert.ToByte(GetParameterValue(parameter1)), Convert.ToByte(GetParameterValue(parameter2)));
                break;

            case MidiMessageType.SongPositionPointer:
                midiMessageToSend = new MidiSongPositionPointerMessage(Convert.ToUInt16(GetParameterValue(parameter1)));
                break;

            case MidiMessageType.SongSelect:
                midiMessageToSend = new MidiSongSelectMessage(Convert.ToByte(GetParameterValue(parameter1)));
                break;

            case MidiMessageType.TuneRequest:
                midiMessageToSend = new MidiTuneRequestMessage();
                break;

            case MidiMessageType.TimingClock:
                midiMessageToSend = new MidiTimingClockMessage();
                break;

            case MidiMessageType.Start:
                midiMessageToSend = new MidiStartMessage();
                break;

            case MidiMessageType.Continue:
                midiMessageToSend = new MidiContinueMessage();
                break;

            case MidiMessageType.Stop:
                midiMessageToSend = new MidiStopMessage();
                break;

            case MidiMessageType.ActiveSensing:
                midiMessageToSend = new MidiActiveSensingMessage();
                break;

            case MidiMessageType.SystemReset:
                midiMessageToSend = new MidiSystemResetMessage();
                break;

            case MidiMessageType.None:
            default:
                return;
            }

            // Send the message
            _currentMidiOutputDevice.SendMessage(midiMessageToSend);
            NotifyUser("Message sent successfully");
        }