| @@ -0,0 +1,443 @@ |
| | 1 | /*============================================================================== |
| | 2 | |
| | 3 | leaf-midi.h |
| | 4 | Created: 30 Nov 2018 11:29:26am |
| | 5 | Author: airship |
| | 6 | |
| | 7 | ==============================================================================*/ |
| | 8 | |
| | 9 | #ifndef LEAF_MIDI_H_INCLUDED |
| | 10 | #define LEAF_MIDI_H_INCLUDED |
| | 11 | |
| | 12 | #ifdef __cplusplus |
| | 13 | extern "C" { |
| | 14 | #endif |
| | 15 | |
| | 16 | //============================================================================== |
| | 17 | |
| | 18 | #include "leaf-global.h" |
| | 19 | #include "leaf-mempool.h" |
| | 20 | #include "leaf-math.h" |
| | 21 | #include "leaf-envelopes.h" |
| | 22 | |
| | 23 | /*! |
| | 24 | * @internal |
| | 25 | * Header. |
| | 26 | * @include basic-oscillators.h |
| | 27 | * @example basic-oscillators.c |
| | 28 | * An example. |
| | 29 | */ |
| | 30 | |
| | 31 | //============================================================================== |
| | 32 | |
| | 33 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| | 34 | |
| | 35 | /*! |
| | 36 | @defgroup tstack tStack |
| | 37 | @ingroup midi |
| | 38 | @brief A basic stack of integers with a fixed capacity of 128, used by tPoly to keep track of MIDI notes. |
| | 39 | @{ |
| | 40 | |
| | 41 | @fn void tStack_init (tStack* const stack, LEAF* const leaf) |
| | 42 | @brief Initialize a tStack to the default mempool of a LEAF instance. |
| | 43 | @param stack A pointer to the tStack to initialize. |
| | 44 | @param leaf A pointer to the leaf instance. |
| | 45 | |
| | 46 | @fn void tStack_initToPool (tStack* const stack, tMempool* const mempool) |
| | 47 | @brief Initialize a tStack to a specified mempool. |
| | 48 | @param stack A pointer to the tStack to initialize. |
| | 49 | @param mempool A pointer to the tMempool to use. |
| | 50 | |
| | 51 | @fn void tStack_free (tStack* const stack) |
| | 52 | @brief Free a tStack from its mempool. |
| | 53 | @param stack A pointer to the tStack to free. |
| | 54 | |
| | 55 | @fn void tStack_setCapacity (tStack* const stack, uint16_t cap) |
| | 56 | @brief Set the capacity of the stack. |
| | 57 | @param stack A pointer to the relevant tStack. |
| | 58 | @param cap The new capacity. |
| | 59 | |
| | 60 | @fn int tStack_addIfNotAlreadyThere (tStack* const stack, uint16_t item) |
| | 61 | @brief Add a value to the stack only if that value is not already in the stack. |
| | 62 | @param stack A pointer to the relevant tStack. |
| | 63 | @param item The value to be added. |
| | 64 | |
| | 65 | @fn void tStack_add (tStack* const stack, uint16_t item) |
| | 66 | @brief Add a value to the stack. |
| | 67 | @param stack A pointer to the relevant tStack. |
| | 68 | @param item The value to be added. |
| | 69 | |
| | 70 | @fn int tStack_remove (tStack* const stack, uint16_t item) |
| | 71 | @brief Remove a single instance of a value from the stack. |
| | 72 | @param stack A pointer to the relevant tStack. |
| | 73 | @param item The value to be removed. |
| | 74 | |
| | 75 | @fn void tStack_clear (tStack* const stack) |
| | 76 | @brief Clear the stack. |
| | 77 | @param stack A pointer to the relevant tStack. |
| | 78 | |
| | 79 | @fn int tStack_first (tStack* const stack) |
| | 80 | @brief Get the first value in the stack. |
| | 81 | @param stack A pointer to the relevant tStack. |
| | 82 | @return The first value in the stack. |
| | 83 | |
| | 84 | @fn int tStack_getSize (tStack* const stack) |
| | 85 | @brief Get the current size of the stack. |
| | 86 | @param stack A pointer to the relevant tStack. |
| | 87 | @return The current size of the stack. |
| | 88 | |
| | 89 | @fn int tStack_contains (tStack* const stack, uint16_t item) |
| | 90 | @brief Check if the stack contains a value, and if it does, get the index of that value. |
| | 91 | @param stack A pointer to the relevant tStack. |
| | 92 | @param item The value to check against the stack. |
| | 93 | @return The index of the value or -1 if the stack does not contain the value. |
| | 94 | |
| | 95 | @fn int tStack_next (tStack* const stack) |
| | 96 | @brief Get the next value in the stack, starting from the earliest added values. |
| | 97 | @param stack A pointer to the relevant tStack. |
| | 98 | @return The next value in the stack or -1 if there are no values in the stack. |
| | 99 | |
| | 100 | @fn int tStack_get (tStack* const stack, int index) |
| | 101 | @brief Get the value at a given index of the stack. |
| | 102 | @param stack A pointer to the relevant tStack. |
| | 103 | @param index The index of the stack from which to get a value. |
| | 104 | @return The value at the given index. |
| | 105 | |
| | 106 | @} */ |
| | 107 | |
| | 108 | #define STACK_SIZE 128 |
| | 109 | typedef struct _tStack |
| | 110 | { |
| | 111 | |
| | 112 | tMempool mempool; |
| | 113 | int data[STACK_SIZE]; |
| | 114 | uint16_t pos; |
| | 115 | uint16_t size; |
| | 116 | uint16_t capacity; |
| | 117 | int ordered; |
| | 118 | } _tStack; |
| | 119 | |
| | 120 | typedef _tStack* tStack; |
| | 121 | |
| | 122 | void tStack_init (tStack* const stack, LEAF* const leaf); |
| | 123 | void tStack_initToPool (tStack* const stack, tMempool* const pool); |
| | 124 | void tStack_free (tStack* const stack); |
| | 125 | |
| | 126 | void tStack_setCapacity (tStack* const stack, uint16_t cap); |
| | 127 | int tStack_addIfNotAlreadyThere (tStack* const stack, uint16_t item); |
| | 128 | void tStack_add (tStack* const stack, uint16_t item); |
| | 129 | int tStack_remove (tStack* const stack, uint16_t item); |
| | 130 | void tStack_clear (tStack* const stack); |
| | 131 | int tStack_first (tStack* const stack); |
| | 132 | int tStack_getSize (tStack* const stack); |
| | 133 | int tStack_contains (tStack* const stack, uint16_t item); |
| | 134 | int tStack_next (tStack* const stack); |
| | 135 | int tStack_get (tStack* const stack, int index); |
| | 136 | |
| | 137 | /*! @} |
| | 138 | @defgroup tpoly tPoly |
| | 139 | @ingroup midi |
| | 140 | @brief Polyphony handler with glide and pitch bend options. |
| | 141 | @{ |
| | 142 | |
| | 143 | @fn void tPoly_init (tPoly* const poly, int maxNumVoices, LEAF* const leaf) |
| | 144 | @brief Initialize a tPoly to the default mempool of a LEAF instance. |
| | 145 | @param poly A pointer to the tPoly to initialize. |
| | 146 | @param maxNumVoices The maximum number of voices this tPoly can handle at once. |
| | 147 | @param leaf A pointer to the leaf instance. |
| | 148 | |
| | 149 | @fn void tPoly_initToPool (tPoly* const poly, int maxNumVoices, tMempool* const pool) |
| | 150 | @brief Initialize a tPoly to a specified mempool. |
| | 151 | @param poly A pointer to the tPoly to initialize. |
| | 152 | @param mempool A pointer to the tMempool to use. |
| | 153 | |
| | 154 | @fn void tPoly_free (tPoly* const poly) |
| | 155 | @brief Free a tPoly from its mempool. |
| | 156 | @param poly A pointer to the tPoly to free. |
| | 157 | |
| | 158 | @fn int tPoly_noteOn (tPoly* const poly, int note, uint8_t vel) |
| | 159 | @brief Add a note with a given velocity to the poly handler. |
| | 160 | @param poly A pointer to the relevant tPoly. |
| | 161 | @param note The MIDI note number to add. |
| | 162 | @param vel The MIDI velocity of the note to add. |
| | 163 | @return The voice that will play the note. |
| | 164 | |
| | 165 | @fn int tPoly_noteOff (tPoly* const poly, uint8_t note) |
| | 166 | @brief Remove a note from the poly handler. |
| | 167 | @param poly A pointer to the relevant tPoly. |
| | 168 | @param note The MIDI note number to remove. |
| | 169 | @return The voice that was playing the removed note. |
| | 170 | |
| | 171 | @fn void tPoly_orderedAddToStack (tPoly* const poly, uint8_t note) |
| | 172 | @brief |
| | 173 | @param |
| | 174 | |
| | 175 | @fn void tPoly_setNumVoices (tPoly* const poly, uint8_t numVoices) |
| | 176 | @brief Set the number of voices available to play notes. |
| | 177 | @param poly A pointer to the relevant tPoly. |
| | 178 | @param numVoices The new number of available voices. Cannot be greater than the max number voices given in tPoly_init(). |
| | 179 | |
| | 180 | @fn void tPoly_setPitchGlideActive (tPoly* const poly, int isActive) |
| | 181 | @brief Set whether pitch glide over note changes in voices is active. |
| | 182 | @param poly A pointer to the relevant tPoly. |
| | 183 | @param isActive Whether pitch glide should be active or not. |
| | 184 | |
| | 185 | @fn void tPoly_setPitchGlideTime (tPoly* const poly, float t) |
| | 186 | @brief Set how long pitch glide over note changes in voices takes. |
| | 187 | @param poly A pointer to the relevant tPoly. |
| | 188 | @param t The time to glide in milliseconds. |
| | 189 | |
| | 190 | @fn void tPoly_setPitchBend (tPoly* const poly, float pitchBend) |
| | 191 | @brief Set the amount of pitch bend |
| | 192 | @param poly A pointer to the relevant tPoly. |
| | 193 | @param pitchBend The new amount of pitch bend. |
| | 194 | |
| | 195 | @fn void tPoly_setBendGlideTime (tPoly* const poly, float t) |
| | 196 | @brief |
| | 197 | @param |
| | 198 | |
| | 199 | @fn void tPoly_setBendSamplesPerTick (tPoly* const poly, float t) |
| | 200 | @brief |
| | 201 | @param |
| | 202 | |
| | 203 | @fn void tPoly_tickPitch (tPoly* const poly) |
| | 204 | @brief Execute all tick-rate changes in the poly handler's pitch, including glide and bend. |
| | 205 | @param poly A pointer to the relevant tPoly. |
| | 206 | |
| | 207 | @fn void tPoly_tickPitchGlide (tPoly* const poly) |
| | 208 | @brief Execute the tick-rate change of the poly handler's pitch glide. |
| | 209 | @param poly A pointer to the relevant tPoly. |
| | 210 | |
| | 211 | @fn void tPoly_tickPitchBend (tPoly* const poly) |
| | 212 | @brief Execute the tick-rate change of the poly handler's pitch bend. |
| | 213 | @param poly A pointer to the relevant tPoly. |
| | 214 | |
| | 215 | @fn int tPoly_getNumVoices (tPoly* const poly) |
| | 216 | @brief Get the current number of voices available to play notes. |
| | 217 | @param poly A pointer to the relevant tPoly. |
| | 218 | @return The current number of voices available to play notes. |
| | 219 | |
| | 220 | @fn int tPoly_getNumActiveVoices (tPoly* const poly) |
| | 221 | @brief Get the number of voices currently playing notes. |
| | 222 | @param poly A pointer to the relevant tPoly. |
| | 223 | @return The number of voices currently playing notes. |
| | 224 | |
| | 225 | @fn float tPoly_getPitch (tPoly* const poly, uint8_t voice) |
| | 226 | @brief Get the current pitch of a given voice. |
| | 227 | @param poly A pointer to the relevant tPoly. |
| | 228 | @param voice The voice to get the pitch of. |
| | 229 | @return The current pitch of the given voice as a fractional MIDI note number. |
| | 230 | |
| | 231 | @fn int tPoly_getKey (tPoly* const poly, uint8_t voice) |
| | 232 | @brief Get the current MIDI note number of a given voice. |
| | 233 | @param poly A pointer to the relevant tPoly. |
| | 234 | @param voice The voice to get the MIDI note number of. |
| | 235 | @return The MIDI note number of the given voice. |
| | 236 | |
| | 237 | @fn int tPoly_getVelocity (tPoly* const poly, uint8_t voice) |
| | 238 | @brief Get the current MIDI velocity of a given voice. |
| | 239 | @param poly A pointer to the relevant tPoly. |
| | 240 | @param voice The voice to get the MIDI velocity of. |
| | 241 | @return The current MIDI velocity of the given voice. |
| | 242 | |
| | 243 | @fn int tPoly_isOn (tPoly* const poly, uint8_t voice) |
| | 244 | @brief Get the current play state of a given voice. |
| | 245 | @param poly A pointer to the relevant tPoly. |
| | 246 | @param voice The voice to get the state of. |
| | 247 | @return The current play state of the given voice. |
| | 248 | |
| | 249 | @} */ |
| | 250 | |
| | 251 | typedef struct _tPoly |
| | 252 | { |
| | 253 | |
| | 254 | tMempool mempool; |
| | 255 | |
| | 256 | tStack stack; |
| | 257 | tStack orderStack; |
| | 258 | |
| | 259 | tRamp* ramps; |
| | 260 | float* rampVals; |
| | 261 | int* firstReceived; |
| | 262 | float glideTime; |
| | 263 | int pitchGlideIsActive; |
| | 264 | |
| | 265 | int numVoices; |
| | 266 | int maxNumVoices; |
| | 267 | |
| | 268 | //int voices[POLY_NUM_MAX_VOICES][2]; |
| | 269 | int** voices; |
| | 270 | |
| | 271 | int notes[128][2]; |
| | 272 | |
| | 273 | int CCs[128]; |
| | 274 | |
| | 275 | uint8_t CCsRaw[128]; |
| | 276 | |
| | 277 | int lastVoiceToChange; |
| | 278 | |
| | 279 | float pitchBend; |
| | 280 | tRamp pitchBendRamp; |
| | 281 | |
| | 282 | int currentNote; |
| | 283 | int currentVoice; |
| | 284 | int currentVelocity; |
| | 285 | int maxLength; |
| | 286 | } _tPoly; |
| | 287 | |
| | 288 | typedef _tPoly* tPoly; |
| | 289 | |
| | 290 | void tPoly_init (tPoly* const poly, int maxNumVoices, LEAF* const leaf); |
| | 291 | void tPoly_initToPool (tPoly* const poly, int maxNumVoices, tMempool* const pool); |
| | 292 | void tPoly_free (tPoly* const poly); |
| | 293 | |
| | 294 | int tPoly_noteOn (tPoly* const poly, int note, uint8_t vel); |
| | 295 | int tPoly_noteOff (tPoly* const poly, uint8_t note); |
| | 296 | void tPoly_orderedAddToStack (tPoly* const poly, uint8_t note); |
| | 297 | void tPoly_setNumVoices (tPoly* const poly, uint8_t numVoices); |
| | 298 | void tPoly_setPitchGlideActive (tPoly* const poly, int isActive); |
| | 299 | void tPoly_setPitchGlideTime (tPoly* const poly, float t); |
| | 300 | void tPoly_setPitchBend (tPoly* const poly, float pitchBend); |
| | 301 | void tPoly_setBendGlideTime (tPoly* const poly, float t); |
| | 302 | void tPoly_setBendSamplesPerTick (tPoly* const poly, float t); |
| | 303 | void tPoly_tickPitch (tPoly* const poly); |
| | 304 | void tPoly_tickPitchGlide (tPoly* const poly); |
| | 305 | void tPoly_tickPitchBend (tPoly* const poly); |
| | 306 | int tPoly_getNumVoices (tPoly* const poly); |
| | 307 | int tPoly_getNumActiveVoices (tPoly* const poly); |
| | 308 | float tPoly_getPitch (tPoly* const poly, uint8_t voice); |
| | 309 | int tPoly_getKey (tPoly* const poly, uint8_t voice); |
| | 310 | int tPoly_getVelocity (tPoly* const poly, uint8_t voice); |
| | 311 | int tPoly_isOn (tPoly* const poly, uint8_t voice); |
| | 312 | void tPoly_setSampleRate (tPoly* const poly, float sr); |
| | 313 | |
| | 314 | //============================================================================== |
| | 315 | |
| | 316 | /*! @} |
| | 317 | @defgroup tsimplepoly tSimplePoly |
| | 318 | @ingroup midi |
| | 319 | @brief Polyphony handler. |
| | 320 | @{ |
| | 321 | |
| | 322 | @fn void tSimplePoly_init (tSimplePoly* const poly, int maxNumVoices, LEAF* const leaf) |
| | 323 | @brief Initialize a tSimplePoly to the default mempool of a LEAF instance. |
| | 324 | @param poly A pointer to the tSimplePoly to initialize. |
| | 325 | @param maxNumVoices The maximum number of voices this tSimplePoly can handle at once. |
| | 326 | @param leaf A pointer to the leaf instance. |
| | 327 | |
| | 328 | @fn void tSimplePoly_initToPool (tSimplePoly* const poly, int maxNumVoices, tMempool* const pool) |
| | 329 | @brief Initialize a tSimplePoly to a specified mempool. |
| | 330 | @param poly A pointer to the tSimplePoly to initialize. |
| | 331 | @param mempool A pointer to the tMempool to use. |
| | 332 | |
| | 333 | @fn void tSimplePoly_free (tSimplePoly* const poly) |
| | 334 | @brief Free a tSimplePoly from its mempool. |
| | 335 | @param poly A pointer to the tSimplePoly to free. |
| | 336 | |
| | 337 | @fn int tSimplePoly_noteOn (tSimplePoly* const poly, int note, uint8_t vel) |
| | 338 | @brief Add a note with a given velocity to the poly handler. |
| | 339 | @param poly A pointer to the relevant tSimplePoly. |
| | 340 | @param note The MIDI note number to add. |
| | 341 | @param vel The MIDI velocity of the note to add. |
| | 342 | @return The voice that will play the note. |
| | 343 | |
| | 344 | @fn int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note) |
| | 345 | @brief Remove a note from the poly handler. |
| | 346 | @param poly A pointer to the relevant tSimplePoly. |
| | 347 | @param note The MIDI note number to remove. |
| | 348 | @return The voice that was playing the removed note. |
| | 349 | |
| | 350 | @fn void tSimplePoly_deactivateVoice(tSimplePoly* const polyh, uint8_t voice) |
| | 351 | @brief |
| | 352 | @param |
| | 353 | |
| | 354 | @fn int tSimplePoly_markPendingNoteOff(tSimplePoly* const polyh, uint8_t note) |
| | 355 | @brief |
| | 356 | @param |
| | 357 | |
| | 358 | @fn int tSimplePoly_findVoiceAssignedToNote(tSimplePoly* const polyh, uint8_t note) |
| | 359 | @brief Find if there is a voice with that note -- useful for note offs where you want to wait to remove it from the poly until the release phase of the envelope is finished |
| | 360 | @param |
| | 361 | |
| | 362 | @fn void tSimplePoly_setNumVoices (tSimplePoly* const poly, uint8_t numVoices) |
| | 363 | @brief Set the number of voices available to play notes. |
| | 364 | @param poly A pointer to the relevant tSimplePoly. |
| | 365 | @param numVoices The new number of available voices. Cannot be greater than the max number voices given on initialization. |
| | 366 | |
| | 367 | @fn int tSimplePoly_getNumVoices (tSimplePoly* const poly) |
| | 368 | @brief Get the current number of voices available to play notes. |
| | 369 | @param poly A pointer to the relevant tSimplePoly. |
| | 370 | @return The current number of voices available to play notes. |
| | 371 | |
| | 372 | @fn int tSimplePoly_getNumActiveVoices (tSimplePoly* const poly) |
| | 373 | @brief Get the number of voices currently playing notes. |
| | 374 | @param poly A pointer to the relevant tSimplePoly. |
| | 375 | @return The number of voices currently playing notes. |
| | 376 | |
| | 377 | @fn int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice) |
| | 378 | @brief Get the current MIDI note number of a given voice. |
| | 379 | @param poly A pointer to the relevant tSimplePoly. |
| | 380 | @param voice The voice to get the MIDI note number of. |
| | 381 | @return The MIDI note number of the given voice. |
| | 382 | |
| | 383 | @fn int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice) |
| | 384 | @brief Returns negative one if the voice is inactive |
| | 385 | |
| | 386 | @fn int tSimplePoly_getVelocity (tSimplePoly* const poly, uint8_t voice) |
| | 387 | @brief Get the current MIDI velocity of a given voice. |
| | 388 | @param poly A pointer to the relevant tSimplePoly. |
| | 389 | @param voice The voice to get the MIDI velocity of. |
| | 390 | @return The current MIDI velocity of the given voice. |
| | 391 | |
| | 392 | @fn int tSimplePoly_isOn (tSimplePoly* const poly, uint8_t voice) |
| | 393 | @brief Get the current play state of a given voice. |
| | 394 | @param poly A pointer to the relevant tSimplePoly. |
| | 395 | @param voice The voice to get the state of. |
| | 396 | @return The current play state of the given voice. |
| | 397 | |
| | 398 | @} */ |
| | 399 | typedef struct _tSimplePoly |
| | 400 | { |
| | 401 | tMempool mempool; |
| | 402 | |
| | 403 | tStack stack; |
| | 404 | |
| | 405 | int numVoices; |
| | 406 | int maxNumVoices; |
| | 407 | int** voices; |
| | 408 | int stealing_on; |
| | 409 | int recover_stolen; |
| | 410 | |
| | 411 | int notes[128][2]; |
| | 412 | } _tSimplePoly; |
| | 413 | |
| | 414 | typedef _tSimplePoly* tSimplePoly; |
| | 415 | |
| | 416 | void tSimplePoly_init (tSimplePoly* const poly, int maxNumVoices, LEAF* const leaf); |
| | 417 | void tSimplePoly_initToPool (tSimplePoly* const poly, int maxNumVoices, tMempool* const pool); |
| | 418 | void tSimplePoly_free (tSimplePoly* const poly); |
| | 419 | |
| | 420 | int tSimplePoly_noteOn (tSimplePoly* const poly, int note, uint8_t vel); |
| | 421 | int tSimplePoly_noteOff (tSimplePoly* const poly, uint8_t note); |
| | 422 | void tSimplePoly_deactivateVoice (tSimplePoly* const polyh, uint8_t voice); |
| | 423 | int tSimplePoly_markPendingNoteOff (tSimplePoly* const polyh, uint8_t note); |
| | 424 | int tSimplePoly_findVoiceAssignedToNote (tSimplePoly* const polyh, uint8_t note); |
| | 425 | void tSimplePoly_setNumVoices (tSimplePoly* const poly, uint8_t numVoices); |
| | 426 | int tSimplePoly_getNumVoices (tSimplePoly* const poly); |
| | 427 | int tSimplePoly_getNumActiveVoices (tSimplePoly* const poly); |
| | 428 | int tSimplePoly_getPitch (tSimplePoly* const poly, uint8_t voice); |
| | 429 | int tSimplePoly_getPitchAndCheckActive(tSimplePoly* const polyh, uint8_t voice); |
| | 430 | int tSimplePoly_getVelocity (tSimplePoly* const poly, uint8_t voice); |
| | 431 | int tSimplePoly_isOn (tSimplePoly* const poly, uint8_t voice); |
| | 432 | |
| | 433 | //============================================================================== |
| | 434 | |
| | 435 | #ifdef __cplusplus |
| | 436 | } |
| | 437 | #endif |
| | 438 | |
| | 439 | #endif // LEAF_MIDI_H_INCLUDED |
| | 440 | |
| | 441 | //============================================================================== |
| | 442 | |
| | 443 | |