USB device stack
Dependents: blinky_max32630fthr FTHR_USB_serial FTHR_OLED HSP_RPC_GUI_3_0_1 ... more
Fork of USBDevice by
MIDIMessage.h
00001 /* Copyright (c) 2010-2011 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without 00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish, 00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 00007 * Software is furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #ifndef MIDIMESSAGE_H 00020 #define MIDIMESSAGE_H 00021 00022 #include "mbed.h" 00023 00024 #define MAX_MIDI_MESSAGE_SIZE 256 // Max message size. SysEx can be up to 65536 but 256 should be fine for most usage 00025 00026 // MIDI Message Format 00027 // 00028 // [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ] 00029 // 00030 // MIDI Data Messages (Channel Specific) 00031 // 00032 // Message msg n m 00033 // --------------------------------------------- 00034 // Note Off 0x8 Key Velocity 00035 // Note On 0x9 Key Velocity 00036 // Polyphonic Aftertouch 0xA Key Pressure 00037 // Control Change 0xB Controller Value 00038 // Program Change 0xC Program - 00039 // Channel Aftertouch 0xD Pressure - 00040 // Pitch Wheel 0xE LSB MSB 00041 00042 #define CABLE_NUM (0<<4) 00043 00044 /** A MIDI message container */ 00045 class MIDIMessage { 00046 public: 00047 MIDIMessage() : length(4) {} 00048 00049 MIDIMessage(uint8_t *buf) : length(4) { 00050 for (int i = 0; i < 4; i++) 00051 data[i] = buf[i]; 00052 } 00053 00054 // New constructor, buf is a true MIDI message (not USBMidi message) and buf_len true message length. 00055 MIDIMessage(uint8_t *buf, int buf_len) { 00056 length=buf_len+1; 00057 // first byte keeped for retro-compatibility 00058 data[0]=0; 00059 00060 for (int i = 0; i < buf_len; i++) 00061 data[i+1] = buf[i]; 00062 } 00063 00064 // create messages 00065 00066 /** Create a NoteOff message 00067 * @param key Key ID 00068 * @param velocity Key velocity (0-127, default = 127) 00069 * @param channel Key channel (0-15, default 0) 00070 * @returns A MIDIMessage 00071 */ 00072 static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) { 00073 MIDIMessage msg; 00074 msg.data[0] = CABLE_NUM | 0x08; 00075 msg.data[1] = 0x80 | (channel & 0x0F); 00076 msg.data[2] = key & 0x7F; 00077 msg.data[3] = velocity & 0x7F; 00078 return msg; 00079 } 00080 00081 /** Create a NoteOn message 00082 * @param key Key ID 00083 * @param velocity Key velocity (0-127, default = 127) 00084 * @param channel Key channel (0-15, default 0) 00085 * @returns A MIDIMessage 00086 */ 00087 static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) { 00088 MIDIMessage msg; 00089 msg.data[0] = CABLE_NUM | 0x09; 00090 msg.data[1] = 0x90 | (channel & 0x0F); 00091 msg.data[2] = key & 0x7F; 00092 msg.data[3] = velocity & 0x7F; 00093 return msg; 00094 } 00095 00096 /** Create a PolyPhonic Aftertouch message 00097 * @param key Key ID 00098 * @param pressure Aftertouch pressure (0-127) 00099 * @param channel Key channel (0-15, default 0) 00100 * @returns A MIDIMessage 00101 */ 00102 static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) { 00103 MIDIMessage msg; 00104 msg.data[0] = CABLE_NUM | 0x0A; 00105 msg.data[1] = 0xA0 | (channel & 0x0F); 00106 msg.data[2] = key & 0x7F; 00107 msg.data[3] = pressure & 0x7F; 00108 return msg; 00109 } 00110 00111 /** Create a Control Change message 00112 * @param control Controller ID 00113 * @param value Controller value (0-127) 00114 * @param channel Controller channel (0-15, default 0) 00115 * @returns A MIDIMessage 00116 */ 00117 static MIDIMessage ControlChange(int control, int value, int channel = 0) { 00118 MIDIMessage msg; 00119 msg.data[0] = CABLE_NUM | 0x0B; 00120 msg.data[1] = 0xB0 | (channel & 0x0F); 00121 msg.data[2] = control & 0x7F; 00122 msg.data[3] = value & 0x7F; 00123 return msg; 00124 } 00125 00126 /** Create a Program Change message 00127 * @param program Program ID 00128 * @param channel Channel (0-15, default 0) 00129 * @returns A MIDIMessage 00130 */ 00131 static MIDIMessage ProgramChange(int program, int channel = 0) { 00132 MIDIMessage msg; 00133 msg.data[0] = CABLE_NUM | 0x0C; 00134 msg.data[1] = 0xC0 | (channel & 0x0F); 00135 msg.data[2] = program & 0x7F; 00136 msg.data[3] = 0x00; 00137 return msg; 00138 } 00139 00140 /** Create a Channel Aftertouch message 00141 * @param pressure Pressure 00142 * @param channel Key channel (0-15, default 0) 00143 * @returns A MIDIMessage 00144 */ 00145 static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) { 00146 MIDIMessage msg; 00147 msg.data[0] = CABLE_NUM | 0x0D; 00148 msg.data[1] = 0xD0 | (channel & 0x0F); 00149 msg.data[2] = pressure & 0x7F; 00150 msg.data[3] = 0x00; 00151 return msg; 00152 } 00153 00154 /** Create a Pitch Wheel message 00155 * @param pitch Pitch (-8192 - 8191, default = 0) 00156 * @param channel Channel (0-15, default 0) 00157 * @returns A MIDIMessage 00158 */ 00159 static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) { 00160 MIDIMessage msg; 00161 int p = pitch + 8192; // 0 - 16383, 8192 is center 00162 msg.data[0] = CABLE_NUM | 0x0E; 00163 msg.data[1] = 0xE0 | (channel & 0x0F); 00164 msg.data[2] = p & 0x7F; 00165 msg.data[3] = (p >> 7) & 0x7F; 00166 return msg; 00167 } 00168 00169 /** Create an All Notes Off message 00170 * @param channel Channel (0-15, default 0) 00171 * @returns A MIDIMessage 00172 */ 00173 static MIDIMessage AllNotesOff(int channel = 0) { 00174 return ControlChange(123, 0, channel); 00175 } 00176 00177 /** Create a SysEx message 00178 * @param data SysEx data (including 0xF0 .. 0xF7) 00179 * @param len SysEx data length 00180 * @returns A MIDIMessage 00181 */ 00182 static MIDIMessage SysEx(uint8_t *data, int len) { 00183 MIDIMessage msg=MIDIMessage(data,len); 00184 return msg; 00185 } 00186 00187 // decode messages 00188 00189 /** MIDI Message Types */ 00190 enum MIDIMessageType { 00191 ErrorType, 00192 NoteOffType, 00193 NoteOnType, 00194 PolyphonicAftertouchType, 00195 ControlChangeType, 00196 ProgramChangeType, 00197 ChannelAftertouchType, 00198 PitchWheelType, 00199 AllNotesOffType, 00200 SysExType 00201 }; 00202 00203 /** Read the message type 00204 * @returns MIDIMessageType 00205 */ 00206 MIDIMessageType type() { 00207 switch((data[1] >> 4) & 0xF) { 00208 case 0x8: return NoteOffType; 00209 case 0x9: return NoteOnType; 00210 case 0xA: return PolyphonicAftertouchType; 00211 case 0xB: 00212 if(controller() < 120) { // standard controllers 00213 return ControlChangeType; 00214 } else if(controller() == 123) { 00215 return AllNotesOffType; 00216 } else { 00217 return ErrorType; // unsupported atm 00218 } 00219 case 0xC: return ProgramChangeType; 00220 case 0xD: return ChannelAftertouchType; 00221 case 0xE: return PitchWheelType; 00222 case 0xF: return SysExType; 00223 default: return ErrorType; 00224 } 00225 } 00226 00227 /** Read the channel number */ 00228 int channel() { 00229 return (data[1] & 0x0F); 00230 } 00231 00232 /** Read the key ID */ 00233 int key() { 00234 return (data[2] & 0x7F); 00235 } 00236 00237 /** Read the velocity */ 00238 int velocity() { 00239 return (data[3] & 0x7F); 00240 } 00241 00242 /** Read the controller value */ 00243 int value() { 00244 return (data[3] & 0x7F); 00245 } 00246 00247 /** Read the aftertouch pressure */ 00248 int pressure() { 00249 if(type() == PolyphonicAftertouchType) { 00250 return (data[3] & 0x7F); 00251 } else { 00252 return (data[2] & 0x7F); 00253 } 00254 } 00255 00256 /** Read the controller number */ 00257 int controller() { 00258 return (data[2] & 0x7F); 00259 } 00260 00261 /** Read the program number */ 00262 int program() { 00263 return (data[2] & 0x7F); 00264 } 00265 00266 /** Read the pitch value */ 00267 int pitch() { 00268 int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F); 00269 return p - 8192; // 0 - 16383, 8192 is center 00270 } 00271 00272 uint8_t data[MAX_MIDI_MESSAGE_SIZE+1]; 00273 uint8_t length; 00274 }; 00275 00276 #endif
Generated on Wed Jul 13 2022 12:44:03 by 1.7.2