Beispiel #1
0
        private void Send(MidiEvent m)
        {
            var size = MidiEvent.FixedDataSize(m.StatusByte);

            buffer[0] = m.StatusByte;
            buffer[1] = m.Msb;
            buffer[2] = m.Lsb;
            _device.Send(buffer, 0, size + 1, 0);
        }
Beispiel #2
0
 public void GetFixedSize()
 {
     Assert.AreEqual(2, MidiEvent.FixedDataSize(0x90), "NoteOn");
     Assert.AreEqual(1, MidiEvent.FixedDataSize(0xC0), "ProgramChange");
     Assert.AreEqual(1, MidiEvent.FixedDataSize(0xD0), "CAf");
     Assert.AreEqual(2, MidiEvent.FixedDataSize(0xA0), "PAf");
     Assert.AreEqual(0, MidiEvent.FixedDataSize(0xF0), "SysEx");
     Assert.AreEqual(2, MidiEvent.FixedDataSize(0xF2), "SongPositionPointer");
     Assert.AreEqual(1, MidiEvent.FixedDataSize(0xF3), "SongSelect");
     Assert.AreEqual(0, MidiEvent.FixedDataSize(0xF8), "MidiClock");
     Assert.AreEqual(0, MidiEvent.FixedDataSize(0xFF), "META");
 }
        private void HandleMidiData(IntPtr dwParam1, IntPtr dwParam2)
        {
            if (MidiEventReceived == null)
            {
                return;
            }
            byte status = (byte)((uint)dwParam1 & 0xFF);
            byte msb    = (byte)(((uint)dwParam1 & 0xFF00) >> 8);
            byte lsb    = (byte)(((uint)dwParam1 & 0xFF0000) >> 16);
            byte size   = MidiEvent.FixedDataSize(status);

            MidiEventReceived?.Invoke(this, new MidiEventReceivedEventArgs(new MidiEvent(status, msb, lsb, (long)dwParam2)));
        }
        void HandleData(IntPtr param1, IntPtr param2)
        {
            var status = (byte)((int)param1 & 0xFF);
            var msb    = (byte)(((int)param1 & 0xFF00) >> 8);
            var lsb    = (byte)(((int)param1 & 0xFF0000) >> 16);
            var data   = MidiEvent.FixedDataSize(status) == 2 ? data3b : data2b;

            data[0] = status;
            data[1] = msb;
            if (data.Length == 3)
            {
                data[2] = lsb;
            }

            MessageReceived(this, new MidiReceivedEventArgs()
            {
                Data = data, Start = 0, Length = data.Length, Timestamp = (long)param2
            });
        }
 // How does it dispatch SYSEX mesasges...
 void HandleMidiInProc(IntPtr midiIn, uint msg, ref int instance, ref int param1, ref int param2)
 {
     if (MessageReceived != null)
     {
         var status = (byte)(param1 & 0xFF);
         var msb    = (byte)((param1 & 0xFF00) >> 8);
         var lsb    = (byte)((param1 & 0xFF0000) >> 16);
         var data   = MidiEvent.FixedDataSize(status) == 3 ? data3b : data2b;
         data[0] = status;
         data[1] = msb;
         if (data.Length == 3)
         {
             data[2] = lsb;
         }
         MessageReceived(this, new MidiReceivedEventArgs()
         {
             Data = data, Timestamp = 0
         });
     }
 }
Beispiel #6
0
        /// <remarks>
        /// This function is not intended to provide complete correctness of MIDI parsing.
        /// For now the goal is to correctly parse "note start" and "note end" events and correctly delimit all events.
        /// </remarks>
        private void readEvent(byte[] data, string senderId, ref int i, out byte eventType, out byte key, out byte velocity)
        {
            byte statusType = data[i++];

            // continuation messages:
            // need running status to be interpreted correctly
            if (statusType <= 0x7F)
            {
                if (!runningStatus.ContainsKey(senderId))
                {
                    throw new InvalidDataException($"Received running status of sender {senderId}, but no event type was stored");
                }

                eventType = runningStatus[senderId];
                key       = statusType;
                velocity  = data[i++];
                return;
            }

            // real-time messages:
            // 0 additional data bytes always, do not reset running status
            if (statusType >= 0xF8)
            {
                eventType = statusType;
                key       = velocity = 0;
                return;
            }

            // system common messages:
            // variable number of additional data bytes, reset running status
            if (statusType >= 0xF0)
            {
                eventType = statusType;

                // system exclusive message
                // vendor-specific, terminated by 0xF7
                // ignoring their whole contents for now since we can't do anything with them anyway
                if (statusType == 0xF0)
                {
                    while (data[i - 1] != 0xF7)
                    {
                        i++;
                    }

                    key = velocity = 0;
                }
                // other common system messages
                // fixed size given by MidiEvent.FixedDataSize
                else
                {
                    key      = MidiEvent.FixedDataSize(statusType) >= 1 ? data[i++] : (byte)0;
                    velocity = MidiEvent.FixedDataSize(statusType) == 2 ? data[i++] : (byte)0;
                }

                runningStatus.Remove(senderId);
                return;
            }

            // channel messages
            // fixed size (varying per event type), set running status
            eventType = statusType;
            key       = MidiEvent.FixedDataSize(statusType) >= 1 ? data[i++] : (byte)0;
            velocity  = MidiEvent.FixedDataSize(statusType) == 2 ? data[i++] : (byte)0;

            runningStatus[senderId] = eventType;
        }
Beispiel #7
0
        IEnumerable <IMidiMessage> Convert(byte[] mevent, int offset, int length, long timestamp)
        {
            int end = offset + length;

            for (int i = offset; i < end;)
            {
                switch (mevent[i] & 0xF0)
                {
                case MidiEvent.NoteOn:
                    if (i + 3 < end)
                    {
                        yield return(new MidiNoteOnMessage((byte)(mevent[i] & 0x7F), mevent[i + 1], mevent[i + 2]));
                    }
                    break;

                case MidiEvent.NoteOff:
                    if (i + 3 < end)
                    {
                        yield return(new MidiNoteOffMessage((byte)(mevent[i] & 0x7F), mevent[i + 1],
                                                            mevent[i + 2]));
                    }
                    break;

                case MidiEvent.PAf:
                    if (i + 3 < end)
                    {
                        yield return(new MidiPolyphonicKeyPressureMessage((byte)(mevent[i] & 0x7F), mevent[i + 1],
                                                                          mevent[i + 2]));
                    }
                    break;

                case MidiEvent.CC:
                    if (i + 3 < end)
                    {
                        yield return(new MidiControlChangeMessage((byte)(mevent[i] & 0x7F), mevent[i + 1],
                                                                  mevent[i + 2]));
                    }
                    break;

                case MidiEvent.Program:
                    if (i + 2 < end)
                    {
                        yield return(new MidiProgramChangeMessage((byte)(mevent[i] & 0x7F), mevent[i + 1]));
                    }
                    break;

                case MidiEvent.CAf:
                    if (i + 2 < end)
                    {
                        yield return(new MidiChannelPressureMessage((byte)(mevent[i] & 0x7F), mevent[i + 1]));
                    }
                    break;

                case MidiEvent.Pitch:
                    if (i + 3 < end)
                    {
                        yield return(new MidiPitchBendChangeMessage((byte)(mevent[i] & 0x7F),
                                                                    (ushort)((mevent[i + 1] << 13) + mevent[i + 2])));
                    }
                    break;

                case MidiEvent.SysEx1:
                    int pos = Array.IndexOf(mevent, MidiEvent.EndSysEx, i, length - i);
                    if (pos >= 0)
                    {
                        yield return(new MidiSystemExclusiveMessage(new Buffer(mevent, i, pos - i)));
                    }
                    break;

                default:
                    throw new NotSupportedException(
                              $"MIDI message byte '{mevent[i].ToString("X02")}' is not supported.");
                }

                if (mevent[i] != MidiEvent.SysEx1)
                {
                    i += MidiEvent.FixedDataSize(mevent[i]);
                }
            }
        }
Beispiel #8
0
        public override void Send(byte[] mevent, int offset, int length, long timestamp)
        {
            int end = offset + length;

            for (int i = offset; i < end;)
            {
                switch (mevent[i] & 0xF0)
                {
                case MidiEvent.ActiveSense:
                    break;

                case MidiEvent.NoteOn:
                    if (i + 2 < end)
                    {
                        _sampler.StartNote(mevent[i + 1], mevent[i + 2], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.NoteOff:
                    if (i + 2 < end)
                    {
                        _sampler.StopNote(mevent[i + 1], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.PAf:
                    if (i + 2 < end)
                    {
                        _sampler.SendPressureForKey(mevent[i + 1], mevent[i + 2], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.CC:
                    if (i + 2 < end)
                    {
                        _sampler.SendController(mevent[i + 1], mevent[i + 2], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.Program:
                    if (i + 2 < end)
                    {
                        _sampler.SendProgramChange(mevent[i + 1], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.CAf:
                    if (i + 2 < end)
                    {
                        _sampler.SendPressure(mevent[i + 1], (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.Pitch:
                    if (i + 2 < end)
                    {
                        _sampler.SendPitchBend((ushort)((mevent[i + 1] << 13) + mevent[i + 2]), (byte)(mevent[i] & 0x0f));
                    }
                    break;

                case MidiEvent.SysEx1:
                    int pos = Array.IndexOf(mevent, MidiEvent.EndSysEx, i, length - i);
                    if (pos >= 0)
                    {
                        pos++;
                        byte[] message = new byte[pos - i];
                        Array.Copy(mevent, i, message, 0, pos - i);
                        _sampler.SendMidiSysExEvent(NSData.FromArray(message));
                        i = pos;
                    }
                    break;

                default:
                    throw new NotSupportedException($"MIDI message byte '{mevent[i].ToString("X02")}' is not supported.");
                }
                if (mevent[i] != MidiEvent.SysEx1)
                {
                    i += MidiEvent.FixedDataSize(mevent[i]) + 1;
                }
            }
        }