Dependencies:   ChaNFSSD mbed ChaNFS

Committer:
okini3939
Date:
Thu Nov 10 03:20:42 2011 +0000
Revision:
1:efbcfbae4747
Parent:
0:02c293160df3

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:02c293160df3 1 /* @license The MIT License
okini3939 0:02c293160df3 2 * Copyright (c) 2011 mux, simon
okini3939 0:02c293160df3 3 *
okini3939 0:02c293160df3 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
okini3939 0:02c293160df3 5 * of this software and associated documentation files (the "Software"), to deal
okini3939 0:02c293160df3 6 * in the Software without restriction, including without limitation the rights
okini3939 0:02c293160df3 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
okini3939 0:02c293160df3 8 * copies of the Software, and to permit persons to whom the Software is
okini3939 0:02c293160df3 9 * furnished to do so, subject to the following conditions:
okini3939 0:02c293160df3 10 *
okini3939 0:02c293160df3 11 * The above copyright notice and this permission notice shall be included in
okini3939 0:02c293160df3 12 * all copies or substantial portions of the Software.
okini3939 0:02c293160df3 13 *
okini3939 0:02c293160df3 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
okini3939 0:02c293160df3 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
okini3939 0:02c293160df3 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
okini3939 0:02c293160df3 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
okini3939 0:02c293160df3 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
okini3939 0:02c293160df3 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
okini3939 0:02c293160df3 20 * THE SOFTWARE.
okini3939 0:02c293160df3 21 */
okini3939 0:02c293160df3 22
okini3939 0:02c293160df3 23 #ifndef MIDIMESSAGE_H
okini3939 0:02c293160df3 24 #define MIDIMESSAGE_H
okini3939 0:02c293160df3 25
okini3939 0:02c293160df3 26 #include "mbed.h"
okini3939 0:02c293160df3 27
okini3939 0:02c293160df3 28 // MIDI Message Format
okini3939 0:02c293160df3 29 //
okini3939 0:02c293160df3 30 // [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
okini3939 0:02c293160df3 31 //
okini3939 0:02c293160df3 32 // MIDI Data Messages (Channel Specific)
okini3939 0:02c293160df3 33 //
okini3939 0:02c293160df3 34 // Message msg n m
okini3939 0:02c293160df3 35 // ---------------------------------------------
okini3939 0:02c293160df3 36 // Note Off 0x8 Key Velocity
okini3939 0:02c293160df3 37 // Note On 0x9 Key Velocity
okini3939 0:02c293160df3 38 // Polyphonic Aftertouch 0xA Key Pressure
okini3939 0:02c293160df3 39 // Control Change 0xB Controller Value
okini3939 0:02c293160df3 40 // Program Change 0xC Program -
okini3939 0:02c293160df3 41 // Channel Aftertouch 0xD Pressure -
okini3939 0:02c293160df3 42 // Pitch Wheel 0xE LSB MSB
okini3939 0:02c293160df3 43
okini3939 0:02c293160df3 44 #define CABLE_NUM (0<<4)
okini3939 0:02c293160df3 45
okini3939 0:02c293160df3 46 /** A MIDI message container */
okini3939 0:02c293160df3 47 class MIDIMessage {
okini3939 0:02c293160df3 48 public:
okini3939 0:02c293160df3 49 MIDIMessage() {}
okini3939 0:02c293160df3 50
okini3939 0:02c293160df3 51 MIDIMessage(uint8_t *buf) {
okini3939 0:02c293160df3 52 *((uint32_t *)data) = *((uint32_t *)buf);
okini3939 0:02c293160df3 53 }
okini3939 0:02c293160df3 54
okini3939 0:02c293160df3 55 // create messages
okini3939 0:02c293160df3 56
okini3939 0:02c293160df3 57 /** Create a NoteOff message
okini3939 0:02c293160df3 58 * @param key Key ID
okini3939 0:02c293160df3 59 * @param velocity Key velocity (0-127, default = 127)
okini3939 0:02c293160df3 60 * @param channel Key channel (0-15, default 0)
okini3939 0:02c293160df3 61 * @returns A MIDIMessage
okini3939 0:02c293160df3 62 */
okini3939 0:02c293160df3 63 static MIDIMessage NoteOff(int key, int velocity = 127, int channel = 0) {
okini3939 0:02c293160df3 64 MIDIMessage msg;
okini3939 0:02c293160df3 65 msg.data[0] = CABLE_NUM | 0x08;
okini3939 0:02c293160df3 66 msg.data[1] = 0x80 | (channel & 0x0F);
okini3939 0:02c293160df3 67 msg.data[2] = key & 0x7F;
okini3939 0:02c293160df3 68 msg.data[3] = velocity & 0x7F;
okini3939 0:02c293160df3 69 return msg;
okini3939 0:02c293160df3 70 }
okini3939 0:02c293160df3 71
okini3939 0:02c293160df3 72 /** Create a NoteOn message
okini3939 0:02c293160df3 73 * @param key Key ID
okini3939 0:02c293160df3 74 * @param velocity Key velocity (0-127, default = 127)
okini3939 0:02c293160df3 75 * @param channel Key channel (0-15, default 0)
okini3939 0:02c293160df3 76 * @returns A MIDIMessage
okini3939 0:02c293160df3 77 */
okini3939 0:02c293160df3 78 static MIDIMessage NoteOn(int key, int velocity = 127, int channel = 0) {
okini3939 0:02c293160df3 79 MIDIMessage msg;
okini3939 0:02c293160df3 80 msg.data[0] = CABLE_NUM | 0x09;
okini3939 0:02c293160df3 81 msg.data[1] = 0x90 | (channel & 0x0F);
okini3939 0:02c293160df3 82 msg.data[2] = key & 0x7F;
okini3939 0:02c293160df3 83 msg.data[3] = velocity & 0x7F;
okini3939 0:02c293160df3 84 return msg;
okini3939 0:02c293160df3 85 }
okini3939 0:02c293160df3 86
okini3939 0:02c293160df3 87 /** Create a PolyPhonic Aftertouch message
okini3939 0:02c293160df3 88 * @param key Key ID
okini3939 0:02c293160df3 89 * @param pressure Aftertouch pressure (0-127)
okini3939 0:02c293160df3 90 * @param channel Key channel (0-15, default 0)
okini3939 0:02c293160df3 91 * @returns A MIDIMessage
okini3939 0:02c293160df3 92 */
okini3939 0:02c293160df3 93 static MIDIMessage PolyphonicAftertouch(int key, int pressure, int channel = 0) {
okini3939 0:02c293160df3 94 MIDIMessage msg;
okini3939 0:02c293160df3 95 msg.data[0] = CABLE_NUM | 0x0A;
okini3939 0:02c293160df3 96 msg.data[1] = 0xA0 | (channel & 0x0F);
okini3939 0:02c293160df3 97 msg.data[2] = key & 0x7F;
okini3939 0:02c293160df3 98 msg.data[3] = pressure & 0x7F;
okini3939 0:02c293160df3 99 return msg;
okini3939 0:02c293160df3 100 }
okini3939 0:02c293160df3 101
okini3939 0:02c293160df3 102 /** Create a Control Change message
okini3939 0:02c293160df3 103 * @param control Controller ID
okini3939 0:02c293160df3 104 * @param value Controller value (0-127)
okini3939 0:02c293160df3 105 * @param channel Controller channel (0-15, default 0)
okini3939 0:02c293160df3 106 * @returns A MIDIMessage
okini3939 0:02c293160df3 107 */
okini3939 0:02c293160df3 108 static MIDIMessage ControlChange(int control, int value, int channel = 0) {
okini3939 0:02c293160df3 109 MIDIMessage msg;
okini3939 0:02c293160df3 110 msg.data[0] = CABLE_NUM | 0x0B;
okini3939 0:02c293160df3 111 msg.data[1] = 0xB0 | (channel & 0x0F);
okini3939 0:02c293160df3 112 msg.data[2] = control & 0x7F;
okini3939 0:02c293160df3 113 msg.data[3] = value & 0x7F;
okini3939 0:02c293160df3 114 return msg;
okini3939 0:02c293160df3 115 }
okini3939 0:02c293160df3 116
okini3939 0:02c293160df3 117 /** Create a Program Change message
okini3939 0:02c293160df3 118 * @param program Program ID
okini3939 0:02c293160df3 119 * @param channel Channel (0-15, default 0)
okini3939 0:02c293160df3 120 * @returns A MIDIMessage
okini3939 0:02c293160df3 121 */
okini3939 0:02c293160df3 122 static MIDIMessage ProgramChange(int program, int channel = 0) {
okini3939 0:02c293160df3 123 MIDIMessage msg;
okini3939 0:02c293160df3 124 msg.data[0] = CABLE_NUM | 0x0C;
okini3939 0:02c293160df3 125 msg.data[1] = 0xC0 | (channel & 0x0F);
okini3939 0:02c293160df3 126 msg.data[2] = program & 0x7F;
okini3939 0:02c293160df3 127 msg.data[3] = 0x00;
okini3939 0:02c293160df3 128 return msg;
okini3939 0:02c293160df3 129 }
okini3939 0:02c293160df3 130
okini3939 0:02c293160df3 131 /** Create a Channel Aftertouch message
okini3939 0:02c293160df3 132 * @param pressure Pressure
okini3939 0:02c293160df3 133 * @param channel Key channel (0-15, default 0)
okini3939 0:02c293160df3 134 * @returns A MIDIMessage
okini3939 0:02c293160df3 135 */
okini3939 0:02c293160df3 136 static MIDIMessage ChannelAftertouch(int pressure, int channel = 0) {
okini3939 0:02c293160df3 137 MIDIMessage msg;
okini3939 0:02c293160df3 138 msg.data[0] = CABLE_NUM | 0x0D;
okini3939 0:02c293160df3 139 msg.data[1] = 0xD0 | (channel & 0x0F);
okini3939 0:02c293160df3 140 msg.data[2] = pressure & 0x7F;
okini3939 0:02c293160df3 141 msg.data[3] = 0x00;
okini3939 0:02c293160df3 142 return msg;
okini3939 0:02c293160df3 143 }
okini3939 0:02c293160df3 144
okini3939 0:02c293160df3 145 /** Create a Pitch Wheel message
okini3939 0:02c293160df3 146 * @param pitch Pitch (-8192 - 8191, default = 0)
okini3939 0:02c293160df3 147 * @param channel Channel (0-15, default 0)
okini3939 0:02c293160df3 148 * @returns A MIDIMessage
okini3939 0:02c293160df3 149 */
okini3939 0:02c293160df3 150 static MIDIMessage PitchWheel(int pitch = 0, int channel = 0) {
okini3939 0:02c293160df3 151 MIDIMessage msg;
okini3939 0:02c293160df3 152 int p = pitch + 8192; // 0 - 16383, 8192 is center
okini3939 0:02c293160df3 153 msg.data[0] = CABLE_NUM | 0x0E;
okini3939 0:02c293160df3 154 msg.data[1] = 0xE0 | (channel & 0x0F);
okini3939 0:02c293160df3 155 msg.data[2] = p & 0x7F;
okini3939 0:02c293160df3 156 msg.data[3] = (p >> 7) & 0x7F;
okini3939 0:02c293160df3 157 return msg;
okini3939 0:02c293160df3 158 }
okini3939 0:02c293160df3 159
okini3939 0:02c293160df3 160 /** Create an All Notes Off message
okini3939 0:02c293160df3 161 * @param channel Channel (0-15, default 0)
okini3939 0:02c293160df3 162 * @returns A MIDIMessage
okini3939 0:02c293160df3 163 */
okini3939 0:02c293160df3 164 static MIDIMessage AllNotesOff(int channel = 0) {
okini3939 0:02c293160df3 165 return ControlChange(123, 0, channel);
okini3939 0:02c293160df3 166 }
okini3939 0:02c293160df3 167
okini3939 0:02c293160df3 168 // decode messages
okini3939 0:02c293160df3 169
okini3939 0:02c293160df3 170 /** MIDI Message Types */
okini3939 0:02c293160df3 171 enum MIDIMessageType {
okini3939 0:02c293160df3 172 ErrorType,
okini3939 0:02c293160df3 173 NoteOffType,
okini3939 0:02c293160df3 174 NoteOnType,
okini3939 0:02c293160df3 175 PolyphonicAftertouchType,
okini3939 0:02c293160df3 176 ControlChangeType,
okini3939 0:02c293160df3 177 ProgramChangeType,
okini3939 0:02c293160df3 178 ChannelAftertouchType,
okini3939 0:02c293160df3 179 PitchWheelType,
okini3939 0:02c293160df3 180 AllNotesOffType
okini3939 0:02c293160df3 181 };
okini3939 0:02c293160df3 182
okini3939 0:02c293160df3 183 /** Read the message type
okini3939 0:02c293160df3 184 * @returns MIDIMessageType
okini3939 0:02c293160df3 185 */
okini3939 0:02c293160df3 186 MIDIMessageType type() {
okini3939 0:02c293160df3 187 switch((data[1] >> 4) & 0xF) {
okini3939 0:02c293160df3 188 case 0x8: return NoteOffType;
okini3939 0:02c293160df3 189 case 0x9: return NoteOnType;
okini3939 0:02c293160df3 190 case 0xA: return PolyphonicAftertouchType;
okini3939 0:02c293160df3 191 case 0xB:
okini3939 0:02c293160df3 192 if(controller() < 120) { // standard controllers
okini3939 0:02c293160df3 193 return ControlChangeType;
okini3939 0:02c293160df3 194 } else if(controller() == 123) {
okini3939 0:02c293160df3 195 return AllNotesOffType;
okini3939 0:02c293160df3 196 } else {
okini3939 0:02c293160df3 197 return ErrorType; // unsupported atm
okini3939 0:02c293160df3 198 }
okini3939 0:02c293160df3 199 case 0xC: return ProgramChangeType;
okini3939 0:02c293160df3 200 case 0xD: return ChannelAftertouchType;
okini3939 0:02c293160df3 201 case 0xE: return PitchWheelType;
okini3939 0:02c293160df3 202 default: return ErrorType;
okini3939 0:02c293160df3 203 }
okini3939 0:02c293160df3 204 }
okini3939 0:02c293160df3 205
okini3939 0:02c293160df3 206 /** Read the channel number */
okini3939 0:02c293160df3 207 int channel() {
okini3939 0:02c293160df3 208 return (data[1] & 0x0F);
okini3939 0:02c293160df3 209 }
okini3939 0:02c293160df3 210
okini3939 0:02c293160df3 211 /** Read the key ID */
okini3939 0:02c293160df3 212 int key() {
okini3939 0:02c293160df3 213 return (data[2] & 0x7F);
okini3939 0:02c293160df3 214 }
okini3939 0:02c293160df3 215
okini3939 0:02c293160df3 216 /** Read the velocity */
okini3939 0:02c293160df3 217 int velocity() {
okini3939 0:02c293160df3 218 return (data[3] & 0x7F);
okini3939 0:02c293160df3 219 }
okini3939 0:02c293160df3 220
okini3939 0:02c293160df3 221 /** Read the controller value */
okini3939 0:02c293160df3 222 int value() {
okini3939 0:02c293160df3 223 return (data[3] & 0x7F);
okini3939 0:02c293160df3 224 }
okini3939 0:02c293160df3 225
okini3939 0:02c293160df3 226 /** Read the aftertouch pressure */
okini3939 0:02c293160df3 227 int pressure() {
okini3939 0:02c293160df3 228 if(type() == PolyphonicAftertouchType) {
okini3939 0:02c293160df3 229 return (data[3] & 0x7F);
okini3939 0:02c293160df3 230 } else {
okini3939 0:02c293160df3 231 return (data[2] & 0x7F);
okini3939 0:02c293160df3 232 }
okini3939 0:02c293160df3 233 }
okini3939 0:02c293160df3 234
okini3939 0:02c293160df3 235 /** Read the controller number */
okini3939 0:02c293160df3 236 int controller() {
okini3939 0:02c293160df3 237 return (data[2] & 0x7F);
okini3939 0:02c293160df3 238 }
okini3939 0:02c293160df3 239
okini3939 0:02c293160df3 240 /** Read the program number */
okini3939 0:02c293160df3 241 int program() {
okini3939 0:02c293160df3 242 return (data[2] & 0x7F);
okini3939 0:02c293160df3 243 }
okini3939 0:02c293160df3 244
okini3939 0:02c293160df3 245 /** Read the pitch value */
okini3939 0:02c293160df3 246 int pitch() {
okini3939 0:02c293160df3 247 int p = ((data[3] & 0x7F) << 7) | (data[2] & 0x7F);
okini3939 0:02c293160df3 248 return p - 8192; // 0 - 16383, 8192 is center
okini3939 0:02c293160df3 249 }
okini3939 0:02c293160df3 250
okini3939 0:02c293160df3 251 uint8_t data[4];
okini3939 0:02c293160df3 252 };
okini3939 0:02c293160df3 253
okini3939 0:02c293160df3 254 #endif