USB device stack - modified

Dependents:   shaun_larada

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