1 module midi2.types.structs; 2 3 /** 4 * midi2 - MIDI 2.0 implementation. 5 * 6 * midi2.types.structs: 7 * 8 * Contains Universal MIDI Packets, etc. 9 */ 10 11 public import midi2.types.enums; 12 13 /** 14 * Defines a basic Universal MIDI Packet. 15 * 16 * Extra data (64 bit and larger) are stored in separate fields. 17 * 18 * Original format is in little endian, and the current implementation is formed around that. If you 19 * need big endian support for some MCU, then you can implement it. :) 20 */ 21 struct UMP { 22 union { 23 uint base; ///Value of the UMP as a single unsigned 32 bit integer 24 ubyte[4] bytes; ///Individual bytes of the UMP's field 25 } 26 @nogc @safe nothrow pure { 27 /** 28 * Creates a UMP with two 8 bit fields. 29 */ 30 this(ubyte msgType, ubyte group, ubyte status, ubyte channel, ubyte val0 = 0, ubyte val1 = 0) { 31 bytes[0] = cast(ubyte)((msgType<<4) | (group & 0xF)); 32 bytes[1] = cast(ubyte)((status<<4) | (channel & 0xF)); 33 bytes[2] = val0; 34 bytes[3] = val1; 35 } 36 /** 37 * Creates a MIDI 1.0 compatible pitch-bend command. 38 */ 39 this(ubyte group, ubyte channel, ushort val) { 40 bytes[0] = (MessageType.MIDI1<<4) | (group & 0xF); 41 bytes[1] = (MIDI1_0Cmd.PitchBend<<4) | (channel & 0xF); 42 bytes[3] = cast(ubyte)((val>>7)&0x7F); 43 bytes[2] = cast(ubyte)(val&0x7F); 44 } 45 /** 46 * Returns the message type of the packet. 47 * 48 * This value should not be changed on the fly. 49 */ 50 ubyte msgType() const { 51 return bytes[0]>>4; 52 } 53 /** 54 * Returns the group of the packet. 55 */ 56 ubyte group() const { 57 return bytes[0] & 0xF; 58 } 59 /** 60 * Sets the group of the packet. 61 */ 62 ubyte group(ubyte val) { 63 bytes[0] &= 0xF0; 64 bytes[0] |= val & 0xF; 65 return bytes[0] & 0xF; 66 } 67 /** 68 * Returns the status value of the field, or 0 if message type hasn't defined it. 69 */ 70 ubyte status() const { 71 switch (msgType) { 72 case MessageType.MIDI2 , MessageType.MIDI1 , MessageType.Data64 , MessageType.Data128: 73 return bytes[1]>>4; 74 default: 75 return bytes[1]; 76 } 77 } 78 /** 79 * Returns the note number of this packet. 80 */ 81 ubyte note() const { 82 return bytes[2]; 83 } 84 /** 85 * Sets the note number of this packet. 86 */ 87 ubyte note(ubyte val) { 88 return bytes[2] = val; 89 } 90 alias index = note; 91 alias program = note; 92 /** 93 * Returns the value of this packet. 94 */ 95 ubyte value() const { 96 return bytes[3]; 97 } 98 /** 99 * Sets the value of this packet. 100 */ 101 ubyte value(ubyte val) { 102 return bytes[3] = val; 103 } 104 alias velocity = value; 105 /** 106 * Returns the pitch bend value of this packet. 107 */ 108 ushort bend() const { 109 return (cast(ushort)bytes[3])<<7 | bytes[2]; 110 } 111 /** 112 * Return the channel number of this packet. 113 */ 114 ubyte channel() const { 115 return bytes[1] & 0xF; 116 } 117 /** 118 * Sets the channel number of this packet. 119 */ 120 ubyte channel(ubyte val) { 121 bytes[1] &= 0xF0; 122 bytes[1] |= val & 0xF; 123 return bytes[1] & 0xF; 124 } 125 } 126 } 127 /** 128 * Defines the MIDI 2.0 note commands' data fields. 129 */ 130 struct NoteVals { 131 ushort velocity; ///Velocity of the note 132 ushort attrData; ///Attribute data 133 } 134 135 136 unittest { 137 assert(UMP.sizeof == 4); 138 assert(NoteVals.sizeof == 4); 139 140 UMP a = UMP(MessageType.MIDI2, 0x5, MIDI2_0Cmd.NoteOn, 0x3, 0x84, 0x35); 141 assert(a.msgType == MessageType.MIDI2); 142 assert(a.group == 0x5); 143 assert(a.status == MIDI2_0Cmd.NoteOn); 144 assert(a.channel == 0x3); 145 assert(a.note == 0x84); 146 assert(a.value == 0x35); 147 }