USB device stack, fixes for USBSerial & KL25Z

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MIDIMessage.h Source File

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 // MIDI Message Format
00025 // 
00026 // [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
00027 //
00028 // MIDI Data Messages (Channel Specific)
00029 //
00030 // Message               msg n          m
00031 // ---------------------------------------------
00032 // Note Off              0x8 Key        Velocity
00033 // Note On               0x9 Key        Velocity
00034 // Polyphonic Aftertouch 0xA Key        Pressure
00035 // Control Change        0xB Controller Value
00036 // Program Change        0xC Program    -
00037 // Channel Aftertouch    0xD Pressure   -
00038 // Pitch Wheel           0xE LSB        MSB
00039 
00040 #define CABLE_NUM (0<<4)
00041 
00042 /** A MIDI message container */
00043 class MIDIMessage {
00044 public:
00045     MIDIMessage() {}
00046     
00047     MIDIMessage(uint8_t *buf) {
00048         for (int i = 0; i < 4; i++)
00049             data[i] = buf[i];
00050     }
00051     
00052     // create messages
00053     
00054     /** Create a NoteOff message 
00055      * @param key Key ID
00056      * @param velocity Key velocity (0-127, default = 127)
00057      * @param channel Key channel (0-15, default 0)
00058      * @returns A MIDIMessage
00059      */
00060     static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
00061         MIDIMessage msg;
00062         msg.data[0] = CABLE_NUM | 0x08;
00063         msg.data[1] = 0x80 | (channel & 0x0F);
00064         msg.data[2] = key & 0x7F;
00065         msg.data[3] = velocity & 0x7F; 
00066         return msg;
00067     }
00068     
00069     /** Create a NoteOn message 
00070      * @param key Key ID
00071      * @param velocity Key velocity (0-127, default = 127)
00072      * @param channel Key channel (0-15, default 0)
00073      * @returns A MIDIMessage
00074      */
00075     static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
00076         MIDIMessage msg;
00077         msg.data[0] = CABLE_NUM | 0x09;
00078         msg.data[1] = 0x90 | (channel & 0x0F);
00079         msg.data[2] = key & 0x7F;
00080         msg.data[3] = velocity & 0x7F;                 
00081         return msg;
00082     }
00083     
00084     /** Create a PolyPhonic Aftertouch message 
00085      * @param key Key ID
00086      * @param pressure Aftertouch pressure (0-127)
00087      * @param channel Key channel (0-15, default 0)
00088      * @returns A MIDIMessage
00089      */    
00090     static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
00091         MIDIMessage msg;
00092         msg.data[0] = CABLE_NUM | 0x0A;
00093         msg.data[1] = 0xA0 | (channel & 0x0F);
00094         msg.data[2] = key & 0x7F;
00095         msg.data[3] = pressure & 0x7F;         
00096         return msg;
00097     }
00098     
00099     /** Create a Control Change message 
00100      * @param control Controller ID
00101      * @param value Controller value (0-127)
00102      * @param channel Controller channel (0-15, default 0)
00103      * @returns A MIDIMessage
00104      */
00105     static MIDIMessage ControlChange(int control, int value, int channel = 0) {
00106         MIDIMessage msg;
00107         msg.data[0] = CABLE_NUM | 0x0B;
00108         msg.data[1] = 0xB0 | (channel & 0x0F);
00109         msg.data[2] = control & 0x7F;
00110         msg.data[3] = value & 0x7F;         
00111         return msg;
00112     }
00113     
00114     /** Create a Program Change message 
00115      * @param program Program ID
00116      * @param channel Channel (0-15, default 0)
00117      * @returns A MIDIMessage
00118      */    
00119     static MIDIMessage ProgramChange(int program, int channel = 0) {
00120         MIDIMessage msg;
00121         msg.data[0] = CABLE_NUM | 0x0C;
00122         msg.data[1] = 0xC0 | (channel & 0x0F);
00123         msg.data[2] = program & 0x7F;
00124         msg.data[3] = 0x00;         
00125         return msg;
00126     }
00127     
00128     /** Create a Channel Aftertouch message 
00129      * @param pressure Pressure 
00130      * @param channel Key channel (0-15, default 0)
00131      * @returns A MIDIMessage
00132      */    
00133     static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
00134         MIDIMessage msg;
00135         msg.data[0] = CABLE_NUM | 0x0D;
00136         msg.data[1] = 0xD0 | (channel & 0x0F);
00137         msg.data[2] = pressure & 0x7F;
00138         msg.data[3] = 0x00;         
00139         return msg;
00140     }
00141     
00142     /** Create a Pitch Wheel message 
00143      * @param pitch Pitch (-8192 - 8191, default = 0)
00144      * @param channel Channel (0-15, default 0)
00145      * @returns A MIDIMessage
00146      */    
00147     static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
00148         MIDIMessage msg;
00149         int p = pitch + 8192;    // 0 - 16383, 8192 is center
00150         msg.data[0] = CABLE_NUM | 0x0E;
00151         msg.data[1] = 0xE0 | (channel & 0x0F);
00152         msg.data[2] = p & 0x7F;
00153         msg.data[3] = (p >> 7) & 0x7F;                 
00154         return msg;
00155     }
00156     
00157     /** Create an All Notes Off message 
00158      * @param channel Channel (0-15, default 0)
00159      * @returns A MIDIMessage
00160      */    
00161     static MIDIMessage AllNotesOff(int channel = 0) {
00162         return ControlChange(123, 0, channel);
00163     }
00164     
00165     // decode messages
00166     
00167     /** MIDI Message Types */
00168     enum MIDIMessageType {
00169         ErrorType,
00170         NoteOffType,
00171         NoteOnType,
00172         PolyphonicAftertouchType,
00173         ControlChangeType,
00174         ProgramChangeType,
00175         ChannelAftertouchType,
00176         PitchWheelType,
00177         AllNotesOffType
00178     };
00179     
00180     /** Read the message type
00181      * @returns MIDIMessageType
00182      */    
00183     MIDIMessageType type() {
00184         switch((data[1] >> 4) & 0xF) {
00185             case 0x8: return NoteOffType;
00186             case 0x9: return NoteOnType;
00187             case 0xA: return PolyphonicAftertouchType;
00188             case 0xB: 
00189                 if(controller() < 120) { // standard controllers
00190                     return ControlChangeType;
00191                 } else if(controller() == 123) {
00192                     return AllNotesOffType;
00193                 } else {
00194                     return ErrorType; // unsupported atm
00195                 }
00196             case 0xC: return ProgramChangeType;
00197             case 0xD: return ChannelAftertouchType;
00198             case 0xE: return PitchWheelType;
00199             default: return ErrorType;
00200         }
00201     }
00202 
00203     /** Read the channel number */    
00204     int channel() {
00205         return (data[1] & 0x0F);
00206     }
00207     
00208     /** Read the key ID */    
00209     int key() {
00210         return (data[2] & 0x7F);        
00211     }
00212         
00213     /** Read the velocity */    
00214     int velocity() {
00215         return (data[3] & 0x7F);        
00216     }
00217 
00218     /** Read the controller value */    
00219     int value() {
00220         return (data[3] & 0x7F);        
00221     }
00222     
00223     /** Read the aftertouch pressure */        
00224     int pressure() {
00225         if(type() == PolyphonicAftertouchType) {
00226             return (data[3] & 0x7F);        
00227         } else {
00228             return (data[2] & 0x7F);        
00229         }
00230     }
00231 
00232     /** Read the controller number */    
00233     int controller() {
00234         return (data[2] & 0x7F);        
00235     }
00236 
00237     /** Read the program number */    
00238     int program() {
00239         return (data[2] & 0x7F);        
00240     }
00241     
00242     /** Read the pitch value */        
00243     int pitch() {
00244         int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
00245         return p - 8192; // 0 - 16383, 8192 is center
00246     }
00247     
00248     uint8_t data[4];
00249 };
00250 
00251 #endif