1 /*
2   Copyright 2012-2016 David Robillard <d@drobilla.net>
3 
4   Permission to use, copy, modify, and/or distribute this software for any
5   purpose with or without fee is hereby granted, provided that the above
6   copyright notice and this permission notice appear in all copies.
7 
8   THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 
17 #ifndef LV2_MIDI_H
18 #define LV2_MIDI_H
19 
20 /**
21    @defgroup midi MIDI
22    @ingroup lv2
23 
24    Definitions of standard MIDI messages.
25 
26    See <http://lv2plug.in/ns/ext/midi> for details.
27 
28    @{
29 */
30 
31 #include <stdbool.h>
32 #include <stdint.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 // clang-format off
39 
40 #define LV2_MIDI_URI    "http://lv2plug.in/ns/ext/midi"  ///< http://lv2plug.in/ns/ext/midi
41 #define LV2_MIDI_PREFIX LV2_MIDI_URI "#"                 ///< http://lv2plug.in/ns/ext/midi#
42 
43 #define LV2_MIDI__ActiveSense      LV2_MIDI_PREFIX "ActiveSense"       ///< http://lv2plug.in/ns/ext/midi#ActiveSense
44 #define LV2_MIDI__Aftertouch       LV2_MIDI_PREFIX "Aftertouch"        ///< http://lv2plug.in/ns/ext/midi#Aftertouch
45 #define LV2_MIDI__Bender           LV2_MIDI_PREFIX "Bender"            ///< http://lv2plug.in/ns/ext/midi#Bender
46 #define LV2_MIDI__ChannelPressure  LV2_MIDI_PREFIX "ChannelPressure"   ///< http://lv2plug.in/ns/ext/midi#ChannelPressure
47 #define LV2_MIDI__Chunk            LV2_MIDI_PREFIX "Chunk"             ///< http://lv2plug.in/ns/ext/midi#Chunk
48 #define LV2_MIDI__Clock            LV2_MIDI_PREFIX "Clock"             ///< http://lv2plug.in/ns/ext/midi#Clock
49 #define LV2_MIDI__Continue         LV2_MIDI_PREFIX "Continue"          ///< http://lv2plug.in/ns/ext/midi#Continue
50 #define LV2_MIDI__Controller       LV2_MIDI_PREFIX "Controller"        ///< http://lv2plug.in/ns/ext/midi#Controller
51 #define LV2_MIDI__MidiEvent        LV2_MIDI_PREFIX "MidiEvent"         ///< http://lv2plug.in/ns/ext/midi#MidiEvent
52 #define LV2_MIDI__NoteOff          LV2_MIDI_PREFIX "NoteOff"           ///< http://lv2plug.in/ns/ext/midi#NoteOff
53 #define LV2_MIDI__NoteOn           LV2_MIDI_PREFIX "NoteOn"            ///< http://lv2plug.in/ns/ext/midi#NoteOn
54 #define LV2_MIDI__ProgramChange    LV2_MIDI_PREFIX "ProgramChange"     ///< http://lv2plug.in/ns/ext/midi#ProgramChange
55 #define LV2_MIDI__QuarterFrame     LV2_MIDI_PREFIX "QuarterFrame"      ///< http://lv2plug.in/ns/ext/midi#QuarterFrame
56 #define LV2_MIDI__Reset            LV2_MIDI_PREFIX "Reset"             ///< http://lv2plug.in/ns/ext/midi#Reset
57 #define LV2_MIDI__SongPosition     LV2_MIDI_PREFIX "SongPosition"      ///< http://lv2plug.in/ns/ext/midi#SongPosition
58 #define LV2_MIDI__SongSelect       LV2_MIDI_PREFIX "SongSelect"        ///< http://lv2plug.in/ns/ext/midi#SongSelect
59 #define LV2_MIDI__Start            LV2_MIDI_PREFIX "Start"             ///< http://lv2plug.in/ns/ext/midi#Start
60 #define LV2_MIDI__Stop             LV2_MIDI_PREFIX "Stop"              ///< http://lv2plug.in/ns/ext/midi#Stop
61 #define LV2_MIDI__SystemCommon     LV2_MIDI_PREFIX "SystemCommon"      ///< http://lv2plug.in/ns/ext/midi#SystemCommon
62 #define LV2_MIDI__SystemExclusive  LV2_MIDI_PREFIX "SystemExclusive"   ///< http://lv2plug.in/ns/ext/midi#SystemExclusive
63 #define LV2_MIDI__SystemMessage    LV2_MIDI_PREFIX "SystemMessage"     ///< http://lv2plug.in/ns/ext/midi#SystemMessage
64 #define LV2_MIDI__SystemRealtime   LV2_MIDI_PREFIX "SystemRealtime"    ///< http://lv2plug.in/ns/ext/midi#SystemRealtime
65 #define LV2_MIDI__Tick             LV2_MIDI_PREFIX "Tick"              ///< http://lv2plug.in/ns/ext/midi#Tick
66 #define LV2_MIDI__TuneRequest      LV2_MIDI_PREFIX "TuneRequest"       ///< http://lv2plug.in/ns/ext/midi#TuneRequest
67 #define LV2_MIDI__VoiceMessage     LV2_MIDI_PREFIX "VoiceMessage"      ///< http://lv2plug.in/ns/ext/midi#VoiceMessage
68 #define LV2_MIDI__benderValue      LV2_MIDI_PREFIX "benderValue"       ///< http://lv2plug.in/ns/ext/midi#benderValue
69 #define LV2_MIDI__binding          LV2_MIDI_PREFIX "binding"           ///< http://lv2plug.in/ns/ext/midi#binding
70 #define LV2_MIDI__byteNumber       LV2_MIDI_PREFIX "byteNumber"        ///< http://lv2plug.in/ns/ext/midi#byteNumber
71 #define LV2_MIDI__channel          LV2_MIDI_PREFIX "channel"           ///< http://lv2plug.in/ns/ext/midi#channel
72 #define LV2_MIDI__chunk            LV2_MIDI_PREFIX "chunk"             ///< http://lv2plug.in/ns/ext/midi#chunk
73 #define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber"  ///< http://lv2plug.in/ns/ext/midi#controllerNumber
74 #define LV2_MIDI__controllerValue  LV2_MIDI_PREFIX "controllerValue"   ///< http://lv2plug.in/ns/ext/midi#controllerValue
75 #define LV2_MIDI__noteNumber       LV2_MIDI_PREFIX "noteNumber"        ///< http://lv2plug.in/ns/ext/midi#noteNumber
76 #define LV2_MIDI__pressure         LV2_MIDI_PREFIX "pressure"          ///< http://lv2plug.in/ns/ext/midi#pressure
77 #define LV2_MIDI__programNumber    LV2_MIDI_PREFIX "programNumber"     ///< http://lv2plug.in/ns/ext/midi#programNumber
78 #define LV2_MIDI__property         LV2_MIDI_PREFIX "property"          ///< http://lv2plug.in/ns/ext/midi#property
79 #define LV2_MIDI__songNumber       LV2_MIDI_PREFIX "songNumber"        ///< http://lv2plug.in/ns/ext/midi#songNumber
80 #define LV2_MIDI__songPosition     LV2_MIDI_PREFIX "songPosition"      ///< http://lv2plug.in/ns/ext/midi#songPosition
81 #define LV2_MIDI__status           LV2_MIDI_PREFIX "status"            ///< http://lv2plug.in/ns/ext/midi#status
82 #define LV2_MIDI__statusMask       LV2_MIDI_PREFIX "statusMask"        ///< http://lv2plug.in/ns/ext/midi#statusMask
83 #define LV2_MIDI__velocity         LV2_MIDI_PREFIX "velocity"          ///< http://lv2plug.in/ns/ext/midi#velocity
84 
85 // clang-format on
86 
87 /**
88    MIDI Message Type.
89 
90    This includes both voice messages (which have a channel) and system messages
91    (which do not), as well as a sentinel value for invalid messages.  To get
92    the type of a message suitable for use in a switch statement, use
93    lv2_midi_get_type() on the status byte.
94 */
95 typedef enum {
96   LV2_MIDI_MSG_INVALID          = 0,    /**< Invalid Message */
97   LV2_MIDI_MSG_NOTE_OFF         = 0x80, /**< Note Off */
98   LV2_MIDI_MSG_NOTE_ON          = 0x90, /**< Note On */
99   LV2_MIDI_MSG_NOTE_PRESSURE    = 0xA0, /**< Note Pressure */
100   LV2_MIDI_MSG_CONTROLLER       = 0xB0, /**< Controller */
101   LV2_MIDI_MSG_PGM_CHANGE       = 0xC0, /**< Program Change */
102   LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0, /**< Channel Pressure */
103   LV2_MIDI_MSG_BENDER           = 0xE0, /**< Pitch Bender */
104   LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0, /**< System Exclusive Begin */
105   LV2_MIDI_MSG_MTC_QUARTER      = 0xF1, /**< MTC Quarter Frame */
106   LV2_MIDI_MSG_SONG_POS         = 0xF2, /**< Song Position */
107   LV2_MIDI_MSG_SONG_SELECT      = 0xF3, /**< Song Select */
108   LV2_MIDI_MSG_TUNE_REQUEST     = 0xF6, /**< Tune Request */
109   LV2_MIDI_MSG_CLOCK            = 0xF8, /**< Clock */
110   LV2_MIDI_MSG_START            = 0xFA, /**< Start */
111   LV2_MIDI_MSG_CONTINUE         = 0xFB, /**< Continue */
112   LV2_MIDI_MSG_STOP             = 0xFC, /**< Stop */
113   LV2_MIDI_MSG_ACTIVE_SENSE     = 0xFE, /**< Active Sensing */
114   LV2_MIDI_MSG_RESET            = 0xFF  /**< Reset */
115 } LV2_Midi_Message_Type;
116 
117 /**
118    Standard MIDI Controller Numbers.
119 */
120 typedef enum {
121   LV2_MIDI_CTL_MSB_BANK             = 0x00, /**< Bank Selection */
122   LV2_MIDI_CTL_MSB_MODWHEEL         = 0x01, /**< Modulation */
123   LV2_MIDI_CTL_MSB_BREATH           = 0x02, /**< Breath */
124   LV2_MIDI_CTL_MSB_FOOT             = 0x04, /**< Foot */
125   LV2_MIDI_CTL_MSB_PORTAMENTO_TIME  = 0x05, /**< Portamento Time */
126   LV2_MIDI_CTL_MSB_DATA_ENTRY       = 0x06, /**< Data Entry */
127   LV2_MIDI_CTL_MSB_MAIN_VOLUME      = 0x07, /**< Main Volume */
128   LV2_MIDI_CTL_MSB_BALANCE          = 0x08, /**< Balance */
129   LV2_MIDI_CTL_MSB_PAN              = 0x0A, /**< Panpot */
130   LV2_MIDI_CTL_MSB_EXPRESSION       = 0x0B, /**< Expression */
131   LV2_MIDI_CTL_MSB_EFFECT1          = 0x0C, /**< Effect1 */
132   LV2_MIDI_CTL_MSB_EFFECT2          = 0x0D, /**< Effect2 */
133   LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, /**< General Purpose 1 */
134   LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, /**< General Purpose 2 */
135   LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, /**< General Purpose 3 */
136   LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, /**< General Purpose 4 */
137   LV2_MIDI_CTL_LSB_BANK             = 0x20, /**< Bank Selection */
138   LV2_MIDI_CTL_LSB_MODWHEEL         = 0x21, /**< Modulation */
139   LV2_MIDI_CTL_LSB_BREATH           = 0x22, /**< Breath */
140   LV2_MIDI_CTL_LSB_FOOT             = 0x24, /**< Foot */
141   LV2_MIDI_CTL_LSB_PORTAMENTO_TIME  = 0x25, /**< Portamento Time */
142   LV2_MIDI_CTL_LSB_DATA_ENTRY       = 0x26, /**< Data Entry */
143   LV2_MIDI_CTL_LSB_MAIN_VOLUME      = 0x27, /**< Main Volume */
144   LV2_MIDI_CTL_LSB_BALANCE          = 0x28, /**< Balance */
145   LV2_MIDI_CTL_LSB_PAN              = 0x2A, /**< Panpot */
146   LV2_MIDI_CTL_LSB_EXPRESSION       = 0x2B, /**< Expression */
147   LV2_MIDI_CTL_LSB_EFFECT1          = 0x2C, /**< Effect1 */
148   LV2_MIDI_CTL_LSB_EFFECT2          = 0x2D, /**< Effect2 */
149   LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, /**< General Purpose 1 */
150   LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, /**< General Purpose 2 */
151   LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, /**< General Purpose 3 */
152   LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, /**< General Purpose 4 */
153   LV2_MIDI_CTL_SUSTAIN              = 0x40, /**< Sustain Pedal */
154   LV2_MIDI_CTL_PORTAMENTO           = 0x41, /**< Portamento */
155   LV2_MIDI_CTL_SOSTENUTO            = 0x42, /**< Sostenuto */
156   LV2_MIDI_CTL_SOFT_PEDAL           = 0x43, /**< Soft Pedal */
157   LV2_MIDI_CTL_LEGATO_FOOTSWITCH    = 0x44, /**< Legato Foot Switch */
158   LV2_MIDI_CTL_HOLD2                = 0x45, /**< Hold2 */
159   LV2_MIDI_CTL_SC1_SOUND_VARIATION  = 0x46, /**< SC1 Sound Variation */
160   LV2_MIDI_CTL_SC2_TIMBRE           = 0x47, /**< SC2 Timbre */
161   LV2_MIDI_CTL_SC3_RELEASE_TIME     = 0x48, /**< SC3 Release Time */
162   LV2_MIDI_CTL_SC4_ATTACK_TIME      = 0x49, /**< SC4 Attack Time */
163   LV2_MIDI_CTL_SC5_BRIGHTNESS       = 0x4A, /**< SC5 Brightness */
164   LV2_MIDI_CTL_SC6                  = 0x4B, /**< SC6 */
165   LV2_MIDI_CTL_SC7                  = 0x4C, /**< SC7 */
166   LV2_MIDI_CTL_SC8                  = 0x4D, /**< SC8 */
167   LV2_MIDI_CTL_SC9                  = 0x4E, /**< SC9 */
168   LV2_MIDI_CTL_SC10                 = 0x4F, /**< SC10 */
169   LV2_MIDI_CTL_GENERAL_PURPOSE5     = 0x50, /**< General Purpose 5 */
170   LV2_MIDI_CTL_GENERAL_PURPOSE6     = 0x51, /**< General Purpose 6 */
171   LV2_MIDI_CTL_GENERAL_PURPOSE7     = 0x52, /**< General Purpose 7 */
172   LV2_MIDI_CTL_GENERAL_PURPOSE8     = 0x53, /**< General Purpose 8 */
173   LV2_MIDI_CTL_PORTAMENTO_CONTROL   = 0x54, /**< Portamento Control */
174   LV2_MIDI_CTL_E1_REVERB_DEPTH      = 0x5B, /**< E1 Reverb Depth */
175   LV2_MIDI_CTL_E2_TREMOLO_DEPTH     = 0x5C, /**< E2 Tremolo Depth */
176   LV2_MIDI_CTL_E3_CHORUS_DEPTH      = 0x5D, /**< E3 Chorus Depth */
177   LV2_MIDI_CTL_E4_DETUNE_DEPTH      = 0x5E, /**< E4 Detune Depth */
178   LV2_MIDI_CTL_E5_PHASER_DEPTH      = 0x5F, /**< E5 Phaser Depth */
179   LV2_MIDI_CTL_DATA_INCREMENT       = 0x60, /**< Data Increment */
180   LV2_MIDI_CTL_DATA_DECREMENT       = 0x61, /**< Data Decrement */
181   LV2_MIDI_CTL_NRPN_LSB          = 0x62, /**< Non-registered Parameter Number */
182   LV2_MIDI_CTL_NRPN_MSB          = 0x63, /**< Non-registered Parameter Number */
183   LV2_MIDI_CTL_RPN_LSB           = 0x64, /**< Registered Parameter Number */
184   LV2_MIDI_CTL_RPN_MSB           = 0x65, /**< Registered Parameter Number */
185   LV2_MIDI_CTL_ALL_SOUNDS_OFF    = 0x78, /**< All Sounds Off */
186   LV2_MIDI_CTL_RESET_CONTROLLERS = 0x79, /**< Reset Controllers */
187   LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A, /**< Local Control Switch */
188   LV2_MIDI_CTL_ALL_NOTES_OFF        = 0x7B, /**< All Notes Off */
189   LV2_MIDI_CTL_OMNI_OFF             = 0x7C, /**< Omni Off */
190   LV2_MIDI_CTL_OMNI_ON              = 0x7D, /**< Omni On */
191   LV2_MIDI_CTL_MONO1                = 0x7E, /**< Mono1 */
192   LV2_MIDI_CTL_MONO2                = 0x7F  /**< Mono2 */
193 } LV2_Midi_Controller;
194 
195 /**
196    Return true iff `msg` is a MIDI voice message (which has a channel).
197 */
198 static inline bool
lv2_midi_is_voice_message(const uint8_t * msg)199 lv2_midi_is_voice_message(const uint8_t* msg)
200 {
201   return msg[0] >= 0x80 && msg[0] < 0xF0;
202 }
203 
204 /**
205    Return true iff `msg` is a MIDI system message (which has no channel).
206 */
207 static inline bool
lv2_midi_is_system_message(const uint8_t * msg)208 lv2_midi_is_system_message(const uint8_t* msg)
209 {
210   switch (msg[0]) {
211   case 0xF4:
212   case 0xF5:
213   case 0xF7:
214   case 0xF9:
215   case 0xFD:
216     return false;
217   default:
218     return (msg[0] & 0xF0) == 0xF0;
219   }
220 }
221 
222 /**
223    Return the type of a MIDI message.
224    @param msg Pointer to the start (status byte) of a MIDI message.
225 */
226 static inline LV2_Midi_Message_Type
lv2_midi_message_type(const uint8_t * msg)227 lv2_midi_message_type(const uint8_t* msg)
228 {
229   if (lv2_midi_is_voice_message(msg)) {
230     return (LV2_Midi_Message_Type)(msg[0] & 0xF0);
231   }
232 
233   if (lv2_midi_is_system_message(msg)) {
234     return (LV2_Midi_Message_Type)msg[0];
235   }
236 
237   return LV2_MIDI_MSG_INVALID;
238 }
239 
240 #ifdef __cplusplus
241 } /* extern "C" */
242 #endif
243 
244 /**
245    @}
246 */
247 
248 #endif /* LV2_MIDI_H */
249