USBDevice stack

Dependents:   erg USBSerial_HelloWorld Slingshot SuperScanner ... more

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