1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 14 марта 2016 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef CORE_MIDI_H_ 23 #define CORE_MIDI_H_ 24 25 #include <core/types.h> 26 27 namespace lsp 28 { 29 // Generalized midi event structure 30 namespace midi 31 { 32 #pragma pack(push, 1) 33 typedef struct event_t 34 { 35 uint32_t timestamp; // Timestamp 36 uint8_t type; // Type of event 37 uint8_t channel; // ID of the MIDI channel 38 union 39 { 40 uint8_t bparams[2]; // Byte parameters 41 42 struct 43 { 44 uint8_t pitch; // Note key 45 uint8_t velocity; // Note velocity 46 } note; 47 48 struct 49 { 50 uint8_t control; // Control 51 uint8_t value; // Value 52 } ctl; 53 54 struct 55 { 56 uint8_t pitch; // Note key 57 uint8_t pressure; // Note pressure 58 } atouch; 59 60 struct 61 { 62 uint8_t pressure; // Channel pressure 63 } chn; 64 65 uint8_t program; // program 66 uint16_t bend; 67 68 struct 69 { 70 uint8_t type; 71 uint8_t value; 72 } mtc; 73 74 uint16_t beats; 75 uint8_t song; 76 }; 77 } event_t; 78 #pragma pack(pop) 79 80 enum message_t 81 { 82 MIDI_MSG_NOTE_OFF = 0x80, 83 MIDI_MSG_NOTE_ON = 0x90, 84 MIDI_MSG_NOTE_PRESSURE = 0xa0, 85 MIDI_MSG_NOTE_CONTROLLER = 0xb0, 86 MIDI_MSG_PROGRAM_CHANGE = 0xc0, 87 MIDI_MSG_CHANNEL_PRESSURE = 0xd0, 88 MIDI_MSG_PITCH_BEND = 0xe0, 89 MIDI_MSG_SYSTEM_EXCLUSIVE = 0xf0, 90 MIDI_MSG_MTC_QUARTER = 0xf1, 91 MIDI_MSG_SONG_POS = 0xf2, 92 MIDI_MSG_SONG_SELECT = 0xf3, 93 MIDI_MSG_TUNE_REQUEST = 0xf6, 94 MIDI_MSG_END_EXCLUSIVE = 0xf7, 95 MIDI_MSG_CLOCK = 0xf8, 96 MIDI_MSG_START = 0xfa, 97 MIDI_MSG_CONTINUE = 0xfb, 98 MIDI_MSG_STOP = 0xfc, 99 MIDI_MSG_ACTIVE_SENSING = 0xfe, 100 MIDI_MSG_RESET = 0xff 101 }; 102 103 enum controller_t 104 { 105 MIDI_CTL_MSB_BANK = 0x00, 106 MIDI_CTL_MSB_MODWHEEL = 0x01, 107 MIDI_CTL_MSB_BREATH = 0x02, 108 MIDI_CTL_MSB_FOOT = 0x04, 109 MIDI_CTL_MSB_PORTAMENTO_TIME = 0x05, 110 MIDI_CTL_MSB_DATA_ENTRY = 0x06, 111 MIDI_CTL_MSB_MAIN_VOLUME = 0x07, 112 MIDI_CTL_MSB_BALANCE = 0x08, 113 MIDI_CTL_MSB_PAN = 0x0a, 114 MIDI_CTL_MSB_EXPRESSION = 0x0b, 115 MIDI_CTL_MSB_EFFECT1 = 0x0c, 116 MIDI_CTL_MSB_EFFECT2 = 0x0d, 117 MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, 118 MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, 119 MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, 120 MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, 121 MIDI_CTL_LSB_BANK = 0x20, 122 MIDI_CTL_LSB_MODWHEEL = 0x21, 123 MIDI_CTL_LSB_BREATH = 0x22, 124 MIDI_CTL_LSB_FOOT = 0x24, 125 MIDI_CTL_LSB_PORTAMENTO_TIME = 0x25, 126 MIDI_CTL_LSB_DATA_ENTRY = 0x26, 127 MIDI_CTL_LSB_MAIN_VOLUME = 0x27, 128 MIDI_CTL_LSB_BALANCE = 0x28, 129 MIDI_CTL_LSB_PAN = 0x2a, 130 MIDI_CTL_LSB_EXPRESSION = 0x2b, 131 MIDI_CTL_LSB_EFFECT1 = 0x2c, 132 MIDI_CTL_LSB_EFFECT2 = 0x2d, 133 MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, 134 MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, 135 MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, 136 MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, 137 MIDI_CTL_SUSTAIN = 0x40, 138 MIDI_CTL_PORTAMENTO = 0x41, 139 MIDI_CTL_SOSTENUTO = 0x42, 140 MIDI_CTL_SOFT_PEDAL = 0x43, 141 MIDI_CTL_LEGATO_FOOTSWITCH = 0x44, 142 MIDI_CTL_HOLD2 = 0x45, 143 MIDI_CTL_SC1_SOUND_VARIATION = 0x46, 144 MIDI_CTL_SC2_TIMBRE = 0x47, 145 MIDI_CTL_SC3_RELEASE_TIME = 0x48, 146 MIDI_CTL_SC4_ATTACK_TIME = 0x49, 147 MIDI_CTL_SC5_BRIGHTNESS = 0x4a, 148 MIDI_CTL_SC6 = 0x4b, 149 MIDI_CTL_SC7 = 0x4c, 150 MIDI_CTL_SC8 = 0x4d, 151 MIDI_CTL_SC9 = 0x4e, 152 MIDI_CTL_SC10 = 0x4f, 153 MIDI_CTL_GENERAL_PURPOSE5 = 0x50, 154 MIDI_CTL_GENERAL_PURPOSE6 = 0x51, 155 MIDI_CTL_GENERAL_PURPOSE7 = 0x52, 156 MIDI_CTL_GENERAL_PURPOSE8 = 0x53, 157 MIDI_CTL_PORTAMENTO_CONTROL = 0x54, 158 MIDI_CTL_E1_REVERB_DEPTH = 0x5b, 159 MIDI_CTL_E2_TREMOLO_DEPTH = 0x5c, 160 MIDI_CTL_E3_CHORUS_DEPTH = 0x5d, 161 MIDI_CTL_E4_DETUNE_DEPTH = 0x5e, 162 MIDI_CTL_E5_PHASER_DEPTH = 0x5f, 163 MIDI_CTL_DATA_INCREMENT = 0x60, 164 MIDI_CTL_DATA_DECREMENT = 0x61, 165 MIDI_CTL_NRPN_LSB = 0x62, 166 MIDI_CTL_NRPN_MSB = 0x63, 167 MIDI_CTL_RPN_LSB = 0x64, 168 MIDI_CTL_RPN_MSB = 0x65, 169 MIDI_CTL_ALL_SOUNDS_OFF = 0x78, 170 MIDI_CTL_RESET_CONTROLLERS = 0x79, 171 MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7a, 172 MIDI_CTL_ALL_NOTES_OFF = 0x7b, 173 MIDI_CTL_OMNI_OFF = 0x7c, 174 MIDI_CTL_OMNI_ON = 0x7d, 175 MIDI_CTL_MONO1 = 0x7e, 176 MIDI_CTL_MONO2 = 0x7f 177 }; 178 179 /** 180 * Decode MIDI message 181 * @param ev MIDI event structure to decode 182 * @param bytes buffer containing MIDI message 183 * @return number of bytes used for decodingm negative value on error, never zero 184 */ 185 ssize_t decode(event_t *ev, const uint8_t *bytes); 186 187 /** 188 * Encode MIDI message 189 * @param bytes buffer to store encoded MIDI message 190 * @param ev MIDI event to encode 191 * @return number of bytes used for encoding, negative value on error, never zero 192 */ 193 ssize_t encode(uint8_t *bytes, const event_t *ev); 194 195 /** 196 * Return number of bytes required for encoding 197 * @param ev MIDI event 198 * @return number of bytes required to encode MIDI event, negative value on error, never zero 199 */ 200 ssize_t size_of(const event_t *ev); 201 } 202 203 // Midi port structure 204 typedef struct midi_t 205 { 206 size_t nEvents; 207 midi::event_t vEvents[MIDI_EVENTS_MAX]; 208 pushmidi_t209 inline bool push(const midi::event_t *me) 210 { 211 if (nEvents >= MIDI_EVENTS_MAX) 212 return false; 213 vEvents[nEvents++] = *me; 214 return true; 215 } 216 pushmidi_t217 inline bool push(const midi::event_t &me) 218 { 219 return push(&me); 220 } 221 push_allmidi_t222 inline bool push_all(const midi_t *src) 223 { 224 size_t avail = MIDI_EVENTS_MAX - nEvents; 225 size_t count = (src->nEvents > avail) ? avail : src->nEvents; 226 if (count > 0) 227 { 228 ::memcpy(&vEvents[nEvents], src->vEvents, count * sizeof(midi::event_t)); 229 nEvents += count; 230 } 231 232 return count >= src->nEvents; 233 } 234 push_allmidi_t235 inline bool push_all(const midi_t &src) 236 { 237 return push_all(&src); 238 } 239 copy_frommidi_t240 inline void copy_from(const midi_t *src) 241 { 242 nEvents = src->nEvents; 243 if (nEvents > 0) 244 ::memcpy(vEvents, src->vEvents, nEvents * sizeof(midi::event_t)); 245 } 246 copy_tomidi_t247 inline void copy_to(midi_t *dst) const 248 { 249 dst->copy_from(this); 250 } 251 clearmidi_t252 inline void clear() 253 { 254 nEvents = 0; 255 } 256 257 void sort(); 258 } midi_t; 259 } 260 261 #endif /* CORE_MIDI_H_ */ 262