1 /* FluidSynth - A Software Synthesizer 2 * 3 * Copyright (C) 2003 Peter Hanappe and others. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public License 7 * as published by the Free Software Foundation; either version 2.1 of 8 * the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free 17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA 19 */ 20 21 #ifndef _FLUID_MIDI_H 22 #define _FLUID_MIDI_H 23 24 #include "fluidsynth_priv.h" 25 #include "fluid_sys.h" 26 #include "fluid_list.h" 27 28 typedef struct _fluid_midi_parser_t fluid_midi_parser_t; 29 30 fluid_midi_parser_t *new_fluid_midi_parser(void); 31 void delete_fluid_midi_parser(fluid_midi_parser_t *parser); 32 fluid_midi_event_t *fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c); 33 34 35 /*************************************************************** 36 * 37 * CONSTANTS & ENUM 38 */ 39 40 41 #define MAX_NUMBER_OF_TRACKS 128 42 43 enum fluid_midi_event_type 44 { 45 /* channel messages */ 46 NOTE_OFF = 0x80, 47 NOTE_ON = 0x90, 48 KEY_PRESSURE = 0xa0, 49 CONTROL_CHANGE = 0xb0, 50 PROGRAM_CHANGE = 0xc0, 51 CHANNEL_PRESSURE = 0xd0, 52 PITCH_BEND = 0xe0, 53 /* system exclusive */ 54 MIDI_SYSEX = 0xf0, 55 /* system common - never in midi files */ 56 MIDI_TIME_CODE = 0xf1, 57 MIDI_SONG_POSITION = 0xf2, 58 MIDI_SONG_SELECT = 0xf3, 59 MIDI_TUNE_REQUEST = 0xf6, 60 MIDI_EOX = 0xf7, 61 /* system real-time - never in midi files */ 62 MIDI_SYNC = 0xf8, 63 MIDI_TICK = 0xf9, 64 MIDI_START = 0xfa, 65 MIDI_CONTINUE = 0xfb, 66 MIDI_STOP = 0xfc, 67 MIDI_ACTIVE_SENSING = 0xfe, 68 MIDI_SYSTEM_RESET = 0xff, 69 /* meta event - for midi files only */ 70 MIDI_META_EVENT = 0xff 71 }; 72 73 enum fluid_midi_control_change 74 { 75 BANK_SELECT_MSB = 0x00, 76 MODULATION_MSB = 0x01, 77 BREATH_MSB = 0x02, 78 FOOT_MSB = 0x04, 79 PORTAMENTO_TIME_MSB = 0x05, 80 DATA_ENTRY_MSB = 0x06, 81 VOLUME_MSB = 0x07, 82 BALANCE_MSB = 0x08, 83 PAN_MSB = 0x0A, 84 EXPRESSION_MSB = 0x0B, 85 EFFECTS1_MSB = 0x0C, 86 EFFECTS2_MSB = 0x0D, 87 GPC1_MSB = 0x10, /* general purpose controller */ 88 GPC2_MSB = 0x11, 89 GPC3_MSB = 0x12, 90 GPC4_MSB = 0x13, 91 BANK_SELECT_LSB = 0x20, 92 MODULATION_WHEEL_LSB = 0x21, 93 BREATH_LSB = 0x22, 94 FOOT_LSB = 0x24, 95 PORTAMENTO_TIME_LSB = 0x25, 96 DATA_ENTRY_LSB = 0x26, 97 VOLUME_LSB = 0x27, 98 BALANCE_LSB = 0x28, 99 PAN_LSB = 0x2A, 100 EXPRESSION_LSB = 0x2B, 101 EFFECTS1_LSB = 0x2C, 102 EFFECTS2_LSB = 0x2D, 103 GPC1_LSB = 0x30, 104 GPC2_LSB = 0x31, 105 GPC3_LSB = 0x32, 106 GPC4_LSB = 0x33, 107 SUSTAIN_SWITCH = 0x40, 108 PORTAMENTO_SWITCH = 0x41, 109 SOSTENUTO_SWITCH = 0x42, 110 SOFT_PEDAL_SWITCH = 0x43, 111 LEGATO_SWITCH = 0x44, 112 HOLD2_SWITCH = 0x45, 113 SOUND_CTRL1 = 0x46, 114 SOUND_CTRL2 = 0x47, 115 SOUND_CTRL3 = 0x48, 116 SOUND_CTRL4 = 0x49, 117 SOUND_CTRL5 = 0x4A, 118 SOUND_CTRL6 = 0x4B, 119 SOUND_CTRL7 = 0x4C, 120 SOUND_CTRL8 = 0x4D, 121 SOUND_CTRL9 = 0x4E, 122 SOUND_CTRL10 = 0x4F, 123 GPC5 = 0x50, 124 GPC6 = 0x51, 125 GPC7 = 0x52, 126 GPC8 = 0x53, 127 PORTAMENTO_CTRL = 0x54, 128 EFFECTS_DEPTH1 = 0x5B, 129 EFFECTS_DEPTH2 = 0x5C, 130 EFFECTS_DEPTH3 = 0x5D, 131 EFFECTS_DEPTH4 = 0x5E, 132 EFFECTS_DEPTH5 = 0x5F, 133 DATA_ENTRY_INCR = 0x60, 134 DATA_ENTRY_DECR = 0x61, 135 NRPN_LSB = 0x62, 136 NRPN_MSB = 0x63, 137 RPN_LSB = 0x64, 138 RPN_MSB = 0x65, 139 ALL_SOUND_OFF = 0x78, 140 ALL_CTRL_OFF = 0x79, 141 LOCAL_CONTROL = 0x7A, 142 ALL_NOTES_OFF = 0x7B, 143 OMNI_OFF = 0x7C, 144 OMNI_ON = 0x7D, 145 POLY_OFF = 0x7E, 146 POLY_ON = 0x7F 147 }; 148 149 /* General MIDI RPN event numbers (LSB, MSB = 0) */ 150 enum midi_rpn_event 151 { 152 RPN_PITCH_BEND_RANGE = 0x00, 153 RPN_CHANNEL_FINE_TUNE = 0x01, 154 RPN_CHANNEL_COARSE_TUNE = 0x02, 155 RPN_TUNING_PROGRAM_CHANGE = 0x03, 156 RPN_TUNING_BANK_SELECT = 0x04, 157 RPN_MODULATION_DEPTH_RANGE = 0x05 158 }; 159 160 enum midi_meta_event 161 { 162 MIDI_TEXT = 0x01, 163 MIDI_COPYRIGHT = 0x02, 164 MIDI_TRACK_NAME = 0x03, 165 MIDI_INST_NAME = 0x04, 166 MIDI_LYRIC = 0x05, 167 MIDI_MARKER = 0x06, 168 MIDI_CUE_POINT = 0x07, 169 MIDI_EOT = 0x2f, 170 MIDI_SET_TEMPO = 0x51, 171 MIDI_SMPTE_OFFSET = 0x54, 172 MIDI_TIME_SIGNATURE = 0x58, 173 MIDI_KEY_SIGNATURE = 0x59, 174 MIDI_SEQUENCER_EVENT = 0x7f 175 }; 176 177 /* MIDI SYSEX useful manufacturer values */ 178 enum midi_sysex_manuf 179 { 180 MIDI_SYSEX_MANUF_ROLAND = 0x41, /**< Roland manufacturer ID */ 181 MIDI_SYSEX_UNIV_NON_REALTIME = 0x7E, /**< Universal non realtime message */ 182 MIDI_SYSEX_UNIV_REALTIME = 0x7F /**< Universal realtime message */ 183 }; 184 185 #define MIDI_SYSEX_DEVICE_ID_ALL 0x7F /**< Device ID used in SYSEX messages to indicate all devices */ 186 187 /* SYSEX sub-ID #1 which follows device ID */ 188 #define MIDI_SYSEX_MIDI_TUNING_ID 0x08 /**< Sysex sub-ID #1 for MIDI tuning messages */ 189 #define MIDI_SYSEX_GM_ID 0x09 /**< Sysex sub-ID #1 for General MIDI messages */ 190 191 /** 192 * SYSEX tuning message IDs. 193 */ 194 enum midi_sysex_tuning_msg_id 195 { 196 MIDI_SYSEX_TUNING_BULK_DUMP_REQ = 0x00, /**< Bulk tuning dump request (non-realtime) */ 197 MIDI_SYSEX_TUNING_BULK_DUMP = 0x01, /**< Bulk tuning dump response (non-realtime) */ 198 MIDI_SYSEX_TUNING_NOTE_TUNE = 0x02, /**< Tuning note change message (realtime) */ 199 MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK = 0x03, /**< Bulk tuning dump request (with bank, non-realtime) */ 200 MIDI_SYSEX_TUNING_BULK_DUMP_BANK = 0x04, /**< Bulk tuning dump resonse (with bank, non-realtime) */ 201 MIDI_SYSEX_TUNING_OCTAVE_DUMP_1BYTE = 0x05, /**< Octave tuning dump using 1 byte values (non-realtime) */ 202 MIDI_SYSEX_TUNING_OCTAVE_DUMP_2BYTE = 0x06, /**< Octave tuning dump using 2 byte values (non-realtime) */ 203 MIDI_SYSEX_TUNING_NOTE_TUNE_BANK = 0x07, /**< Tuning note change message (with bank, realtime/non-realtime) */ 204 MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE = 0x08, /**< Octave tuning message using 1 byte values (realtime/non-realtime) */ 205 MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE = 0x09 /**< Octave tuning message using 2 byte values (realtime/non-realtime) */ 206 }; 207 208 /* General MIDI sub-ID #2 */ 209 #define MIDI_SYSEX_GM_ON 0x01 /**< Enable GM mode */ 210 #define MIDI_SYSEX_GM_OFF 0x02 /**< Disable GM mode */ 211 212 enum fluid_driver_status 213 { 214 FLUID_MIDI_READY, 215 FLUID_MIDI_LISTENING, 216 FLUID_MIDI_DONE 217 }; 218 219 /*************************************************************** 220 * 221 * TYPE DEFINITIONS & FUNCTION DECLARATIONS 222 */ 223 224 /* 225 * fluid_midi_event_t 226 */ 227 struct _fluid_midi_event_t 228 { 229 fluid_midi_event_t *next; /* Link to next event */ 230 void *paramptr; /* Pointer parameter (for SYSEX data), size is stored to param1, param2 indicates if pointer should be freed (dynamic if TRUE) */ 231 unsigned int dtime; /* Delay (ticks) between this and previous event. midi tracks. */ 232 unsigned int param1; /* First parameter */ 233 unsigned int param2; /* Second parameter */ 234 unsigned char type; /* MIDI event type */ 235 unsigned char channel; /* MIDI channel */ 236 }; 237 238 239 /* 240 * fluid_track_t 241 */ 242 struct _fluid_track_t 243 { 244 char *name; 245 int num; 246 fluid_midi_event_t *first; 247 fluid_midi_event_t *cur; 248 fluid_midi_event_t *last; 249 unsigned int ticks; 250 }; 251 252 typedef struct _fluid_track_t fluid_track_t; 253 254 #define fluid_track_eot(track) ((track)->cur == NULL) 255 256 257 /* 258 * fluid_playlist_item 259 * Used as the `data' elements of the fluid_player.playlist. 260 * Represents either a filename or a pre-loaded memory buffer. 261 * Exactly one of `filename' and `buffer' is non-NULL. 262 */ 263 typedef struct 264 { 265 char *filename; /** Name of file (owned); NULL if data pre-loaded */ 266 void *buffer; /** The MIDI file data (owned); NULL if filename */ 267 size_t buffer_len; /** Number of bytes in buffer; 0 if filename */ 268 } fluid_playlist_item; 269 270 /* 271 * fluid_player 272 */ 273 struct _fluid_player_t 274 { 275 int status; 276 int ntracks; 277 fluid_track_t *track[MAX_NUMBER_OF_TRACKS]; 278 fluid_synth_t *synth; 279 fluid_timer_t *system_timer; 280 fluid_sample_timer_t *sample_timer; 281 282 int loop; /* -1 = loop infinitely, otherwise times left to loop the playlist */ 283 fluid_list_t *playlist; /* List of fluid_playlist_item* objects */ 284 fluid_list_t *currentfile; /* points to an item in files, or NULL if not playing */ 285 286 char send_program_change; /* should we ignore the program changes? */ 287 char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */ 288 char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */ 289 int seek_ticks; /* new position in tempo ticks (midi ticks) for seeking */ 290 int start_ticks; /* the number of tempo ticks passed at the last tempo change */ 291 int cur_ticks; /* the number of tempo ticks passed */ 292 int begin_msec; /* the time (msec) of the beginning of the file */ 293 int start_msec; /* the start time of the last tempo change */ 294 int cur_msec; /* the current time */ 295 int miditempo; /* as indicated by MIDI SetTempo: n 24th of a usec per midi-clock. bravo! */ 296 double deltatime; /* milliseconds per midi tick. depends on set-tempo */ 297 unsigned int division; 298 299 handle_midi_event_func_t playback_callback; /* function fired on each midi event as it is played */ 300 void *playback_userdata; /* pointer to user-defined data passed to playback_callback function */ 301 }; 302 303 void fluid_player_settings(fluid_settings_t *settings); 304 305 306 /* 307 * fluid_midi_file 308 */ 309 typedef struct 310 { 311 const char *buffer; /* Entire contents of MIDI file (borrowed) */ 312 int buf_len; /* Length of buffer, in bytes */ 313 int buf_pos; /* Current read position in contents buffer */ 314 int eof; /* The "end of file" condition */ 315 int running_status; 316 int c; 317 int type; 318 int ntracks; 319 int uses_smpte; 320 unsigned int smpte_fps; 321 unsigned int smpte_res; 322 unsigned int division; /* If uses_SMPTE == 0 then division is 323 ticks per beat (quarter-note) */ 324 double tempo; /* Beats per second (SI rules =) */ 325 int tracklen; 326 int trackpos; 327 int eot; 328 int varlen; 329 int dtime; 330 } fluid_midi_file; 331 332 333 334 #define FLUID_MIDI_PARSER_MAX_DATA_SIZE 1024 /**< Maximum size of MIDI parameters/data (largest is SYSEX data) */ 335 336 /* 337 * fluid_midi_parser_t 338 */ 339 struct _fluid_midi_parser_t 340 { 341 unsigned char status; /* Identifies the type of event, that is currently received ('Noteon', 'Pitch Bend' etc). */ 342 unsigned char channel; /* The channel of the event that is received (in case of a channel event) */ 343 unsigned int nr_bytes; /* How many bytes have been read for the current event? */ 344 unsigned int nr_bytes_total; /* How many bytes does the current event type include? */ 345 unsigned char data[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; /* The parameters or SYSEX data */ 346 fluid_midi_event_t event; /* The event, that is returned to the MIDI driver. */ 347 }; 348 349 350 #endif /* _FLUID_MIDI_H */ 351