1 /* 2 * Copyright (C) 2018-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 MIDI notes in the PianoRoll. 24 */ 25 26 #ifndef __AUDIO_MIDI_NOTE_H__ 27 #define __AUDIO_MIDI_NOTE_H__ 28 29 #include <stdint.h> 30 31 #include "audio/midi_region.h" 32 #include "audio/position.h" 33 #include "audio/velocity.h" 34 #include "gui/backend/arranger_object.h" 35 36 typedef struct _MidiNoteWidget MidiNoteWidget; 37 typedef struct Channel Channel; 38 typedef struct Track Track; 39 typedef struct MidiEvents MidiEvents; 40 typedef struct Position Position; 41 typedef struct Velocity Velocity; 42 43 /** 44 * @addtogroup audio 45 * 46 * @{ 47 */ 48 49 #define MIDI_NOTE_SCHEMA_VERSION 1 50 51 #define MIDI_NOTE_MAGIC 3588791 52 #define IS_MIDI_NOTE(tr) \ 53 ((MidiNote *) tr && \ 54 ((MidiNote *) tr)->magic == MIDI_NOTE_MAGIC) 55 56 #define midi_note_is_selected(r) \ 57 arranger_object_is_selected ( \ 58 (ArrangerObject *) r) 59 60 /** 61 * A MIDI note inside a ZRegion shown in the 62 * piano roll. 63 */ 64 typedef struct MidiNote 65 { 66 /** Base struct. */ 67 ArrangerObject base; 68 69 int schema_version; 70 71 /** Velocity. */ 72 Velocity * vel; 73 74 /** The note/pitch, (0-127). */ 75 uint8_t val; 76 77 /** Cached note, for live operations. */ 78 uint8_t cache_val; 79 80 /** Muted or not */ 81 int muted; 82 83 /** Whether or not this note is currently 84 * listened to */ 85 int currently_listened; 86 87 /** The note/pitch that is currently playing, 88 * if \ref MidiNote.currently_listened is true. */ 89 uint8_t last_listened_val; 90 91 /** Index in the parent region. */ 92 int pos; 93 94 int magic; 95 96 /** Cache layout for drawing the name. */ 97 PangoLayout * layout; 98 } MidiNote; 99 100 static const cyaml_schema_field_t 101 midi_note_fields_schema[] = 102 { 103 YAML_FIELD_MAPPING_EMBEDDED ( 104 MidiNote, base, 105 arranger_object_fields_schema), 106 YAML_FIELD_INT (MidiNote, schema_version), 107 YAML_FIELD_MAPPING_PTR ( 108 MidiNote, vel, velocity_fields_schema), 109 YAML_FIELD_UINT (MidiNote, val), 110 YAML_FIELD_INT (MidiNote, muted), 111 YAML_FIELD_INT (MidiNote, pos), 112 CYAML_FIELD_END 113 }; 114 115 static const cyaml_schema_value_t 116 midi_note_schema = 117 { 118 /* allow nullable for mn_r1 in 119 * ArrangerSelectionsAction */ 120 CYAML_VALUE_MAPPING ( 121 CYAML_FLAG_POINTER_NULL_STR, 122 MidiNote, midi_note_fields_schema), 123 }; 124 125 /** 126 * Gets the global Position of the MidiNote's 127 * start_pos. 128 * 129 * @param pos Position to fill in. 130 */ 131 void 132 midi_note_get_global_start_pos ( 133 MidiNote * self, 134 Position * pos); 135 136 /** 137 * Creates a new MidiNote. 138 */ 139 MidiNote * 140 midi_note_new ( 141 RegionIdentifier * region_id, 142 Position * start_pos, 143 Position * end_pos, 144 uint8_t val, 145 uint8_t vel); 146 147 /** 148 * Sets the region the MidiNote belongs to. 149 */ 150 void 151 midi_note_set_region_and_index ( 152 MidiNote * self, 153 ZRegion * region, 154 int idx); 155 156 void 157 midi_note_set_cache_val ( 158 MidiNote * self, 159 const uint8_t val); 160 161 /** 162 * Returns 1 if the MidiNotes match, 0 if not. 163 */ 164 int 165 midi_note_is_equal ( 166 MidiNote * src, 167 MidiNote * dest); 168 169 /** 170 * Gets the MIDI note's value as a string (eg 171 * "C#4"). 172 * 173 * @param use_markup Use markup to show the octave 174 * as a superscript. 175 */ 176 void 177 midi_note_get_val_as_string ( 178 MidiNote * self, 179 char * buf, 180 const int use_markup); 181 182 /** 183 * For debugging. 184 */ 185 void 186 midi_note_print ( 187 MidiNote * mn); 188 189 /** 190 * Listen to the given MidiNote. 191 * 192 * @param listen Turn note on if 1, or turn it 193 * off if 0. 194 */ 195 void 196 midi_note_listen ( 197 MidiNote * mn, 198 bool listen); 199 200 /** 201 * Shifts MidiNote's position and/or value. 202 * 203 * @param delta Y (0-127) 204 */ 205 void 206 midi_note_shift_pitch ( 207 MidiNote * self, 208 const int delta); 209 210 /** 211 * Returns if the MIDI note is hit at given pos (in 212 * the timeline). 213 */ 214 int 215 midi_note_hit ( 216 MidiNote * midi_note, 217 const long gframes); 218 219 /** 220 * Converts an array of MIDI notes to MidiEvents. 221 * 222 * @param midi_notes Array of MidiNote's. 223 * @param num_notes Number of notes in array. 224 * @param pos Position to offset time from. 225 * @param events Preallocated struct to fill. 226 */ 227 void 228 midi_note_notes_to_events ( 229 MidiNote ** midi_notes, 230 int num_notes, 231 Position * pos, 232 MidiEvents * events); 233 234 /** 235 * Sends a note off if currently playing and sets 236 * the pitch of the MidiNote. 237 */ 238 void 239 midi_note_set_val ( 240 MidiNote * midi_note, 241 const uint8_t val); 242 243 ZRegion * 244 midi_note_get_region ( 245 MidiNote * self); 246 247 /** 248 * @} 249 */ 250 251 #endif // __AUDIO_MIDI_NOTE_H__ 252