예제 #1
0
        //-- Play a note by number (0-127), specifying a velocity value (0-127)
        public void PlayNote(byte Note, byte Velocity)
        {
            byte  Msg     = 0;
            Int32 MidiMsg = default(Int32);

            if (_Engaged == false)
            {
                return;
            }
            Msg     = StuffByte(GetByte(MIDIStatusMessages.NoteOn), _OutputChannel);
            MidiMsg = StuffInt32(Msg, GetByte(Note + _Transpose), Velocity, 0);
            try
            {
                MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
                if (_NoteDuration > 0)
                {
                    NotesOff no = default(NotesOff);
                    no.Note        = GetByte(Note + _Transpose);
                    no.ShutoffTime = DateAndTime.DateAdd(DateInterval.Second, _NoteDuration, DateAndTime.Now);
                    lock (notesToTurnOff)
                    {
                        notesToTurnOff.Add(no);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
예제 #2
0
        //-- This function opens a MIDI Output port. No callback is needed
        private Int32 OpenMIDIOutPort(ref int DeviceID, bool Open)
        {
            int midiError = 0;

            if (Open == true)
            {
                //midiError = MIDI.midiOutOpen(ref hMidiOUT, DeviceID, VariantType.Null, 0, MIDI.CALLBACK_NULL);
                midiError = MIDI.midiOutOpen(ref hMidiOUT, DeviceID, (int)VariantType.Null, 0, MIDI.CALLBACK_NULL);
                if (midiError != MIDI.MMSYSERR_NOERROR)
                {
                    ThrowMidiException("midiOUT_Open", ref midiError);
                }
            }
            else
            {
                if (hMidiOUT != 0)
                {
                    midiError = MIDI.midiOutClose(hMidiOUT);
                    hMidiOUT  = 0;
                    if (midiError != MIDI.MMSYSERR_NOERROR)
                    {
                        ThrowMidiException("midiOUT_Close", ref midiError);
                    }
                }
            }
            return(hMidiOUT);
        }
예제 #3
0
        //-- Send a controller change by using an Enumeration
        public void SendControllerChange(MIDIControllers Controller, ref byte Data1, byte Data2 = 0)
        {
            int  MidiMsg       = 0;
            byte CmdAndChannel = 0;

            CmdAndChannel = StuffByte(GetByte(MIDIStatusMessages.ControllerChange), OutputChannel);
            MidiMsg       = StuffInt32(CmdAndChannel, GetByte(Controller), Data1, Data2);
            MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
        }
예제 #4
0
        //-- Send MIDI Data by specifying a message from an Enumeration
        public void SendMessage(MIDIStatusMessages Msg, ref byte Data1, byte Data2 = 0, byte Data3 = 0)
        {
            int  MidiMsg       = 0;
            byte CmdAndChannel = 0;

            CmdAndChannel = StuffByte(GetByte(Msg), OutputChannel);
            MidiMsg       = StuffInt32(CmdAndChannel, Data1, Data2, Data3);
            MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
        }
예제 #5
0
        //-- Sends MIDI Data
        public void Send(byte Channel, byte Status, byte Data1 = 0, byte Data2 = 0, byte Data3 = 0)
        {
            int  MidiMsg       = 0;
            byte CmdAndChannel = 0;

            CmdAndChannel = StuffByte(Status, Channel);
            MidiMsg       = StuffInt32(CmdAndChannel, Data1, Data2, Data3);
            MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
        }
예제 #6
0
        //-- This is called by the thread to shut off a note after it has played.
        //   Only called when NoteDuration is set to non-zero
        protected void ShutoffNoteCallback()
        {
            NotesOff no      = default(NotesOff);
            bool     there   = false;
            byte     Msg     = 0;
            Int32    MidiMsg = default(Int32);

            while (!(_Engaged == false))
            {
                lock (notesToTurnOff)
                {
                    if (notesToTurnOff.Count > 0)
                    {
                        no    = (NotesOff)notesToTurnOff[0];
                        there = true;
                    }
                    else
                    {
                        there = false;
                    }
                }

                if (there)
                {
                    while (!(DateAndTime.Now >= no.ShutoffTime))
                    {
                        System.Threading.Thread.Sleep(1);
                        if (_Engaged == false)
                        {
                            notesToTurnOff.Clear();
                            ev.Set();
                            return;
                        }
                    }
                    Msg     = StuffByte(GetByte(MIDIStatusMessages.NoteOff), _OutputChannel);
                    MidiMsg = StuffInt32(Msg, no.Note, 64, 0);
                    try
                    {
                        MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
                    }
                    catch (Exception ex)
                    {
                        break; // TODO: might not be correct. Was : Exit Do
                    }
                    lock (notesToTurnOff)
                    {
                        notesToTurnOff.RemoveAt(0);
                    }
                }
                System.Threading.Thread.Sleep(1);
            }
            notesToTurnOff.Clear();
            ev.Set();
        }
예제 #7
0
        //-- This is a private function to open and close a MIDI Input port.
        private Int32 OpenMIDIInPort(ref int DeviceID, bool Open)
        {
            int midiError = 0;

            if (Open == true)
            {
                //-- This call opens the MIDI port using a callback function (MidiInProc)
                midiError = MIDI.midiInOpen(ref hMidiIN, DeviceID, dlgMIDIIn, 0, MIDI.CALLBACK_FUNCTION);
                if (midiError != MIDI.MMSYSERR_NOERROR)
                {
                    ThrowMidiException("midiIN_Open", ref midiError);
                }
                else
                {
                    midiError = MIDI.midiInStart(hMidiIN);
                    if (midiError != MIDI.MMSYSERR_NOERROR)
                    {
                        ThrowMidiException("midiIN_Start", ref midiError);
                    }
                }
            }
            else
            {
                if (hMidiIN != 0)
                {
                    midiError = MIDI.midiInStop(hMidiIN);
                    if (midiError != MIDI.MMSYSERR_NOERROR)
                    {
                        ThrowMidiException("midiIN_Start", ref midiError);
                    }
                    else
                    {
                        midiError = MIDI.midiInClose(hMidiIN);
                        if (midiError != MIDI.MMSYSERR_NOERROR)
                        {
                            ThrowMidiException("midiIN_Close", ref midiError);
                        }
                        else
                        {
                            hMidiIN = 0;
                        }
                    }
                }
            }
            return(hMidiIN);
        }
예제 #8
0
        //-- Turn off all notes currently playing
        public void AllNotesOff()
        {
            byte  Msg     = 0;
            Int32 MidiMsg = default(Int32);

            if (_Engaged == false)
            {
                return;
            }
            try
            {
                Msg     = StuffByte(GetByte(MIDIStatusMessages.ChannelModeMessage), _OutputChannel);
                MidiMsg = StuffInt32(Msg, 0x7b, 0, 0);
                MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
예제 #9
0
        //-- Return a list of output device names as a string array
        public static string[] OutDeviceNames()
        {
            int num = 0;
            int i   = 0;

            MIDI.MIDIOUTCAPS Caps  = default(MIDI.MIDIOUTCAPS);
            string[]         names = null;

            num = MIDI.midiOutGetNumDevs();
            if (num > 0)
            {
                names = new string[num];
                for (i = 0; i <= num - 1; i++)
                {
                    MIDI.midiOutGetDevCaps(i, ref Caps, Strings.Len(Caps));
                    names[i] = Caps.szPname;
                }
            }
            return(names);
        }
예제 #10
0
        //-- Stop playing a note by passing the note number (0-127) and optionally velocity (0-127)
        public void StopNote(byte Note, byte Velocity = 64)
        {
            byte Msg = 0;

            Int32 MidiMsg = default(Int32);

            if (_Engaged == false)
            {
                return;
            }
            Msg     = StuffByte(GetByte(MIDIStatusMessages.NoteOff), _OutputChannel);
            MidiMsg = StuffInt32(Msg, GetByte(Note + _Transpose), Velocity, 0);
            try
            {
                MIDI.midiOutShortMsg(hMidiOUT, MidiMsg);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
예제 #11
0
        //-- This is the Input proc that gets called when MIDI Data is received from the
        //   input device.
        protected void MidiInProc(Int32 MidiInHandle, Int32 NewMsg, Int32 Instance, Int32 wParam, Int32 lParam)
        {
            byte chan       = 0;
            byte Msg        = 0;
            byte Status     = 0;
            byte Data1      = 0;
            byte Data2      = 0;
            byte Data3      = 0;
            int  MidiStatus = 0;
            bool Cancel     = false;

            //-- We're only interested in MIDI Data messages
            if (NewMsg == MIDI.MM_MIM_DATA)
            {
                //-- Parse the data into a message byte and three data bytes
                SplitInt32(wParam, ref Msg, ref Data1, ref Data2, ref Data3);
                //-- The message byte is a combination of the channel and a Status byte. Parse
                SplitByte(Msg, ref chan, ref Status);

                Trace.WriteLine(" In: " + chan.ToString() + " " + Status.ToString() + " " + Data1.ToString() + " " + Data2.ToString() + " " + Data3.ToString());

                //-- Is this coming in on our Input Channel?

                if (chan == _InputChannel)
                {
                    //-- What MIDI Command was sent?
                    switch (Status)
                    {
                    case MIDI.NOTE_ON:
                    case MIDI.NOTE_OFF:
                        //-- Transpose the note
                        Int32 DTest = Convert.ToInt32(Data1) + Transpose;
                        if (DTest < 0)
                        {
                            DTest = 0;
                        }
                        else if (DTest > 127)
                        {
                            DTest = 127;
                        }
                        Data1 = GetByte(DTest);
                        //-- No output device?
                        if (hMidiOUT == 0)
                        {
                            //-- Fire the appropriate event
                            if (Status == MIDI.NOTE_ON)
                            {
                                if (NoteOn != null)
                                {
                                    NoteOn(ref chan, ref Data1, ref Data2, ref Cancel);
                                }
                            }
                            else if (Status == MIDI.NOTE_OFF)
                            {
                                if (NoteOff != null)
                                {
                                    NoteOff(ref chan, ref Data1, ref Data2, ref Cancel);
                                }
                            }
                        }
                        else
                        {
                            //-- Change the channel to the output channel
                            chan = _OutputChannel;
                        }
                        break;

                    case MIDI.CHANNEL_PRESSURE:
                        //-- Channel Pressure
                        if (FilterAfterTouch == true)
                        {
                            //-- Cancel this data
                            Cancel = true;
                        }
                        else if (hMidiOUT == 0)
                        {
                            //-- No output device. Fire the Receive event
                            if (Receive != null)
                            {
                                Receive(ref chan, ref Status, ref Data1, ref Data2, ref Data3);
                            }
                        }
                        else
                        {
                            //-- Change the channel to the output channel
                            chan = _OutputChannel;
                        }
                        break;

                    default:
                        if (hMidiOUT == 0)
                        {
                            //-- No output device. Fire the Receive event
                            if (Receive != null)
                            {
                                Receive(ref chan, ref Status, ref Data1, ref Data2, ref Data3);
                            }
                        }
                        else
                        {
                            //-- Change the channel to the output channel
                            chan = _OutputChannel;
                        }
                        break;
                    }
                }

                //-- Prepare the message
                NewMsg = StuffByte(Status, chan);
                lParam = StuffInt32(Convert.ToByte(NewMsg), Data1, Data2, Data3);

                //-- The programmer can set Cancel to true to cancel this note.
                if (Cancel == false)
                {
                    if (hMidiOUT != 0)
                    {
                        //-- We have an output device!
                        Trace.WriteLine("Out: " + chan.ToString() + " " + Status.ToString() + " " + Data1.ToString() + " " + Data2.ToString() + " " + Data3.ToString() + " lParam=" + lParam.ToString());
                        //-- Send the MIDI data out the output device
                        MIDI.midiOutShortMsg(hMidiOUT, lParam);
                    }
                }
            }
        }
예제 #12
0
        //-- Code to get the last MIDI message and throw as an exception
        private void ThrowMidiException(string InFunct, ref Int32 MMErr)
        {
            string Msg = Strings.Space(255);

            if (Strings.InStr(1, InFunct, "out", CompareMethod.Text) == 0)
            {
                MIDI.midiInGetErrorText(MMErr, Msg, 255);
            }
            else
            {
                MIDI.midiOutGetErrorText(MMErr, Msg, 255);
            }
            Msg = InFunct + Constants.vbCrLf + Msg + Constants.vbCrLf;
            switch (MMErr)
            {
            case MIDI.MMSYSERR_NOERROR:
                Msg = Msg + "no error";
                break;

            case MIDI.MMSYSERR_ERROR:
                Msg = Msg + "unspecified error";
                break;

            case MIDI.MMSYSERR_BADDEVICEID:
                Msg = Msg + "device ID out of range";
                break;

            case MIDI.MMSYSERR_NOTENABLED:
                Msg = Msg + "driver failed enable";
                break;

            case MIDI.MMSYSERR_ALLOCATED:
                Msg = Msg + "device already allocated";
                break;

            case MIDI.MMSYSERR_INVALHANDLE:
                Msg = Msg + "device handle is invalid";
                break;

            case MIDI.MMSYSERR_NODRIVER:
                Msg = Msg + "no device driver present";
                break;

            case MIDI.MMSYSERR_NOMEM:
                Msg = Msg + "memory allocation error";
                break;

            case MIDI.MMSYSERR_NOTSUPPORTED:
                Msg = Msg + "function isn't supported";
                break;

            case MIDI.MMSYSERR_BADERRNUM:
                Msg = Msg + "error value out of range";
                break;

            case MIDI.MMSYSERR_INVALFLAG:
                Msg = Msg + "invalid flag passed";
                break;

            case MIDI.MMSYSERR_INVALPARAM:
                Msg = Msg + "invalid parameter passed";
                break;

            case MIDI.MMSYSERR_HANDLEBUSY:
                Msg = Msg + "handle being used simultaneously on another thread (eg callback)";
                break;

            case MIDI.MMSYSERR_INVALIDALIAS:
                Msg = Msg + "Specified alias not found in WIN.INI";
                break;
                //case MIDI.MMSYSERR_LASTERROR:
                //    Msg = Msg + "last error in range";
                //    break;
            }
            throw new Exception(Msg);
        }