/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2004 Masanao Izumo Copyright (C) 1995 Tuukka Toivonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA playmidi.h */ #ifndef ___PLAYMIDI_H_ #define ___PLAYMIDI_H_ #include namespace TimidityPlus { struct AlternateAssign; struct MidiEvent { uint8_t type, channel, a, b; }; #define REDUCE_CHANNELS 16 #define REVERB_MAX_DELAY_OUT (4 * playback_rate) #define SYSEX_TAG 0xFF /* Midi events */ enum midi_event_t { ME_NONE, /* MIDI events */ ME_NOTEOFF, ME_NOTEON, ME_KEYPRESSURE, ME_PROGRAM, ME_CHANNEL_PRESSURE, ME_PITCHWHEEL, /* Controls */ ME_TONE_BANK_MSB, ME_TONE_BANK_LSB, ME_MODULATION_WHEEL, ME_BREATH, ME_FOOT, ME_MAINVOLUME, ME_BALANCE, ME_PAN, ME_EXPRESSION, ME_SUSTAIN, ME_PORTAMENTO_TIME_MSB, ME_PORTAMENTO_TIME_LSB, ME_PORTAMENTO, ME_PORTAMENTO_CONTROL, ME_DATA_ENTRY_MSB, ME_DATA_ENTRY_LSB, ME_SOSTENUTO, ME_SOFT_PEDAL, ME_LEGATO_FOOTSWITCH, ME_HOLD2, ME_HARMONIC_CONTENT, ME_RELEASE_TIME, ME_ATTACK_TIME, ME_BRIGHTNESS, ME_REVERB_EFFECT, ME_TREMOLO_EFFECT, ME_CHORUS_EFFECT, ME_CELESTE_EFFECT, ME_PHASER_EFFECT, ME_RPN_INC, ME_RPN_DEC, ME_NRPN_LSB, ME_NRPN_MSB, ME_RPN_LSB, ME_RPN_MSB, ME_ALL_SOUNDS_OFF, ME_RESET_CONTROLLERS, ME_ALL_NOTES_OFF, ME_MONO, ME_POLY, /* TiMidity Extensionals */ ME_MASTER_TUNING, /* Master tuning */ ME_SCALE_TUNING, /* Scale tuning */ ME_BULK_TUNING_DUMP, /* Bulk tuning dump */ ME_SINGLE_NOTE_TUNING, /* Single-note tuning */ ME_RANDOM_PAN, ME_SET_PATCH, /* Install special instrument */ ME_DRUMPART, ME_KEYSHIFT, ME_PATCH_OFFS, /* Change special instrument sample position * Channel, LSB, MSB */ /* Global channel events */ ME_TEMPO, ME_CHORUS_TEXT, ME_LYRIC, ME_GSLCD, /* GS L.C.D. Exclusive message event */ ME_MARKER, ME_INSERT_TEXT, /* for SC */ ME_TEXT, ME_KARAOKE_LYRIC, /* for KAR format */ ME_MASTER_VOLUME, ME_RESET, /* Reset and change system mode */ ME_NOTE_STEP, ME_TIMESIG, /* Time signature */ ME_KEYSIG, /* Key signature */ ME_TEMPER_KEYSIG, /* Temperament key signature */ ME_TEMPER_TYPE, /* Temperament type */ ME_MASTER_TEMPER_TYPE, /* Master temperament type */ ME_USER_TEMPER_ENTRY, /* User-defined temperament entry */ ME_SYSEX_LSB, /* Universal system exclusive message (LSB) */ ME_SYSEX_MSB, /* Universal system exclusive message (MSB) */ ME_SYSEX_GS_LSB, /* GS system exclusive message (LSB) */ ME_SYSEX_GS_MSB, /* GS system exclusive message (MSB) */ ME_SYSEX_XG_LSB, /* XG system exclusive message (LSB) */ ME_SYSEX_XG_MSB, /* XG system exclusive message (MSB) */ ME_WRD, /* for MIMPI WRD tracer */ ME_SHERRY, /* for Sherry WRD tracer */ ME_BARMARKER, ME_STEP, /* for Metronome */ ME_LAST = 254, /* Last sequence of MIDI list. * This event is reserved for realtime player. */ ME_EOT = 255 /* End of MIDI. Finish to play */ }; #define GLOBAL_CHANNEL_EVENT_TYPE(type) \ ((type) == ME_NONE || (type) >= ME_TEMPO) enum rpn_data_address_t /* NRPN/RPN */ { NRPN_ADDR_0108, NRPN_ADDR_0109, NRPN_ADDR_010A, NRPN_ADDR_0120, NRPN_ADDR_0121, NRPN_ADDR_0130, NRPN_ADDR_0131, NRPN_ADDR_0134, NRPN_ADDR_0135, NRPN_ADDR_0163, NRPN_ADDR_0164, NRPN_ADDR_0166, NRPN_ADDR_1400, NRPN_ADDR_1500, NRPN_ADDR_1600, NRPN_ADDR_1700, NRPN_ADDR_1800, NRPN_ADDR_1900, NRPN_ADDR_1A00, NRPN_ADDR_1C00, NRPN_ADDR_1D00, NRPN_ADDR_1E00, NRPN_ADDR_1F00, NRPN_ADDR_3000, NRPN_ADDR_3100, NRPN_ADDR_3400, NRPN_ADDR_3500, RPN_ADDR_0000, RPN_ADDR_0001, RPN_ADDR_0002, RPN_ADDR_0003, RPN_ADDR_0004, RPN_ADDR_0005, RPN_ADDR_7F7F, RPN_ADDR_FFFF, RPN_MAX_DATA_ADDR }; #define RX_PITCH_BEND (1<<0) #define RX_CH_PRESSURE (1<<1) #define RX_PROGRAM_CHANGE (1<<2) #define RX_CONTROL_CHANGE (1<<3) #define RX_POLY_PRESSURE (1<<4) #define RX_NOTE_MESSAGE (1<<5) #define RX_RPN (1<<6) #define RX_NRPN (1<<7) #define RX_MODULATION (1<<8) #define RX_VOLUME (1<<9) #define RX_PANPOT (1<<10) #define RX_EXPRESSION (1<<11) #define RX_HOLD1 (1<<12) #define RX_PORTAMENTO (1<<13) #define RX_SOSTENUTO (1<<14) #define RX_SOFT (1<<15) #define RX_NOTE_ON (1<<16) #define RX_NOTE_OFF (1<<17) #define RX_BANK_SELECT (1<<18) #define RX_BANK_SELECT_LSB (1<<19) enum { EG_ATTACK = 0, EG_DECAY = 2, EG_DECAY1 = 1, EG_DECAY2 = 2, EG_RELEASE = 3, EG_NULL = 5, EG_GUS_ATTACK = 0, EG_GUS_DECAY = 1, EG_GUS_SUSTAIN = 2, EG_GUS_RELEASE1 = 3, EG_GUS_RELEASE2 = 4, EG_GUS_RELEASE3 = 5, EG_SF_ATTACK = 0, EG_SF_HOLD = 1, EG_SF_DECAY = 2, EG_SF_RELEASE = 3, }; #ifndef PART_EQ_XG #define PART_EQ_XG /*! shelving filter */ struct filter_shelving { double freq, gain, q; int32_t x1l, x2l, y1l, y2l, x1r, x2r, y1r, y2r; int32_t a1, a2, b0, b1, b2; }; /*! Part EQ (XG) */ struct part_eq_xg { int8_t bass, treble, bass_freq, treble_freq; filter_shelving basss, trebles; int8_t valid; }; #endif /* PART_EQ_XG */ struct midi_controller { int16_t val; int8_t pitch; /* in +-semitones [-24, 24] */ int16_t cutoff; /* in +-cents [-9600, 9600] */ float amp; /* [-1.0, 1.0] */ /* in GS, LFO1 means LFO for voice 1, LFO2 means LFO for voice2. LFO2 is not supported. */ float lfo1_rate, lfo2_rate; /* in +-Hz [-10.0, 10.0] */ int16_t lfo1_pitch_depth, lfo2_pitch_depth; /* in cents [0, 600] */ int16_t lfo1_tvf_depth, lfo2_tvf_depth; /* in cents [0, 2400] */ float lfo1_tva_depth, lfo2_tva_depth; /* [0, 1.0] */ int8_t variation_control_depth, insertion_control_depth; }; struct DrumPartEffect { int32_t *buf; int8_t note, reverb_send, chorus_send, delay_send; }; struct DrumParts { int8_t drum_panning; int32_t drum_envelope_rate[6]; /* drum instrument envelope */ int8_t pan_random; /* flag for drum random pan */ float drum_level; int8_t chorus_level, reverb_level, delay_level, coarse, fine, play_note, drum_cutoff_freq, drum_resonance; int32_t rx; }; struct Channel { int8_t bank_msb, bank_lsb, bank, program, volume, expression, sustain, panning, mono, portamento, key_shift, loop_timeout; /* chorus, reverb... Coming soon to a 300-MHz, eight-way superscalar processor near you */ int8_t chorus_level, /* Chorus level */ reverb_level; /* Reverb level. */ int reverb_id; /* Reverb ID used for reverb optimize implementation >=0 reverb_level -1: DEFAULT_REVERB_SEND_LEVEL */ int8_t delay_level; /* Delay Send Level */ int8_t eq_gs; /* EQ ON/OFF (GS) */ int8_t insertion_effect; /* Special sample ID. (0 means Normal sample) */ uint8_t special_sample; int pitchbend; double pitchfactor; /* precomputed pitch bend factor to save some fdiv's */ /* For portamento */ uint8_t portamento_time_msb, portamento_time_lsb; int porta_control_ratio, porta_dpb; int32_t last_note_fine; /* For Drum part */ struct DrumParts *drums[128]; /* For NRPN Vibrato */ int32_t vibrato_depth, vibrato_delay; float vibrato_ratio; /* For RPN */ uint8_t rpnmap[RPN_MAX_DATA_ADDR]; /* pseudo RPN address map */ uint8_t rpnmap_lsb[RPN_MAX_DATA_ADDR]; uint8_t lastlrpn, lastmrpn; int8_t nrpn; /* 0:RPN, 1:NRPN, -1:Undefined */ int rpn_7f7f_flag; /* Boolean flag used for RPN 7F/7F */ /* For channel envelope */ int32_t envelope_rate[6]; /* for Envelope Generator in mix.c * 0: value for attack rate * 2: value for decay rate * 3: value for release rate */ int mapID; /* Program map ID */ AlternateAssign *altassign; /* Alternate assign patch table */ int32_t lasttime; /* Last sample time of computed voice on this channel */ /* flag for random pan */ int pan_random; /* for Voice LPF / Resonance */ int8_t param_resonance, param_cutoff_freq; /* -64 ~ 63 */ float cutoff_freq_coef, resonance_dB; int8_t velocity_sense_depth, velocity_sense_offset; int8_t scale_tuning[12], prev_scale_tuning; int8_t temper_type; int8_t soft_pedal; int8_t sostenuto; int8_t damper_mode; int8_t tone_map0_number; double pitch_offset_fine; /* in Hz */ int8_t assign_mode; int8_t legato; /* legato footswitch */ int8_t legato_flag; /* note-on flag for legato */ midi_controller mod, bend, caf, paf, cc1, cc2; ChannelBitMask channel_layer; int port_select; struct part_eq_xg eq_xg; int8_t dry_level; int8_t note_limit_high, note_limit_low; /* Note Limit (Keyboard Range) */ int8_t vel_limit_high, vel_limit_low; /* Velocity Limit */ int32_t rx; /* Rx. ~ (Rcv ~) */ int drum_effect_num; int8_t drum_effect_flag; struct DrumPartEffect *drum_effect; int8_t sysex_gs_msb_addr, sysex_gs_msb_val, sysex_xg_msb_addr, sysex_xg_msb_val, sysex_msb_addr, sysex_msb_val; }; /* Causes the instrument's default panning to be used. */ #define NO_PANNING -1 typedef struct { int16_t freq, last_freq, orig_freq; double reso_dB, last_reso_dB, orig_reso_dB, reso_lin; int8_t type; /* filter type. 0: Off, 1: 12dB/oct, 2: 24dB/oct */ int32_t f, q, p; /* coefficients in fixed-point */ int32_t b0, b1, b2, b3, b4; float gain; int8_t start_flag; } FilterCoefficients; #define ENABLE_PAN_DELAY #define PAN_DELAY_BUF_MAX 48 /* 0.5ms in 96kHz */ typedef struct { uint8_t status, channel, note, velocity; int vid, temper_instant; Sample *sample; int64_t sample_offset; /* sample_offset must be signed */ int32_t orig_frequency, frequency, sample_increment, envelope_volume, envelope_target, envelope_increment, tremolo_sweep, tremolo_sweep_position, tremolo_phase, tremolo_phase_increment, vibrato_sweep, vibrato_sweep_position; final_volume_t left_mix, right_mix; int32_t old_left_mix, old_right_mix, left_mix_offset, right_mix_offset, left_mix_inc, right_mix_inc; double left_amp, right_amp, tremolo_volume; int32_t vibrato_sample_increment[VIBRATO_SAMPLE_INCREMENTS], vibrato_delay; int vibrato_phase, orig_vibrato_control_ratio, vibrato_control_ratio, vibrato_depth, vibrato_control_counter, envelope_stage, control_counter, panning, panned; int16_t tremolo_depth; /* for portamento */ int porta_control_ratio, porta_control_counter, porta_dpb; int32_t porta_pb; int delay; /* Note ON delay samples */ int32_t timeout; struct cache_hash *cache; uint8_t chorus_link; /* Chorus link */ int8_t proximate_flag; FilterCoefficients fc; double envelope_scale, last_envelope_volume; int32_t inv_envelope_scale; int modenv_stage; int32_t modenv_volume, modenv_target, modenv_increment; double last_modenv_volume; int32_t tremolo_delay, modenv_delay; int32_t delay_counter; #ifdef ENABLE_PAN_DELAY int32_t *pan_delay_buf, pan_delay_rpt, pan_delay_wpt, pan_delay_spt; #endif /* ENABLE_PAN_DELAY */ } Voice; /* Voice status options: */ #define VOICE_FREE (1<<0) #define VOICE_ON (1<<1) #define VOICE_SUSTAINED (1<<2) #define VOICE_OFF (1<<3) #define VOICE_DIE (1<<4) /* Voice panned options: */ #define PANNED_MYSTERY 0 #define PANNED_LEFT 1 #define PANNED_RIGHT 2 #define PANNED_CENTER 3 /* Anything but PANNED_MYSTERY only uses the left volume */ enum { MODULE_TIMIDITY_DEFAULT = 0x0, /* GS modules */ MODULE_SC55 = 0x1, MODULE_SC88 = 0x2, MODULE_SC88PRO = 0x3, MODULE_SC8850 = 0x4, /* XG modules */ MODULE_MU50 = 0x10, MODULE_MU80 = 0x11, MODULE_MU90 = 0x12, MODULE_MU100 = 0x13, /* GM modules */ MODULE_SBLIVE = 0x20, MODULE_SBAUDIGY = 0x21, /* Special modules */ MODULE_TIMIDITY_SPECIAL1 = 0x70, MODULE_TIMIDITY_DEBUG = 0x7f, }; struct midi_file_info { int readflag; int16_t hdrsiz; int16_t format; int16_t tracks; int32_t divisions; int time_sig_n, time_sig_d, time_sig_c, time_sig_b; /* Time signature */ int drumchannels_isset; ChannelBitMask drumchannels; ChannelBitMask drumchannel_mask; int32_t samples; int max_channel; int compressed; /* True if midi_data is compressed */ }; class Recache; class Mixer; class Reverb; class Effect; class Player { public: Channel channel[MAX_CHANNELS]; Voice voice[max_voices]; ChannelBitMask default_drumchannel_mask; ChannelBitMask default_drumchannels; ChannelBitMask drumchannel_mask; ChannelBitMask drumchannels; double *vol_table; // make this private later Instruments *instruments; private: int last_reverb_setting; Recache *recache; Mixer *mixer; Reverb *reverb; Effect *effect; MidiEvent *current_event; int32_t sample_count; /* Length of event_list */ int32_t current_sample; /* Number of calclated samples */ double midi_time_ratio; /* For speed up/down */ int computed_samples; int note_key_offset = 0; /* For key up/down */ ChannelBitMask channel_mute; /* For channel mute */ double master_volume; int32_t master_volume_ratio; int play_system_mode; int midi_streaming; int volatile stream_max_compute; /* compute time limit (in msec) when streaming */ int8_t current_keysig; int8_t current_temper_keysig; int temper_adj; int32_t current_play_tempo; int opt_realtime_playing; int check_eot_flag; int playmidi_seek_flag; int opt_pure_intonation; int current_freq_table; int current_temper_freq_table; int master_tuning; int make_rvid_flag; /* For reverb optimization */ int32_t amplification; int voices, upper_voices; struct midi_file_info midifileinfo, *current_file_info; MBlockList playmidi_pool; int32_t freq_table_user[4][48][128]; char *reverb_buffer; /* MAX_CHANNELS*AUDIO_BUFFER_SIZE*8 */ int32_t lost_notes, cut_notes; int32_t common_buffer[AUDIO_BUFFER_SIZE * 2], *buffer_pointer; /* stereo samples */ int16_t wav_buffer[AUDIO_BUFFER_SIZE * 2]; int32_t insertion_effect_buffer[AUDIO_BUFFER_SIZE * 2]; /* Ring voice id for each notes. This ID enables duplicated note. */ uint8_t vidq_head[128 * MAX_CHANNELS], vidq_tail[128 * MAX_CHANNELS]; int MIDI_EVENT_NOTE(MidiEvent *ep) { return (ISDRUMCHANNEL((ep)->channel) ? (ep)->a : (((int)(ep)->a + note_key_offset + channel[ep->channel].key_shift) & 0x7f)); } int16_t conv_lfo_pitch_depth(float val) { return (int16_t)(0.0318f * val * val + 0.6858f * val + 0.5f); } int16_t conv_lfo_filter_depth(float val) { return (int16_t)((0.0318f * val * val + 0.6858f * val) * 4.0f + 0.5f); } bool IS_SYSEX_EVENT_TYPE(MidiEvent *event); double cnv_Hz_to_vib_ratio(double freq); int new_vidq(int ch, int note); int last_vidq(int ch, int note); void reset_voices(void); void kill_note(int i); void kill_all_voices(void); void reset_drum_controllers(struct DrumParts *d[], int note); void reset_nrpn_controllers(int c); void reset_controllers(int c); int32_t calc_velocity(int32_t ch, int32_t vel); void recompute_voice_tremolo(int v); void recompute_amp(int v); void reset_midi(int playing); void recompute_channel_filter(int ch, int note); void init_voice_filter(int i); int reduce_voice(void); int find_free_voice(void); int get_panning(int ch, int note, int v); void init_voice_vibrato(int v); void init_voice_pan_delay(int v); void init_voice_portamento(int v); void init_voice_tremolo(int v); void start_note(MidiEvent *e, int i, int vid, int cnt); void set_envelope_time(int ch, int val, int stage); void new_chorus_voice_alternate(int v1, int level); void note_on(MidiEvent *e); void update_sostenuto_controls(int ch); void update_redamper_controls(int ch); void note_off(MidiEvent *e); void all_notes_off(int c); void all_sounds_off(int c); void adjust_pressure(MidiEvent *e); void adjust_channel_pressure(MidiEvent *e); void adjust_panning(int c); void adjust_drum_panning(int ch, int note); void drop_sustain(int c); void adjust_all_pitch(void); void adjust_pitch(int c); void adjust_volume(int c); void set_reverb_level(int ch, int level); void make_drum_effect(int ch); void adjust_master_volume(void); void add_channel_layer(int to_ch, int from_ch); void remove_channel_layer(int ch); void process_sysex_event(int ev, int ch, int val, int b); double gs_cnv_vib_rate(int rate); int32_t gs_cnv_vib_depth(int depth); int32_t gs_cnv_vib_delay(int delay); int last_rpn_addr(int ch); void voice_increment(int n); void voice_decrement(int n); void voice_decrement_conservative(int n); void mix_signal(int32_t *dest, int32_t *src, int32_t count); int is_insertion_effect_xg(int ch); void do_compute_data(int32_t count); int check_midi_play_end(MidiEvent *e, int len); int midi_play_end(void); void update_modulation_wheel(int ch); void drop_portamento(int ch); void update_portamento_time(int ch); void update_legato_controls(int ch); void set_master_tuning(int tune); struct midi_file_info *new_midi_file_info(); void adjust_amplification(void); void init_freq_table_user(void); int find_samples(MidiEvent *, int *); int select_play_sample(Sample *, int, int *, int *, MidiEvent *); double get_play_note_ratio(int, int); int find_voice(MidiEvent *); void finish_note(int i); void update_portamento_controls(int ch); void update_rpn_map(int ch, int addr, int update_now); void set_single_note_tuning(int, int, int, int); void set_user_temper_entry(int, int, int); void recompute_bank_parameter(int, int); float calc_drum_tva_level(int ch, int note, int level); int32_t calc_random_delay(int ch, int note); /* XG Part EQ */ void init_part_eq_xg(struct part_eq_xg *); void recompute_part_eq_xg(struct part_eq_xg *); /* MIDI controllers (MW, Bend, CAf, PAf,...) */ void init_midi_controller(midi_controller *); float get_midi_controller_amp(midi_controller *); float get_midi_controller_filter_cutoff(midi_controller *); float get_midi_controller_filter_depth(midi_controller *); int32_t get_midi_controller_pitch(midi_controller *); int16_t get_midi_controller_pitch_depth(midi_controller *); int16_t get_midi_controller_amp_depth(midi_controller *); /* Rx. ~ (Rcv ~) */ void init_rx(int); void set_rx(int, int32_t, int); void init_rx_drum(struct DrumParts *); void set_rx_drum(struct DrumParts *, int32_t, int); int32_t get_rx_drum(struct DrumParts *, int32_t); int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret); public: Player(Instruments *); ~Player(); bool ISDRUMCHANNEL(int c) { return !!IS_SET_CHANNELMASK(drumchannels, c); } int midi_drumpart_change(int ch, int isdrum); int get_reverb_level(int ch); int get_chorus_level(int ch); Instrument *play_midi_load_instrument(int dr, int bk, int prog); void midi_program_change(int ch, int prog); void free_voice(int v); void play_midi_setup_drums(int ch, int note); /* For stream player */ void playmidi_stream_init(void); void playmidi_tmr_reset(void); int play_event(MidiEvent *ev); void recompute_voice_filter(int); void free_drum_effect(int); void change_system_mode(int mode); void recompute_freq(int v); int get_default_mapID(int ch); void init_channel_layer(int ch); int compute_data(float *buffer, int32_t count); int send_event(int status, int parm1, int parm2); void send_long_event(const uint8_t *sysexbuffer, int exlen); }; class SysexConvert { const int midi_port_number = 0; uint8_t rhythm_part[2] = { 0,0 }; /* for GS */ uint8_t drum_setup_xg[16] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; /* for XG */ public: int parse_sysex_event_multi(const uint8_t *val, int32_t len, MidiEvent *evm, Instruments *instruments); int parse_sysex_event(const uint8_t *val, int32_t len, MidiEvent *ev, Instruments *instruments); }; void free_gauss_table(void); void set_playback_rate(int freq); } #endif /* ___PLAYMIDI_H_ */