1 /* 2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org> 3 * 4 * This file is part of Zrythm 5 * 6 * Zrythm is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Affero General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Zrythm is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Affero General Public License for more details. 15 * 16 * You should have received a copy of the GNU Affero General Public License 17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 /** 21 * \file 22 * 23 * API for Region's specific to instrument Track's. 24 */ 25 26 #ifndef __AUDIO_MIDI_REGION_H__ 27 #define __AUDIO_MIDI_REGION_H__ 28 29 #include <stddef.h> 30 #include <stdbool.h> 31 #include <stdint.h> 32 33 #include "utils/types.h" 34 35 typedef struct Track Track; 36 typedef struct Position Position; 37 typedef struct MidiNote MidiNote; 38 typedef struct ZRegion ZRegion; 39 typedef struct MidiEvents MidiEvents; 40 typedef struct ChordDescriptor ChordDescriptor; 41 typedef struct Velocity Velocity; 42 typedef ZRegion MidiRegion; 43 typedef void MIDI_FILE; 44 45 /** 46 * @addtogroup audio 47 * 48 * @{ 49 */ 50 51 /** 52 * Creates a new ZRegion for MIDI notes. 53 */ 54 ZRegion * 55 midi_region_new ( 56 const Position * start_pos, 57 const Position * end_pos, 58 unsigned int track_name_hash, 59 int lane_pos, 60 int idx_inside_lane); 61 62 /** 63 * Creates a MIDI region from the given MIDI 64 * file path, starting at the given Position. 65 * 66 * @param idx The index of this track, starting from 67 * 0. This will be sequential, ie, if idx 1 is 68 * requested and the MIDI file only has tracks 69 * 5 and 7, it will use track 7. 70 */ 71 ZRegion * 72 midi_region_new_from_midi_file ( 73 const Position * start_pos, 74 const char * abs_path, 75 unsigned int track_name_hash, 76 int lane_pos, 77 int idx_inside_lane, 78 int idx); 79 80 /** 81 * Create a region from the chord descriptor. 82 * 83 * Default size will be timeline snap and default 84 * notes size will be editor snap. 85 */ 86 ZRegion * 87 midi_region_new_from_chord_descr ( 88 const Position * pos, 89 ChordDescriptor * descr, 90 unsigned int track_name_hash, 91 int lane_pos, 92 int idx_inside_lane); 93 94 /** 95 * Adds the MidiNote to the given ZRegion. 96 * 97 * @param pub_events Publish UI events or not. 98 */ 99 #define midi_region_add_midi_note( \ 100 region,midi_note,pub_events) \ 101 midi_region_insert_midi_note ( \ 102 region, midi_note, \ 103 ((ZRegion *) (region))->num_midi_notes, \ 104 pub_events) 105 106 /** 107 * Inserts the MidiNote to the given ZRegion. 108 * 109 * @param idx Index to insert at. 110 * @param pub_events Publish UI events or not. 111 */ 112 void 113 midi_region_insert_midi_note ( 114 ZRegion * region, 115 MidiNote * midi_note, 116 int idx, 117 int pub_events); 118 119 /** 120 * Starts an unended note with the given pitch and 121 * velocity and adds it to \ref ZRegion.midi_notes. 122 * 123 * @param end_pos If this is NULL, it will be set to 124 * 1 tick after the start_pos. 125 */ 126 void 127 midi_region_start_unended_note ( 128 ZRegion * self, 129 Position * start_pos, 130 Position * end_pos, 131 int pitch, 132 int vel, 133 int pub_events); 134 135 /** 136 * Returns the midi note with the given pitch from 137 * the unended notes. 138 * 139 * Used when recording. 140 * 141 * @param pitch The pitch. If -1, it returns any 142 * unended note. This is useful when the loop 143 * point is met and we want to end them all. 144 */ 145 MidiNote * 146 midi_region_pop_unended_note ( 147 ZRegion * self, 148 int pitch); 149 150 /** 151 * Fills MIDI event queue from the region. 152 * 153 * The events are dequeued right after the call to 154 * this function. 155 * 156 * @note The caller already splits calls to this 157 * function at each sub-loop inside the region, 158 * so region loop related logic is not needed. 159 * 160 * @param g_start_frames Global start frame. 161 * @param local_start_frame The start frame offset 162 * from 0 in this cycle. 163 * @param nframes Number of frames at start 164 * Position. 165 * @param note_off_at_end Whether a note off should 166 * be added at the end frame (eg, when the caller 167 * knows there is a region loop or the region 168 * ends). 169 * @param midi_events MidiEvents to fill (from 170 * Piano Roll Port for example). 171 */ 172 REALTIME 173 void 174 midi_region_fill_midi_events ( 175 ZRegion * self, 176 long g_start_frames, 177 nframes_t local_start_frame, 178 nframes_t nframes, 179 bool note_off_at_end, 180 MidiEvents * midi_events); 181 182 /** 183 * Prints the MidiNotes in the Region. 184 * 185 * Used for debugging. 186 */ 187 void 188 midi_region_print_midi_notes ( 189 ZRegion * self); 190 191 /** 192 * Gets first midi note 193 */ 194 MidiNote * 195 midi_region_get_first_midi_note ( 196 ZRegion * region); 197 198 /** 199 * Gets last midi note 200 */ 201 MidiNote * 202 midi_region_get_last_midi_note ( 203 ZRegion * region); 204 205 /** 206 * Gets highest midi note 207 */ 208 MidiNote * 209 midi_region_get_highest_midi_note ( 210 ZRegion * region); 211 212 /** 213 * Gets lowest midi note 214 */ 215 MidiNote * 216 midi_region_get_lowest_midi_note ( 217 ZRegion * region); 218 219 /** 220 * Removes the MIDI note from the Region. 221 * 222 * @param free Also free the MidiNote. 223 * @param pub_event Publish an event. 224 */ 225 void 226 midi_region_remove_midi_note ( 227 ZRegion * region, 228 MidiNote * midi_note, 229 int free, 230 int pub_event); 231 232 /** 233 * Removes all MIDI ntoes and their components 234 * completely. 235 */ 236 void 237 midi_region_remove_all_midi_notes ( 238 ZRegion * region); 239 240 241 /** 242 * Returns the midi note at given position with the given 243 * pitch. 244 * 245 * Used when recording. 246 */ 247 //MidiNote * 248 //midi_region_get_midi_note_at ( 249 //ZRegion * self, 250 //Position * pos, 251 //int pitch); 252 253 /** 254 * Exports the ZRegion to an existing MIDI file 255 * instance. 256 * 257 * @param add_region_start Add the region start 258 * offset to the positions. 259 * @param export_full Traverse loops and export the 260 * MIDI file as it would be played inside Zrythm. 261 * If this is 0, only the original region (from 262 * true start to true end) is exported. 263 * @param use_track_pos Whether to use the track 264 * position in the MIDI data. The track will be 265 * set to 1 if false. 266 */ 267 void 268 midi_region_write_to_midi_file ( 269 ZRegion * self, 270 MIDI_FILE * mf, 271 const int add_region_start, 272 bool export_full, 273 bool use_track_pos); 274 275 /** 276 * Exports the ZRegion to a specified MIDI file. 277 * 278 * @param full_path Absolute path to the MIDI file. 279 * @param export_full Traverse loops and export the 280 * MIDI file as it would be played inside Zrythm. 281 * If this is 0, only the original region (from 282 * true start to true end) is exported. 283 */ 284 void 285 midi_region_export_to_midi_file ( 286 ZRegion * self, 287 const char * full_path, 288 int midi_version, 289 const int export_full); 290 291 /** 292 * Returns the MIDI channel that this region should 293 * be played on, starting from 1. 294 */ 295 uint8_t 296 midi_region_get_midi_ch ( 297 const ZRegion * self); 298 299 /** 300 * Returns a newly initialized MidiEvents with 301 * the contents of the region converted into 302 * events. 303 * 304 * Must be free'd with midi_events_free (). 305 * 306 * @param add_region_start Add the region start 307 * offset to the positions. 308 */ 309 MidiEvents * 310 midi_region_get_as_events ( 311 const ZRegion * self, 312 const int add_region_start, 313 const int full); 314 315 /** 316 * Fills in the array with all the velocities in 317 * the project that are within or outside the 318 * range given. 319 * 320 * @param inside Whether to find velocities inside 321 * the range (1) or outside (0). 322 */ 323 void 324 midi_region_get_velocities_in_range ( 325 const ZRegion * self, 326 const Position * start_pos, 327 const Position * end_pos, 328 Velocity *** velocities, 329 int * num_velocities, 330 size_t * velocities_size, 331 int inside); 332 333 /** 334 * Frees members only but not the midi region itself. 335 * 336 * Regions should be free'd using region_free. 337 */ 338 void 339 midi_region_free_members ( 340 ZRegion * self); 341 342 /** 343 * @} 344 */ 345 346 #endif // __AUDIO_MIDI_REGION_H__ 347