mirror of
https://github.com/DrBeef/QuestZDoom.git
synced 2025-03-05 17:10:55 +00:00
335 lines
9.5 KiB
C
335 lines
9.5 KiB
C
/* FluidSynth - A Software Synthesizer
|
|
*
|
|
* Copyright (C) 2003 Peter Hanappe and others.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public License
|
|
* as published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
* 02111-1307, USA
|
|
*/
|
|
|
|
#ifndef _FLUID_MIDI_H
|
|
#define _FLUID_MIDI_H
|
|
|
|
#include "fluidsynth_priv.h"
|
|
#include "fluid_sys.h"
|
|
#include "fluid_list.h"
|
|
|
|
typedef struct _fluid_midi_parser_t fluid_midi_parser_t;
|
|
|
|
fluid_midi_parser_t* new_fluid_midi_parser(void);
|
|
int delete_fluid_midi_parser(fluid_midi_parser_t* parser);
|
|
fluid_midi_event_t* fluid_midi_parser_parse(fluid_midi_parser_t* parser, unsigned char c);
|
|
|
|
int fluid_midi_send_event(fluid_synth_t* synth, fluid_player_t* player, fluid_midi_event_t* evt);
|
|
|
|
|
|
/***************************************************************
|
|
*
|
|
* CONSTANTS & ENUM
|
|
*/
|
|
|
|
|
|
#define MAX_NUMBER_OF_TRACKS 128
|
|
|
|
enum fluid_midi_event_type {
|
|
/* channel messages */
|
|
NOTE_OFF = 0x80,
|
|
NOTE_ON = 0x90,
|
|
KEY_PRESSURE = 0xa0,
|
|
CONTROL_CHANGE = 0xb0,
|
|
PROGRAM_CHANGE = 0xc0,
|
|
CHANNEL_PRESSURE = 0xd0,
|
|
PITCH_BEND = 0xe0,
|
|
/* system exclusive */
|
|
MIDI_SYSEX = 0xf0,
|
|
/* system common - never in midi files */
|
|
MIDI_TIME_CODE = 0xf1,
|
|
MIDI_SONG_POSITION = 0xf2,
|
|
MIDI_SONG_SELECT = 0xf3,
|
|
MIDI_TUNE_REQUEST = 0xf6,
|
|
MIDI_EOX = 0xf7,
|
|
/* system real-time - never in midi files */
|
|
MIDI_SYNC = 0xf8,
|
|
MIDI_TICK = 0xf9,
|
|
MIDI_START = 0xfa,
|
|
MIDI_CONTINUE = 0xfb,
|
|
MIDI_STOP = 0xfc,
|
|
MIDI_ACTIVE_SENSING = 0xfe,
|
|
MIDI_SYSTEM_RESET = 0xff,
|
|
/* meta event - for midi files only */
|
|
MIDI_META_EVENT = 0xff
|
|
};
|
|
|
|
enum fluid_midi_control_change {
|
|
BANK_SELECT_MSB = 0x00,
|
|
MODULATION_MSB = 0x01,
|
|
BREATH_MSB = 0x02,
|
|
FOOT_MSB = 0x04,
|
|
PORTAMENTO_TIME_MSB = 0x05,
|
|
DATA_ENTRY_MSB = 0x06,
|
|
VOLUME_MSB = 0x07,
|
|
BALANCE_MSB = 0x08,
|
|
PAN_MSB = 0x0A,
|
|
EXPRESSION_MSB = 0x0B,
|
|
EFFECTS1_MSB = 0x0C,
|
|
EFFECTS2_MSB = 0x0D,
|
|
GPC1_MSB = 0x10, /* general purpose controller */
|
|
GPC2_MSB = 0x11,
|
|
GPC3_MSB = 0x12,
|
|
GPC4_MSB = 0x13,
|
|
BANK_SELECT_LSB = 0x20,
|
|
MODULATION_WHEEL_LSB = 0x21,
|
|
BREATH_LSB = 0x22,
|
|
FOOT_LSB = 0x24,
|
|
PORTAMENTO_TIME_LSB = 0x25,
|
|
DATA_ENTRY_LSB = 0x26,
|
|
VOLUME_LSB = 0x27,
|
|
BALANCE_LSB = 0x28,
|
|
PAN_LSB = 0x2A,
|
|
EXPRESSION_LSB = 0x2B,
|
|
EFFECTS1_LSB = 0x2C,
|
|
EFFECTS2_LSB = 0x2D,
|
|
GPC1_LSB = 0x30,
|
|
GPC2_LSB = 0x31,
|
|
GPC3_LSB = 0x32,
|
|
GPC4_LSB = 0x33,
|
|
SUSTAIN_SWITCH = 0x40,
|
|
PORTAMENTO_SWITCH = 0x41,
|
|
SOSTENUTO_SWITCH = 0x42,
|
|
SOFT_PEDAL_SWITCH = 0x43,
|
|
LEGATO_SWITCH = 0x45,
|
|
HOLD2_SWITCH = 0x45,
|
|
SOUND_CTRL1 = 0x46,
|
|
SOUND_CTRL2 = 0x47,
|
|
SOUND_CTRL3 = 0x48,
|
|
SOUND_CTRL4 = 0x49,
|
|
SOUND_CTRL5 = 0x4A,
|
|
SOUND_CTRL6 = 0x4B,
|
|
SOUND_CTRL7 = 0x4C,
|
|
SOUND_CTRL8 = 0x4D,
|
|
SOUND_CTRL9 = 0x4E,
|
|
SOUND_CTRL10 = 0x4F,
|
|
GPC5 = 0x50,
|
|
GPC6 = 0x51,
|
|
GPC7 = 0x52,
|
|
GPC8 = 0x53,
|
|
PORTAMENTO_CTRL = 0x54,
|
|
EFFECTS_DEPTH1 = 0x5B,
|
|
EFFECTS_DEPTH2 = 0x5C,
|
|
EFFECTS_DEPTH3 = 0x5D,
|
|
EFFECTS_DEPTH4 = 0x5E,
|
|
EFFECTS_DEPTH5 = 0x5F,
|
|
DATA_ENTRY_INCR = 0x60,
|
|
DATA_ENTRY_DECR = 0x61,
|
|
NRPN_LSB = 0x62,
|
|
NRPN_MSB = 0x63,
|
|
RPN_LSB = 0x64,
|
|
RPN_MSB = 0x65,
|
|
ALL_SOUND_OFF = 0x78,
|
|
ALL_CTRL_OFF = 0x79,
|
|
LOCAL_CONTROL = 0x7A,
|
|
ALL_NOTES_OFF = 0x7B,
|
|
OMNI_OFF = 0x7C,
|
|
OMNI_ON = 0x7D,
|
|
POLY_OFF = 0x7E,
|
|
POLY_ON = 0x7F
|
|
};
|
|
|
|
/* General MIDI RPN event numbers (LSB, MSB = 0) */
|
|
enum midi_rpn_event {
|
|
RPN_PITCH_BEND_RANGE = 0x00,
|
|
RPN_CHANNEL_FINE_TUNE = 0x01,
|
|
RPN_CHANNEL_COARSE_TUNE = 0x02,
|
|
RPN_TUNING_PROGRAM_CHANGE = 0x03,
|
|
RPN_TUNING_BANK_SELECT = 0x04,
|
|
RPN_MODULATION_DEPTH_RANGE = 0x05
|
|
};
|
|
|
|
enum midi_meta_event {
|
|
MIDI_COPYRIGHT = 0x02,
|
|
MIDI_TRACK_NAME = 0x03,
|
|
MIDI_INST_NAME = 0x04,
|
|
MIDI_LYRIC = 0x05,
|
|
MIDI_MARKER = 0x06,
|
|
MIDI_CUE_POINT = 0x07,
|
|
MIDI_EOT = 0x2f,
|
|
MIDI_SET_TEMPO = 0x51,
|
|
MIDI_SMPTE_OFFSET = 0x54,
|
|
MIDI_TIME_SIGNATURE = 0x58,
|
|
MIDI_KEY_SIGNATURE = 0x59,
|
|
MIDI_SEQUENCER_EVENT = 0x7f
|
|
};
|
|
|
|
enum fluid_player_status
|
|
{
|
|
FLUID_PLAYER_READY,
|
|
FLUID_PLAYER_PLAYING,
|
|
FLUID_PLAYER_DONE
|
|
};
|
|
|
|
enum fluid_driver_status
|
|
{
|
|
FLUID_MIDI_READY,
|
|
FLUID_MIDI_LISTENING,
|
|
FLUID_MIDI_DONE
|
|
};
|
|
|
|
/***************************************************************
|
|
*
|
|
* TYPE DEFINITIONS & FUNCTION DECLARATIONS
|
|
*/
|
|
|
|
/* From ctype.h */
|
|
#define fluid_isascii(c) (((c) & ~0x7f) == 0)
|
|
|
|
|
|
|
|
/*
|
|
* fluid_midi_event_t
|
|
*/
|
|
struct _fluid_midi_event_t {
|
|
fluid_midi_event_t* next; /* Don't use it, it will dissappear. Used in midi tracks. */
|
|
unsigned int dtime; /* Delay (ticks) between this and previous event. midi tracks. */
|
|
unsigned char type; /* MIDI event type */
|
|
unsigned char channel; /* MIDI channel */
|
|
unsigned int param1; /* First parameter */
|
|
unsigned int param2; /* Second parameter */
|
|
};
|
|
|
|
|
|
/*
|
|
* fluid_track_t
|
|
*/
|
|
struct _fluid_track_t {
|
|
char* name;
|
|
int num;
|
|
fluid_midi_event_t *first;
|
|
fluid_midi_event_t *cur;
|
|
fluid_midi_event_t *last;
|
|
unsigned int ticks;
|
|
};
|
|
|
|
typedef struct _fluid_track_t fluid_track_t;
|
|
|
|
fluid_track_t* new_fluid_track(int num);
|
|
int delete_fluid_track(fluid_track_t* track);
|
|
int fluid_track_set_name(fluid_track_t* track, char* name);
|
|
char* fluid_track_get_name(fluid_track_t* track);
|
|
int fluid_track_add_event(fluid_track_t* track, fluid_midi_event_t* evt);
|
|
fluid_midi_event_t* fluid_track_first_event(fluid_track_t* track);
|
|
fluid_midi_event_t* fluid_track_next_event(fluid_track_t* track);
|
|
int fluid_track_get_duration(fluid_track_t* track);
|
|
int fluid_track_reset(fluid_track_t* track);
|
|
|
|
int fluid_track_send_events(fluid_track_t* track,
|
|
fluid_synth_t* synth,
|
|
fluid_player_t* player,
|
|
unsigned int ticks);
|
|
|
|
#define fluid_track_eot(track) ((track)->cur == NULL)
|
|
|
|
|
|
/*
|
|
* fluid_player
|
|
*/
|
|
struct _fluid_player_t {
|
|
int status;
|
|
int loop;
|
|
int ntracks;
|
|
fluid_track_t *track[MAX_NUMBER_OF_TRACKS];
|
|
fluid_synth_t* synth;
|
|
fluid_timer_t* timer;
|
|
fluid_list_t* playlist;
|
|
char* current_file;
|
|
char send_program_change; /* should we ignore the program changes? */
|
|
int start_ticks; /* the number of tempo ticks passed at the last tempo change */
|
|
int cur_ticks; /* the number of tempo ticks passed */
|
|
int begin_msec; /* the time (msec) of the beginning of the file */
|
|
int start_msec; /* the start time of the last tempo change */
|
|
int cur_msec; /* the current time */
|
|
int miditempo; /* as indicated by MIDI SetTempo: n 24th of a usec per midi-clock. bravo! */
|
|
double deltatime; /* milliseconds per midi tick. depends on set-tempo */
|
|
unsigned int division;
|
|
};
|
|
|
|
int fluid_player_add_track(fluid_player_t* player, fluid_track_t* track);
|
|
int fluid_player_callback(void* data, unsigned int msec);
|
|
int fluid_player_count_tracks(fluid_player_t* player);
|
|
fluid_track_t* fluid_player_get_track(fluid_player_t* player, int i);
|
|
int fluid_player_reset(fluid_player_t* player);
|
|
int fluid_player_load(fluid_player_t* player, char *filename);
|
|
|
|
|
|
/*
|
|
* fluid_midi_file
|
|
*/
|
|
typedef struct {
|
|
fluid_file fp;
|
|
int running_status;
|
|
int c;
|
|
int type;
|
|
int ntracks;
|
|
int uses_smpte;
|
|
unsigned int smpte_fps;
|
|
unsigned int smpte_res;
|
|
unsigned int division; /* If uses_SMPTE == 0 then division is
|
|
ticks per beat (quarter-note) */
|
|
double tempo; /* Beats per second (SI rules =) */
|
|
int tracklen;
|
|
int trackpos;
|
|
int eot;
|
|
int varlen;
|
|
int dtime;
|
|
} fluid_midi_file;
|
|
|
|
fluid_midi_file* new_fluid_midi_file(char* filename);
|
|
void delete_fluid_midi_file(fluid_midi_file* mf);
|
|
int fluid_midi_file_read_mthd(fluid_midi_file* midifile);
|
|
int fluid_midi_file_load_tracks(fluid_midi_file* midifile, fluid_player_t* player);
|
|
int fluid_midi_file_read_track(fluid_midi_file* mf, fluid_player_t* player, int num);
|
|
int fluid_midi_file_read_event(fluid_midi_file* mf, fluid_track_t* track);
|
|
int fluid_midi_file_read_varlen(fluid_midi_file* mf);
|
|
int fluid_midi_file_getc(fluid_midi_file* mf);
|
|
int fluid_midi_file_push(fluid_midi_file* mf, int c);
|
|
int fluid_midi_file_read(fluid_midi_file* mf, void* buf, int len);
|
|
int fluid_midi_file_skip(fluid_midi_file* mf, int len);
|
|
int fluid_midi_file_read_tracklen(fluid_midi_file* mf);
|
|
int fluid_midi_file_eot(fluid_midi_file* mf);
|
|
int fluid_midi_file_get_division(fluid_midi_file* midifile);
|
|
int fluid_midi_event_length(unsigned char status);
|
|
|
|
/* How many parameters may a MIDI event have? */
|
|
#define FLUID_MIDI_PARSER_MAX_PAR 3
|
|
|
|
/*
|
|
* fluid_midi_parser_t
|
|
*/
|
|
struct _fluid_midi_parser_t {
|
|
unsigned char status; /* Identifies the type of event, that is currently received ('Noteon', 'Pitch Bend' etc). */
|
|
unsigned char channel; /* The channel of the event that is received (in case of a channel event) */
|
|
unsigned int nr_bytes; /* How many bytes have been read for the current event? */
|
|
unsigned int nr_bytes_total; /* How many bytes does the current event type include? */
|
|
unsigned short p[FLUID_MIDI_PARSER_MAX_PAR]; /* The parameters */
|
|
fluid_midi_event_t event; /* The event, that is returned to the MIDI driver. */
|
|
};
|
|
|
|
int fluid_isasciistring(char* s);
|
|
long fluid_getlength(unsigned char *s);
|
|
|
|
|
|
|
|
int fluid_midi_router_send_event(fluid_midi_router_t* router, fluid_midi_event_t* event);
|
|
|
|
|
|
#endif /* _FLUID_MIDI_H */
|