2018-02-19 21:14:22 +00:00
|
|
|
/*
|
|
|
|
TiMidity++ -- MIDI to WAVE converter and player
|
|
|
|
Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.co.jp>
|
|
|
|
Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
|
|
|
|
|
|
|
|
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 <stdint.h>
|
|
|
|
|
|
|
|
namespace TimidityPlus
|
|
|
|
{
|
|
|
|
|
|
|
|
struct AlternateAssign;
|
|
|
|
|
|
|
|
struct MidiEvent
|
|
|
|
{
|
|
|
|
int32_t time;
|
|
|
|
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;
|
|
|
|
char *seq_name;
|
|
|
|
char *karaoke_title;
|
|
|
|
char *first_text;
|
|
|
|
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 AudioQueue;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
private:
|
|
|
|
Recache *recache;
|
|
|
|
Mixer *mixer;
|
|
|
|
Reverb *reverb;
|
|
|
|
AudioQueue *aq;
|
|
|
|
|
|
|
|
|
|
|
|
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 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 buffered_count;
|
|
|
|
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t MIDI_EVENT_TIME(MidiEvent *ep)
|
|
|
|
{
|
|
|
|
return ((int32_t)((ep)->time * midi_time_ratio + 0.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
int compute_data(int32_t count);
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
Player();
|
|
|
|
~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);
|
|
|
|
struct midi_file_info *get_midi_file_info(const char *filename, int newp);
|
|
|
|
void recompute_freq(int v);
|
|
|
|
int get_default_mapID(int ch);
|
|
|
|
void init_channel_layer(int ch);
|
|
|
|
|
|
|
|
// Only until streaming works.
|
|
|
|
void skip_to(int32_t until_time, MidiEvent *evt_start);
|
2018-02-20 00:23:56 +00:00
|
|
|
int start_midi(MidiEvent *eventlist, int32_t samples);
|
|
|
|
void run_midi(int);
|
2018-02-19 21:14:22 +00:00
|
|
|
int play_midi(MidiEvent *eventlist, int32_t samples);
|
|
|
|
friend MidiEvent *groom_list(int32_t divisions, int32_t *eventsp, int32_t *samplesp);
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
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(uint8_t *val, int32_t len, MidiEvent *evm, Instruments *instruments);
|
|
|
|
int parse_sysex_event(uint8_t *val, int32_t len, MidiEvent *ev, Instruments *instruments);
|
|
|
|
};
|
|
|
|
|
|
|
|
// really extern!
|
|
|
|
int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ___PLAYMIDI_H_ */
|