mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- Added the long event handler for Timidity++.
This will be hard to test because there's basically no material out there using the features this implements.
This commit is contained in:
parent
4813eeeb85
commit
445e9451cb
4 changed files with 130 additions and 99 deletions
|
@ -112,6 +112,7 @@ TimidityPPMIDIDevice::TimidityPPMIDIDevice(const char *args)
|
|||
{
|
||||
if (args == NULL || *args == 0) args = timidity_config;
|
||||
|
||||
Renderer = nullptr;
|
||||
if (instruments != nullptr && !instruments->checkConfig(args))
|
||||
{
|
||||
delete instruments;
|
||||
|
@ -152,14 +153,14 @@ TimidityPPMIDIDevice::~TimidityPPMIDIDevice ()
|
|||
|
||||
int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
|
||||
{
|
||||
// No instruments loaded means we cannot play...
|
||||
if (instruments == nullptr) return 0;
|
||||
|
||||
int ret = OpenStream(2, 0, callback, userdata);
|
||||
if (ret == 0)
|
||||
if (ret == 0 && Renderer != nullptr)
|
||||
{
|
||||
Renderer->playmidi_stream_init();
|
||||
}
|
||||
// No instruments loaded means we cannot play...
|
||||
if (instruments == nullptr) return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -176,7 +177,8 @@ int TimidityPPMIDIDevice::Open(MidiCallback callback, void *userdata)
|
|||
|
||||
void TimidityPPMIDIDevice::PrecacheInstruments(const uint16_t *instrumentlist, int count)
|
||||
{
|
||||
instruments->PrecacheInstruments(instrumentlist, count);
|
||||
if (instruments != nullptr)
|
||||
instruments->PrecacheInstruments(instrumentlist, count);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -187,7 +189,8 @@ void TimidityPPMIDIDevice::PrecacheInstruments(const uint16_t *instrumentlist, i
|
|||
|
||||
void TimidityPPMIDIDevice::HandleEvent(int status, int parm1, int parm2)
|
||||
{
|
||||
Renderer->send_event(sampletime, status, parm1, parm2);
|
||||
if (Renderer != nullptr)
|
||||
Renderer->send_event(sampletime, status, parm1, parm2);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -198,7 +201,8 @@ void TimidityPPMIDIDevice::HandleEvent(int status, int parm1, int parm2)
|
|||
|
||||
void TimidityPPMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
|
||||
{
|
||||
//Renderer->HandleLongMessage(data, len);
|
||||
if (Renderer != nullptr)
|
||||
Renderer->send_long_event(sampletime, data, len);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -209,7 +213,8 @@ void TimidityPPMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
|
|||
|
||||
void TimidityPPMIDIDevice::ComputeOutput(float *buffer, int len)
|
||||
{
|
||||
Renderer->get_output(buffer, len);
|
||||
if (Renderer != nullptr)
|
||||
Renderer->get_output(buffer, len);
|
||||
sampletime += len;
|
||||
}
|
||||
|
||||
|
|
|
@ -5046,8 +5046,6 @@ int Player::compute_data(int32_t count)
|
|||
|
||||
while ((count + buffered_count) >= AUDIO_BUFFER_SIZE)
|
||||
{
|
||||
int i;
|
||||
|
||||
do_compute_data(AUDIO_BUFFER_SIZE - buffered_count);
|
||||
count -= AUDIO_BUFFER_SIZE - buffered_count;
|
||||
|
||||
|
@ -5864,6 +5862,7 @@ void Player::playmidi_stream_init(void)
|
|||
reuse_mblock(&playmidi_pool);
|
||||
|
||||
/* Fill in current_file_info */
|
||||
current_file_info = get_midi_file_info("", 0);
|
||||
current_file_info->readflag = 1;
|
||||
current_file_info->seq_name = safe_strdup("TiMidity server");
|
||||
current_file_info->karaoke_title = current_file_info->first_text = NULL;
|
||||
|
@ -6070,6 +6069,72 @@ void Player::get_output(float *buffer, int len)
|
|||
//compute_data(len);
|
||||
}
|
||||
|
||||
|
||||
static const struct ctl_chg_types {
|
||||
unsigned char mtype;
|
||||
int ttype;
|
||||
} ctl_chg_list[] = {
|
||||
{ 0, ME_TONE_BANK_MSB },
|
||||
{ 1, ME_MODULATION_WHEEL },
|
||||
{ 2, ME_BREATH },
|
||||
{ 4, ME_FOOT },
|
||||
{ 5, ME_PORTAMENTO_TIME_MSB },
|
||||
{ 6, ME_DATA_ENTRY_MSB },
|
||||
{ 7, ME_MAINVOLUME },
|
||||
{ 8, ME_BALANCE },
|
||||
{ 10, ME_PAN },
|
||||
{ 11, ME_EXPRESSION },
|
||||
{ 32, ME_TONE_BANK_LSB },
|
||||
{ 37, ME_PORTAMENTO_TIME_LSB },
|
||||
{ 38, ME_DATA_ENTRY_LSB },
|
||||
{ 64, ME_SUSTAIN },
|
||||
{ 65, ME_PORTAMENTO },
|
||||
{ 66, ME_SOSTENUTO },
|
||||
{ 67, ME_SOFT_PEDAL },
|
||||
{ 68, ME_LEGATO_FOOTSWITCH },
|
||||
{ 69, ME_HOLD2 },
|
||||
{ 71, ME_HARMONIC_CONTENT },
|
||||
{ 72, ME_RELEASE_TIME },
|
||||
{ 73, ME_ATTACK_TIME },
|
||||
{ 74, ME_BRIGHTNESS },
|
||||
{ 84, ME_PORTAMENTO_CONTROL },
|
||||
{ 91, ME_REVERB_EFFECT },
|
||||
{ 92, ME_TREMOLO_EFFECT },
|
||||
{ 93, ME_CHORUS_EFFECT },
|
||||
{ 94, ME_CELESTE_EFFECT },
|
||||
{ 95, ME_PHASER_EFFECT },
|
||||
{ 96, ME_RPN_INC },
|
||||
{ 97, ME_RPN_DEC },
|
||||
{ 98, ME_NRPN_LSB },
|
||||
{ 99, ME_NRPN_MSB },
|
||||
{ 100, ME_RPN_LSB },
|
||||
{ 101, ME_RPN_MSB },
|
||||
{ 120, ME_ALL_SOUNDS_OFF },
|
||||
{ 121, ME_RESET_CONTROLLERS },
|
||||
{ 123, ME_ALL_NOTES_OFF },
|
||||
{ 126, ME_MONO },
|
||||
{ 127, ME_POLY },
|
||||
};
|
||||
|
||||
int Player::convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret)
|
||||
{
|
||||
int etype = -1;
|
||||
for (auto &t : ctl_chg_list)
|
||||
{
|
||||
if (t.mtype == type)
|
||||
{
|
||||
if (val > 127) val = 127;
|
||||
ev_ret->type = t.ttype;
|
||||
ev_ret->channel = chn;
|
||||
ev_ret->a = val;
|
||||
ev_ret->b = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Player::send_event(int sampletime, int status, int parm1, int parm2)
|
||||
{
|
||||
MidiEvent ev;
|
||||
|
@ -6122,4 +6187,40 @@ int Player::send_event(int sampletime, int status, int parm1, int parm2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Player::send_long_event(int sampletime, const uint8_t *sysexbuffer, int exlen)
|
||||
{
|
||||
int i, ne;
|
||||
MidiEvent ev;
|
||||
MidiEvent evm[260];
|
||||
SysexConvert sc;
|
||||
|
||||
if ((sysexbuffer[0] != '\xf0') && (sysexbuffer[0] != '\xf7')) return;
|
||||
|
||||
if (sc.parse_sysex_event(sysexbuffer + 1, exlen - 1, &ev, instruments))
|
||||
{
|
||||
if (ev.type == ME_RESET)
|
||||
{
|
||||
kill_all_voices();
|
||||
for (int i = 0; i < MAX_CHANNELS; i++)
|
||||
init_channel_layer(i);
|
||||
|
||||
/* initialize effect status */
|
||||
reverb->init_effect_status(play_system_mode);
|
||||
instruments->init_userdrum();
|
||||
instruments->init_userinst();
|
||||
playmidi_stream_init();
|
||||
}
|
||||
play_event(&ev);
|
||||
}
|
||||
if (ne = sc.parse_sysex_event_multi(sysexbuffer + 1, exlen - 1, evm, instruments))
|
||||
{
|
||||
for (i = 0; i < ne; i++)
|
||||
{
|
||||
play_event(&evm[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -707,6 +707,7 @@ private:
|
|||
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:
|
||||
|
@ -741,15 +742,7 @@ public:
|
|||
void init_channel_layer(int ch);
|
||||
void get_output(float *buffer, int len);
|
||||
int send_event(int time, int status, int parm1, int parm2);
|
||||
|
||||
// Only until streaming works.
|
||||
void skip_to(int32_t until_time, MidiEvent *evt_start);
|
||||
int start_midi(MidiEvent *eventlist, int32_t samples);
|
||||
void run_midi(int);
|
||||
int play_midi(MidiEvent *eventlist, int32_t samples);
|
||||
friend MidiEvent *groom_list(int32_t divisions, int32_t *eventsp, int32_t *samplesp);
|
||||
|
||||
|
||||
void send_long_event(int sampletime, const uint8_t *sysexbuffer, int exlen);
|
||||
};
|
||||
|
||||
class SysexConvert
|
||||
|
@ -759,13 +752,10 @@ class SysexConvert
|
|||
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);
|
||||
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);
|
||||
};
|
||||
|
||||
// really extern!
|
||||
int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -43,71 +43,6 @@ inline void SETMIDIEVENT(MidiEvent &e, int32_t at, uint32_t t, uint32_t ch, uint
|
|||
#define MERGE_CHANNEL_PORT(ch) ((int)(ch) | (midi_port_number << 4))
|
||||
#define MERGE_CHANNEL_PORT2(ch, port) ((int)(ch) | ((int)port << 4))
|
||||
|
||||
|
||||
static const struct ctl_chg_types {
|
||||
unsigned char mtype;
|
||||
int ttype;
|
||||
} ctl_chg_list[] = {
|
||||
{ 0, ME_TONE_BANK_MSB },
|
||||
{ 1, ME_MODULATION_WHEEL },
|
||||
{ 2, ME_BREATH },
|
||||
{ 4, ME_FOOT },
|
||||
{ 5, ME_PORTAMENTO_TIME_MSB },
|
||||
{ 6, ME_DATA_ENTRY_MSB },
|
||||
{ 7, ME_MAINVOLUME },
|
||||
{ 8, ME_BALANCE },
|
||||
{ 10, ME_PAN },
|
||||
{ 11, ME_EXPRESSION },
|
||||
{ 32, ME_TONE_BANK_LSB },
|
||||
{ 37, ME_PORTAMENTO_TIME_LSB },
|
||||
{ 38, ME_DATA_ENTRY_LSB },
|
||||
{ 64, ME_SUSTAIN },
|
||||
{ 65, ME_PORTAMENTO },
|
||||
{ 66, ME_SOSTENUTO },
|
||||
{ 67, ME_SOFT_PEDAL },
|
||||
{ 68, ME_LEGATO_FOOTSWITCH },
|
||||
{ 69, ME_HOLD2 },
|
||||
{ 71, ME_HARMONIC_CONTENT },
|
||||
{ 72, ME_RELEASE_TIME },
|
||||
{ 73, ME_ATTACK_TIME },
|
||||
{ 74, ME_BRIGHTNESS },
|
||||
{ 84, ME_PORTAMENTO_CONTROL },
|
||||
{ 91, ME_REVERB_EFFECT },
|
||||
{ 92, ME_TREMOLO_EFFECT },
|
||||
{ 93, ME_CHORUS_EFFECT },
|
||||
{ 94, ME_CELESTE_EFFECT },
|
||||
{ 95, ME_PHASER_EFFECT },
|
||||
{ 96, ME_RPN_INC },
|
||||
{ 97, ME_RPN_DEC },
|
||||
{ 98, ME_NRPN_LSB },
|
||||
{ 99, ME_NRPN_MSB },
|
||||
{ 100, ME_RPN_LSB },
|
||||
{ 101, ME_RPN_MSB },
|
||||
{ 120, ME_ALL_SOUNDS_OFF },
|
||||
{ 121, ME_RESET_CONTROLLERS },
|
||||
{ 123, ME_ALL_NOTES_OFF },
|
||||
{ 126, ME_MONO },
|
||||
{ 127, ME_POLY },
|
||||
};
|
||||
|
||||
int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret)
|
||||
{
|
||||
int etype = -1;
|
||||
for (auto &t : ctl_chg_list)
|
||||
{
|
||||
if (t.mtype == type)
|
||||
{
|
||||
if (val > 127) val = 127;
|
||||
ev_ret->type = t.ttype;
|
||||
ev_ret->channel = chn;
|
||||
ev_ret->a = val;
|
||||
ev_ret->b = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Map XG types onto GS types. XG should eventually have its own tables */
|
||||
static int set_xg_reverb_type(int msb, int lsb)
|
||||
{
|
||||
|
@ -272,7 +207,7 @@ static uint16_t gm_convert_master_vol(uint16_t v1, uint16_t v2)
|
|||
* This function provides basic support for XG Bulk Dump and Parameter
|
||||
* Change SysEx events
|
||||
*/
|
||||
int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *evm, Instruments *instruments)
|
||||
int SysexConvert::parse_sysex_event_multi(const uint8_t *val, int32_t len, MidiEvent *evm, Instruments *instruments)
|
||||
{
|
||||
int num_events = 0; /* Number of events added */
|
||||
|
||||
|
@ -289,9 +224,9 @@ int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *
|
|||
(val[1] >= 0x10 && val[3] == 0x02))) /* Parameter Change */
|
||||
{
|
||||
uint8_t addhigh, addmid, addlow; /* Addresses */
|
||||
uint8_t *body; /* SysEx body */
|
||||
const uint8_t *body; /* SysEx body */
|
||||
int ent, v; /* Entry # of sub-event */
|
||||
uint8_t *body_end; /* End of SysEx body */
|
||||
const uint8_t *body_end; /* End of SysEx body */
|
||||
|
||||
if (val[1] < 0x10) /* Bulk Dump */
|
||||
{
|
||||
|
@ -484,9 +419,9 @@ int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *
|
|||
(val[1] >= 0x10 && val[3] == 0x03))) /* Parameter Change */
|
||||
{
|
||||
uint8_t addhigh, addmid, addlow; /* Addresses */
|
||||
uint8_t *body; /* SysEx body */
|
||||
const uint8_t *body; /* SysEx body */
|
||||
int ent; /* Entry # of sub-event */
|
||||
uint8_t *body_end; /* End of SysEx body */
|
||||
const uint8_t *body_end; /* End of SysEx body */
|
||||
|
||||
if (val[1] < 0x10) /* Bulk Dump */
|
||||
{
|
||||
|
@ -524,10 +459,10 @@ int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *
|
|||
(val[1] >= 0x10 && val[3] == 0x08))) /* Parameter Change */
|
||||
{
|
||||
uint8_t addhigh, addmid, addlow; /* Addresses */
|
||||
uint8_t *body; /* SysEx body */
|
||||
const uint8_t *body; /* SysEx body */
|
||||
uint8_t p; /* Channel part number [0..15] */
|
||||
int ent; /* Entry # of sub-event */
|
||||
uint8_t *body_end; /* End of SysEx body */
|
||||
const uint8_t *body_end; /* End of SysEx body */
|
||||
|
||||
if (val[1] < 0x10) /* Bulk Dump */
|
||||
{
|
||||
|
@ -1094,10 +1029,10 @@ int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *
|
|||
(val[1] >= 0x10 && (val[3] & 0xF0) == 0x30))) /* Parameter Change */
|
||||
{
|
||||
uint8_t addhigh, addmid, addlow; /* Addresses */
|
||||
uint8_t *body; /* SysEx body */
|
||||
const uint8_t *body; /* SysEx body */
|
||||
uint8_t dp, note; /* Channel part number [0..15] */
|
||||
int ent; /* Entry # of sub-event */
|
||||
uint8_t *body_end; /* End of SysEx body */
|
||||
const uint8_t *body_end; /* End of SysEx body */
|
||||
|
||||
if (val[1] < 0x10) /* Bulk Dump */
|
||||
{
|
||||
|
@ -2410,7 +2345,7 @@ int SysexConvert::parse_sysex_event_multi(uint8_t *val, int32_t len, MidiEvent *
|
|||
}
|
||||
|
||||
|
||||
int SysexConvert::parse_sysex_event(uint8_t *val, int32_t len, MidiEvent *ev, Instruments *instruments)
|
||||
int SysexConvert::parse_sysex_event(const uint8_t *val, int32_t len, MidiEvent *ev, Instruments *instruments)
|
||||
{
|
||||
uint16_t vol;
|
||||
|
||||
|
@ -2430,7 +2365,7 @@ int SysexConvert::parse_sysex_event(uint8_t *val, int32_t len, MidiEvent *ev, In
|
|||
*/
|
||||
|
||||
int32_t addr, checksum, i; /* SysEx address */
|
||||
uint8_t *body; /* SysEx body */
|
||||
const uint8_t *body; /* SysEx body */
|
||||
uint8_t p, gslen; /* Channel part number [0..15] */
|
||||
|
||||
/* check Checksum */
|
||||
|
|
Loading…
Reference in a new issue