mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 05:31:00 +00:00
2664 lines
No EOL
81 KiB
C++
2664 lines
No EOL
81 KiB
C++
/*
|
|
TiMidity++ -- MIDI to WAVE converter and player
|
|
Copyright (C) 1999-2009 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
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "timidity.h"
|
|
#include "instrum.h"
|
|
#include "playmidi.h"
|
|
|
|
namespace TimidityPlus
|
|
{
|
|
|
|
|
|
inline void SETMIDIEVENT(MidiEvent &e, int32_t /*time, not needed anymore*/, uint32_t t, uint32_t ch, uint32_t pa, uint32_t pb)
|
|
{
|
|
(e).type = (t);
|
|
(e).channel = (uint8_t)(ch);
|
|
(e).a = (uint8_t)(pa);
|
|
(e).b = (uint8_t)(pb);
|
|
}
|
|
|
|
#define MERGE_CHANNEL_PORT(ch) ((int)(ch) | (midi_port_number << 4))
|
|
#define MERGE_CHANNEL_PORT2(ch, port) ((int)(ch) | ((int)port << 4))
|
|
|
|
/* Map XG types onto GS types. XG should eventually have its own tables */
|
|
static int set_xg_reverb_type(int msb, int lsb)
|
|
{
|
|
int type = 4;
|
|
|
|
if ((msb == 0x00) ||
|
|
(msb >= 0x05 && msb <= 0x0F) ||
|
|
(msb >= 0x14)) /* NO EFFECT */
|
|
{
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"XG Set Reverb Type (NO EFFECT %d %d)", msb, lsb);
|
|
return -1;
|
|
}
|
|
|
|
switch (msb)
|
|
{
|
|
case 0x01:
|
|
type = 3; /* Hall 1 */
|
|
break;
|
|
case 0x02:
|
|
type = 0; /* Room 1 */
|
|
break;
|
|
case 0x03:
|
|
type = 3; /* Stage 1 -> Hall 1 */
|
|
break;
|
|
case 0x04:
|
|
type = 5; /* Plate */
|
|
break;
|
|
default:
|
|
type = 4; /* unsupported -> Hall 2 */
|
|
break;
|
|
}
|
|
if (lsb == 0x01)
|
|
{
|
|
switch (msb)
|
|
{
|
|
case 0x01:
|
|
type = 4; /* Hall 2 */
|
|
break;
|
|
case 0x02:
|
|
type = 1; /* Room 2 */
|
|
break;
|
|
case 0x03:
|
|
type = 4; /* Stage 2 -> Hall 2 */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (lsb == 0x02 && msb == 0x02)
|
|
type = 2; /* Room 3 */
|
|
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"XG Set Reverb Type (%d)", type);
|
|
return type;
|
|
}
|
|
|
|
|
|
/* Map XG types onto GS types. XG should eventually have its own tables */
|
|
static int set_xg_chorus_type(int msb, int lsb)
|
|
{
|
|
int type = 2;
|
|
|
|
if ((msb >= 0x00 && msb <= 0x40) ||
|
|
(msb >= 0x45 && msb <= 0x47) ||
|
|
(msb >= 0x49)) /* NO EFFECT */
|
|
{
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"XG Set Chorus Type (NO EFFECT %d %d)", msb, lsb);
|
|
return -1;
|
|
}
|
|
|
|
switch (msb)
|
|
{
|
|
case 0x41:
|
|
type = 0; /* Chorus 1 */
|
|
break;
|
|
case 0x42:
|
|
type = 0; /* Celeste 1 -> Chorus 1 */
|
|
break;
|
|
case 0x43:
|
|
type = 5;
|
|
break;
|
|
default:
|
|
type = 2; /* unsupported -> Chorus 3 */
|
|
break;
|
|
}
|
|
if (lsb == 0x01)
|
|
{
|
|
switch (msb)
|
|
{
|
|
case 0x41:
|
|
type = 1; /* Chorus 2 */
|
|
break;
|
|
case 0x42:
|
|
type = 1; /* Celeste 2 -> Chorus 2 */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (lsb == 0x02)
|
|
{
|
|
switch (msb)
|
|
{
|
|
case 0x41:
|
|
type = 2; /* Chorus 3 */
|
|
break;
|
|
case 0x42:
|
|
type = 2; /* Celeste 3 -> Chorus 3 */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (lsb == 0x08)
|
|
{
|
|
switch (msb)
|
|
{
|
|
case 0x41:
|
|
type = 3; /* Chorus 4 */
|
|
break;
|
|
case 0x42:
|
|
type = 3; /* Celeste 4 -> Chorus 4 */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"XG Set Chorus Type (%d)", type);
|
|
return type;
|
|
}
|
|
|
|
static int block_to_part(int block, int port)
|
|
{
|
|
int p;
|
|
p = block & 0x0F;
|
|
if (p == 0) { p = 9; }
|
|
else if (p <= 9) { p--; }
|
|
return MERGE_CHANNEL_PORT2(p, port);
|
|
}
|
|
|
|
static uint16_t gs_convert_master_vol(int vol)
|
|
{
|
|
double v;
|
|
|
|
if (vol >= 0x7f)
|
|
return 0xffff;
|
|
v = (double)vol * (0xffff / 127.0);
|
|
if (v >= 0xffff)
|
|
return 0xffff;
|
|
return (uint16_t)v;
|
|
}
|
|
|
|
static uint16_t gm_convert_master_vol(uint16_t v1, uint16_t v2)
|
|
{
|
|
return (((v1 & 0x7f) | ((v2 & 0x7f) << 7)) << 2) | 3;
|
|
}
|
|
|
|
|
|
/* XG SysEx parsing function by Eric A. Welsh
|
|
* Also handles GS patch+bank changes
|
|
*
|
|
* This function provides basic support for XG Bulk Dump and Parameter
|
|
* Change SysEx events
|
|
*/
|
|
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 */
|
|
|
|
uint32_t channel_tt;
|
|
int i, j;
|
|
static uint8_t xg_reverb_type_msb = 0x01, xg_reverb_type_lsb = 0x00;
|
|
static uint8_t xg_chorus_type_msb = 0x41, xg_chorus_type_lsb = 0x00;
|
|
|
|
/* Effect 1 or Multi EQ */
|
|
if (len >= 8 &&
|
|
val[0] == 0x43 && /* Yamaha ID */
|
|
val[2] == 0x4C && /* XG Model ID */
|
|
((val[1] < 0x10 && val[5] == 0x02) || /* Bulk Dump*/
|
|
(val[1] >= 0x10 && val[3] == 0x02))) /* Parameter Change */
|
|
{
|
|
uint8_t addhigh, addmid, addlow; /* Addresses */
|
|
const uint8_t *body; /* SysEx body */
|
|
int ent, v; /* Entry # of sub-event */
|
|
const uint8_t *body_end; /* End of SysEx body */
|
|
|
|
if (val[1] < 0x10) /* Bulk Dump */
|
|
{
|
|
addhigh = val[5];
|
|
addmid = val[6];
|
|
addlow = val[7];
|
|
body = val + 8;
|
|
body_end = val + len - 3;
|
|
}
|
|
else /* Parameter Change */
|
|
{
|
|
addhigh = val[3];
|
|
addmid = val[4];
|
|
addlow = val[5];
|
|
body = val + 6;
|
|
body_end = val + len - 2;
|
|
}
|
|
|
|
/* set the SYSEX_XG_MSB info */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_MSB, 0, addhigh, addmid);
|
|
num_events++;
|
|
|
|
for (ent = addlow; body <= body_end; body++, ent++) {
|
|
if (addmid == 0x01) { /* Effect 1 */
|
|
switch (ent) {
|
|
case 0x00: /* Reverb Type MSB */
|
|
xg_reverb_type_msb = *body;
|
|
#if 0 /* XG specific reverb is not supported yet, use GS instead */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
#endif
|
|
break;
|
|
|
|
case 0x01: /* Reverb Type LSB */
|
|
xg_reverb_type_lsb = *body;
|
|
#if 0 /* XG specific reverb is not supported yet, use GS instead */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
#else
|
|
v = set_xg_reverb_type(xg_reverb_type_msb, xg_reverb_type_lsb);
|
|
if (v >= 0) {
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, v, 0x05);
|
|
num_events++;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case 0x0C: /* Reverb Return */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x20: /* Chorus Type MSB */
|
|
xg_chorus_type_msb = *body;
|
|
#if 0 /* XG specific chorus is not supported yet, use GS instead */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
#endif
|
|
break;
|
|
|
|
case 0x21: /* Chorus Type LSB */
|
|
xg_chorus_type_lsb = *body;
|
|
#if 0 /* XG specific chorus is not supported yet, use GS instead */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
#else
|
|
v = set_xg_chorus_type(xg_chorus_type_msb, xg_chorus_type_lsb);
|
|
if (v >= 0) {
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, v, 0x0D);
|
|
num_events++;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case 0x2C: /* Chorus Return */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
default:
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
}
|
|
}
|
|
else if (addmid == 0x40) { /* Multi EQ */
|
|
switch (ent) {
|
|
case 0x00: /* EQ type */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x01: /* EQ gain1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x02: /* EQ frequency1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x03: /* EQ Q1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x04: /* EQ shape1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x05: /* EQ gain2 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x06: /* EQ frequency2 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x07: /* EQ Q2 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x09: /* EQ gain3 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0A: /* EQ frequency3 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0B: /* EQ Q3 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0D: /* EQ gain4 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0E: /* EQ frequency4 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0F: /* EQ Q4 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x11: /* EQ gain5 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x12: /* EQ frequency5 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x13: /* EQ Q5 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x14: /* EQ shape5 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Effect 2 (Insertion Effects) */
|
|
else if (len >= 8 &&
|
|
val[0] == 0x43 && /* Yamaha ID */
|
|
val[2] == 0x4C && /* XG Model ID */
|
|
((val[1] < 0x10 && val[5] == 0x03) || /* Bulk Dump*/
|
|
(val[1] >= 0x10 && val[3] == 0x03))) /* Parameter Change */
|
|
{
|
|
uint8_t addhigh, addmid, addlow; /* Addresses */
|
|
const uint8_t *body; /* SysEx body */
|
|
int ent; /* Entry # of sub-event */
|
|
const uint8_t *body_end; /* End of SysEx body */
|
|
|
|
if (val[1] < 0x10) /* Bulk Dump */
|
|
{
|
|
addhigh = val[5];
|
|
addmid = val[6];
|
|
addlow = val[7];
|
|
body = val + 8;
|
|
body_end = val + len - 3;
|
|
}
|
|
else /* Parameter Change */
|
|
{
|
|
addhigh = val[3];
|
|
addmid = val[4];
|
|
addlow = val[5];
|
|
body = val + 6;
|
|
body_end = val + len - 2;
|
|
}
|
|
|
|
/* set the SYSEX_XG_MSB info */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_MSB, 0, addhigh, addmid);
|
|
num_events++;
|
|
|
|
for (ent = addlow; body <= body_end; body++, ent++) {
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, 0, *body, ent);
|
|
num_events++;
|
|
}
|
|
}
|
|
|
|
/* XG Multi Part Data parameter change */
|
|
else if (len >= 10 &&
|
|
val[0] == 0x43 && /* Yamaha ID */
|
|
val[2] == 0x4C && /* XG Model ID */
|
|
((val[1] < 0x10 && val[5] == 0x08 && /* Bulk Dump */
|
|
(val[4] == 0x29 || val[4] == 0x3F)) || /* Blocks 1 or 2 */
|
|
(val[1] >= 0x10 && val[3] == 0x08))) /* Parameter Change */
|
|
{
|
|
uint8_t addhigh, addmid, addlow; /* Addresses */
|
|
const uint8_t *body; /* SysEx body */
|
|
uint8_t p; /* Channel part number [0..15] */
|
|
int ent; /* Entry # of sub-event */
|
|
const uint8_t *body_end; /* End of SysEx body */
|
|
|
|
if (val[1] < 0x10) /* Bulk Dump */
|
|
{
|
|
addhigh = val[5];
|
|
addmid = val[6];
|
|
addlow = val[7];
|
|
body = val + 8;
|
|
p = addmid;
|
|
body_end = val + len - 3;
|
|
}
|
|
else /* Parameter Change */
|
|
{
|
|
addhigh = val[3];
|
|
addmid = val[4];
|
|
addlow = val[5];
|
|
body = val + 6;
|
|
p = addmid;
|
|
body_end = val + len - 2;
|
|
}
|
|
|
|
/* set the SYSEX_XG_MSB info */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_MSB, p, addhigh, addmid);
|
|
num_events++;
|
|
|
|
for (ent = addlow; body <= body_end; body++, ent++) {
|
|
switch (ent) {
|
|
case 0x00: /* Element Reserve */
|
|
/* //printMessage(CMSG_INFO,VERB_NOISY,"Element Reserve is not supported. (CH:%d VAL:%d)", p, *body); */
|
|
break;
|
|
|
|
case 0x01: /* bank select MSB */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_TONE_BANK_MSB, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x02: /* bank select LSB */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_TONE_BANK_LSB, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x03: /* program number */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_PROGRAM, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x04: /* Rcv CHANNEL */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, p, *body, 0x99);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x05: /* mono/poly mode */
|
|
if (*body == 0) { SETMIDIEVENT(evm[num_events], 0, ME_MONO, p, 0, SYSEX_TAG); }
|
|
else { SETMIDIEVENT(evm[num_events], 0, ME_POLY, p, 0, SYSEX_TAG); }
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x06: /* Same Note Number Key On Assign */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, p, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x07: /* Part Mode */
|
|
drum_setup_xg[*body] = p;
|
|
SETMIDIEVENT(evm[num_events], 0, ME_DRUMPART, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x08: /* note shift */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_KEYSHIFT, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x09: /* Detune 1st bit */
|
|
break;
|
|
|
|
case 0x0A: /* Detune 2nd bit */
|
|
break;
|
|
|
|
case 0x0B: /* volume */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_MAINVOLUME, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0C: /* Velocity Sense Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, p, *body, 0x21);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0D: /* Velocity Sense Offset */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, p, *body, 0x22);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0E: /* pan */
|
|
if (*body == 0) {
|
|
SETMIDIEVENT(evm[num_events], 0, ME_RANDOM_PAN, p, 0, SYSEX_TAG);
|
|
}
|
|
else {
|
|
SETMIDIEVENT(evm[num_events], 0, ME_PAN, p, *body, SYSEX_TAG);
|
|
}
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x0F: /* Note Limit Low */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x42);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x10: /* Note Limit High */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x43);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x11: /* Dry Level */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, p, *body, ent);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x12: /* chorus send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_CHORUS_EFFECT, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x13: /* reverb send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_REVERB_EFFECT, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x14: /* Variation Send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_CELESTE_EFFECT, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x15: /* Vibrato Rate */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x08, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x16: /* Vibrato Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x09, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x17: /* Vibrato Delay */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x0A, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x18: /* Filter Cutoff Frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x20, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x19: /* Filter Resonance */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x21, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x1A: /* EG Attack Time */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x63, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x1B: /* EG Decay Time */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x64, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x1C: /* EG Release Time */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x66, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x1D: /* MW Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x16);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x1E: /* MW Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x17);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x1F: /* MW Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x18);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x20: /* MW LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x1A);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x21: /* MW LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x1B);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x22: /* MW LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x1C);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x23: /* bend pitch control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_RPN_MSB, p, 0, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_RPN_LSB, p, 0, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, (*body - 0x40) & 0x7F, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x24: /* Bend Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x22);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x25: /* Bend Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x23);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x26: /* Bend LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x25);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x27: /* Bend LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x26);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x28: /* Bend LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x27);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x30: /* Rcv Pitch Bend */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x48);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x31: /* Rcv Channel Pressure */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x49);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x32: /* Rcv Program Change */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4A);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x33: /* Rcv Control Change */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4B);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x34: /* Rcv Poly Pressure */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4C);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x35: /* Rcv Note Message */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4D);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x36: /* Rcv RPN */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4E);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x37: /* Rcv NRPN */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x4F);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x38: /* Rcv Modulation */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x50);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x39: /* Rcv Volume */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x51);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3A: /* Rcv Pan */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x52);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3B: /* Rcv Expression */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x53);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3C: /* Rcv Hold1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x54);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3D: /* Rcv Portamento */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x55);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3E: /* Rcv Sostenuto */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x56);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x3F: /* Rcv Soft */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x57);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x40: /* Rcv Bank Select */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x58);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x41: /* scale tuning */
|
|
case 0x42:
|
|
case 0x43:
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x48:
|
|
case 0x49:
|
|
case 0x4a:
|
|
case 0x4b:
|
|
case 0x4c:
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SCALE_TUNING, p, ent - 0x41, *body - 64);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x4D: /* CAT Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x00);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x4E: /* CAT Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x01);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x4F: /* CAT Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x02);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x50: /* CAT LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x04);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x51: /* CAT LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x05);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x52: /* CAT LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x06);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x53: /* PAT Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x0B);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x54: /* PAT Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x0C);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x55: /* PAT Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x0D);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x56: /* PAT LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x0F);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x57: /* PAT LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x10);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x58: /* PAT LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x11);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x59: /* AC1 Controller Number */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"AC1 Controller Number is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x5A: /* AC1 Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x2C);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x5B: /* AC1 Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x2D);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x5C: /* AC1 Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x2E);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x5D: /* AC1 LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x30);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x5E: /* AC1 LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x31);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x5F: /* AC1 LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x32);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x60: /* AC2 Controller Number */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"AC2 Controller Number is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x61: /* AC2 Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x37);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x62: /* AC2 Filter Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x38);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x63: /* AC2 Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x39);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x64: /* AC2 LFO PMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x3B);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x65: /* AC2 LFO FMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x3C);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x66: /* AC2 LFO AMod Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x3D);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x67: /* Portamento Switch */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_PORTAMENTO, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
|
|
case 0x68: /* Portamento Time */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_PORTAMENTO_TIME_MSB, p, *body, SYSEX_TAG);
|
|
num_events++;
|
|
|
|
case 0x69: /* Pitch EG Initial Level */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Pitch EG Initial Level is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x6A: /* Pitch EG Attack Time */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Pitch EG Attack Time is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x6B: /* Pitch EG Release Level */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Pitch EG Release Level is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x6C: /* Pitch EG Release Time */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Pitch EG Release Time is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x6D: /* Velocity Limit Low */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x44);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x6E: /* Velocity Limit High */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, p, *body, 0x45);
|
|
num_events++;
|
|
break;
|
|
|
|
case 0x70: /* Bend Pitch Low Control */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Bend Pitch Low Control is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x71: /* Filter EG Depth */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Filter EG Depth is not supported. (CH:%d VAL:%d)", p, *body);
|
|
break;
|
|
|
|
case 0x72: /* EQ BASS */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x30, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x73: /* EQ TREBLE */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x31, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x76: /* EQ BASS frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x34, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
case 0x77: /* EQ TREBLE frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, p, 0x35, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, p, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported XG Bulk Dump SysEx. (ADDR:%02X %02X %02X VAL:%02X)", addhigh, addlow, ent, *body);
|
|
continue;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* XG Drum Setup */
|
|
else if (len >= 10 &&
|
|
val[0] == 0x43 && /* Yamaha ID */
|
|
val[2] == 0x4C && /* XG Model ID */
|
|
((val[1] < 0x10 && (val[5] & 0xF0) == 0x30) || /* Bulk Dump*/
|
|
(val[1] >= 0x10 && (val[3] & 0xF0) == 0x30))) /* Parameter Change */
|
|
{
|
|
uint8_t addhigh, addmid, addlow; /* Addresses */
|
|
const uint8_t *body; /* SysEx body */
|
|
uint8_t dp, note; /* Channel part number [0..15] */
|
|
int ent; /* Entry # of sub-event */
|
|
const uint8_t *body_end; /* End of SysEx body */
|
|
|
|
if (val[1] < 0x10) /* Bulk Dump */
|
|
{
|
|
addhigh = val[5];
|
|
addmid = val[6];
|
|
addlow = val[7];
|
|
body = val + 8;
|
|
body_end = val + len - 3;
|
|
}
|
|
else /* Parameter Change */
|
|
{
|
|
addhigh = val[3];
|
|
addmid = val[4];
|
|
addlow = val[5];
|
|
body = val + 6;
|
|
body_end = val + len - 2;
|
|
}
|
|
|
|
dp = drum_setup_xg[(addhigh & 0x0F) + 1];
|
|
note = addmid;
|
|
|
|
/* set the SYSEX_XG_MSB info */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_MSB, dp, addhigh, addmid);
|
|
num_events++;
|
|
|
|
for (ent = addlow; body <= body_end; body++, ent++) {
|
|
switch (ent) {
|
|
case 0x00: /* Pitch Coarse */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x18, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x01: /* Pitch Fine */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x19, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x02: /* Level */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x1A, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x03: /* Alternate Group */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Alternate Group is not supported. (CH:%d NOTE:%d VAL:%d)", dp, note, *body);
|
|
break;
|
|
case 0x04: /* Pan */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x1C, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x05: /* Reverb Send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x1D, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x06: /* Chorus Send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x1E, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x07: /* Variation Send */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x1F, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x08: /* Key Assign */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Key Assign is not supported. (CH:%d NOTE:%d VAL:%d)", dp, note, *body);
|
|
break;
|
|
case 0x09: /* Rcv Note Off */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_MSB, dp, note, 0);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_SYSEX_LSB, dp, *body, 0x46);
|
|
num_events += 2;
|
|
break;
|
|
case 0x0A: /* Rcv Note On */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_MSB, dp, note, 0);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_SYSEX_LSB, dp, *body, 0x47);
|
|
num_events += 2;
|
|
break;
|
|
case 0x0B: /* Filter Cutoff Frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x14, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x0C: /* Filter Resonance */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x15, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x0D: /* EG Attack */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x16, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x0E: /* EG Decay1 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, dp, *body, ent);
|
|
num_events++;
|
|
break;
|
|
case 0x0F: /* EG Decay2 */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, dp, *body, ent);
|
|
num_events++;
|
|
break;
|
|
case 0x20: /* EQ BASS */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x30, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x21: /* EQ TREBLE */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x31, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x24: /* EQ BASS frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x34, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x25: /* EQ TREBLE frequency */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_NRPN_MSB, dp, 0x35, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 1], 0, ME_NRPN_LSB, dp, note, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[num_events + 2], 0, ME_DATA_ENTRY_MSB, dp, *body, SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x50: /* High Pass Filter Cutoff Frequency */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"High Pass Filter Cutoff Frequency is not supported. (CH:%d NOTE:%d VAL:%d)", dp, note, *body);
|
|
break;
|
|
case 0x60: /* Velocity Pitch Sense */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity Pitch Sense is not supported. (CH:%d NOTE:%d VAL:%d)", dp, note, *body);
|
|
break;
|
|
case 0x61: /* Velocity LPF Cutoff Sense */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Velocity LPF Cutoff Sense is not supported. (CH:%d NOTE:%d VAL:%d)", dp, note, *body);
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported XG Bulk Dump SysEx. (ADDR:%02X %02X %02X VAL:%02X)", addhigh, addmid, ent, *body);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* parsing GS System Exclusive Message...
|
|
*
|
|
* val[4] == Parameter Address(High)
|
|
* val[5] == Parameter Address(Middle)
|
|
* val[6] == Parameter Address(Low)
|
|
* val[7]... == Data...
|
|
* val[last] == Checksum(== 128 - (sum of addresses&data bytes % 128))
|
|
*/
|
|
else if (len >= 9 &&
|
|
val[0] == 0x41 && /* Roland ID */
|
|
val[1] == 0x10 && /* Device ID */
|
|
val[2] == 0x42 && /* GS Model ID */
|
|
val[3] == 0x12) /* Data Set Command */
|
|
{
|
|
uint8_t p, dp, udn, gslen, port = 0;
|
|
int i, addr, addr_h, addr_m, addr_l, checksum;
|
|
p = block_to_part(val[5], midi_port_number);
|
|
|
|
/* calculate checksum */
|
|
checksum = 0;
|
|
for (gslen = 9; gslen < len; gslen++)
|
|
if (val[gslen] == 0xF7)
|
|
break;
|
|
for (i = 4; i<gslen - 1; i++) {
|
|
checksum += val[i];
|
|
}
|
|
if (((128 - (checksum & 0x7F)) & 0x7F) != val[gslen - 1]) {
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"GS SysEx: Checksum Error.");
|
|
return num_events;
|
|
}
|
|
|
|
/* drum channel */
|
|
dp = rhythm_part[(val[5] & 0xF0) >> 4];
|
|
|
|
/* calculate user drumset number */
|
|
udn = (val[5] & 0xF0) >> 4;
|
|
|
|
addr_h = val[4];
|
|
addr_m = val[5];
|
|
addr_l = val[6];
|
|
if (addr_h == 0x50) { /* for double module mode */
|
|
port = 1;
|
|
p = block_to_part(val[5], port);
|
|
addr_h = 0x40;
|
|
}
|
|
else if (addr_h == 0x51) {
|
|
port = 1;
|
|
p = block_to_part(val[5], port);
|
|
addr_h = 0x41;
|
|
}
|
|
addr = (((int32_t)addr_h) << 16 | ((int32_t)addr_m) << 8 | (int32_t)addr_l);
|
|
|
|
switch (addr_h) {
|
|
case 0x40:
|
|
if ((addr & 0xFFF000) == 0x401000) {
|
|
switch (addr & 0xFF) {
|
|
case 0x00: /* Tone Number */
|
|
SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_MSB, p, val[7], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_PROGRAM, p, val[8], SYSEX_TAG);
|
|
num_events += 2;
|
|
break;
|
|
case 0x02: /* Rx. Channel */
|
|
if (val[7] == 0x10) {
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,
|
|
block_to_part(val[5],
|
|
midi_port_number ^ port), 0x80, 0x45);
|
|
}
|
|
else {
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,
|
|
block_to_part(val[5],
|
|
midi_port_number ^ port),
|
|
MERGE_CHANNEL_PORT2(val[7],
|
|
midi_port_number ^ port), 0x45);
|
|
}
|
|
num_events++;
|
|
break;
|
|
case 0x03: /* Rx. Pitch Bend */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x48);
|
|
num_events++;
|
|
break;
|
|
case 0x04: /* Rx. Channel Pressure */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x49);
|
|
num_events++;
|
|
break;
|
|
case 0x05: /* Rx. Program Change */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4A);
|
|
num_events++;
|
|
break;
|
|
case 0x06: /* Rx. Control Change */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4B);
|
|
num_events++;
|
|
break;
|
|
case 0x07: /* Rx. Poly Pressure */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4C);
|
|
num_events++;
|
|
break;
|
|
case 0x08: /* Rx. Note Message */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4D);
|
|
num_events++;
|
|
break;
|
|
case 0x09: /* Rx. RPN */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4E);
|
|
num_events++;
|
|
break;
|
|
case 0x0A: /* Rx. NRPN */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x4F);
|
|
num_events++;
|
|
break;
|
|
case 0x0B: /* Rx. Modulation */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x50);
|
|
num_events++;
|
|
break;
|
|
case 0x0C: /* Rx. Volume */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x51);
|
|
num_events++;
|
|
break;
|
|
case 0x0D: /* Rx. Panpot */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x52);
|
|
num_events++;
|
|
break;
|
|
case 0x0E: /* Rx. Expression */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x53);
|
|
num_events++;
|
|
break;
|
|
case 0x0F: /* Rx. Hold1 */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x54);
|
|
num_events++;
|
|
break;
|
|
case 0x10: /* Rx. Portamento */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x55);
|
|
num_events++;
|
|
break;
|
|
case 0x11: /* Rx. Sostenuto */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x56);
|
|
num_events++;
|
|
break;
|
|
case 0x12: /* Rx. Soft */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x57);
|
|
num_events++;
|
|
break;
|
|
case 0x13: /* MONO/POLY Mode */
|
|
if (val[7] == 0) { SETMIDIEVENT(evm[0], 0, ME_MONO, p, val[7], SYSEX_TAG); }
|
|
else { SETMIDIEVENT(evm[0], 0, ME_POLY, p, val[7], SYSEX_TAG); }
|
|
num_events++;
|
|
break;
|
|
case 0x14: /* Assign Mode */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x24);
|
|
num_events++;
|
|
break;
|
|
case 0x15: /* Use for Rhythm Part */
|
|
if (val[7]) {
|
|
rhythm_part[val[7] - 1] = p;
|
|
}
|
|
break;
|
|
case 0x16: /* Pitch Key Shift (dummy. see parse_sysex_event()) */
|
|
break;
|
|
case 0x17: /* Pitch Offset Fine */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x26);
|
|
num_events++;
|
|
break;
|
|
case 0x19: /* Part Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_MAINVOLUME, p, val[7], SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
case 0x1A: /* Velocity Sense Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x21);
|
|
num_events++;
|
|
break;
|
|
case 0x1B: /* Velocity Sense Offset */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x22);
|
|
num_events++;
|
|
break;
|
|
case 0x1C: /* Part Panpot */
|
|
if (val[7] == 0) {
|
|
SETMIDIEVENT(evm[0], 0, ME_RANDOM_PAN, p, 0, SYSEX_TAG);
|
|
}
|
|
else {
|
|
SETMIDIEVENT(evm[0], 0, ME_PAN, p, val[7], SYSEX_TAG);
|
|
}
|
|
num_events++;
|
|
break;
|
|
case 0x1D: /* Keyboard Range Low */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x42);
|
|
num_events++;
|
|
break;
|
|
case 0x1E: /* Keyboard Range High */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x43);
|
|
num_events++;
|
|
break;
|
|
case 0x1F: /* CC1 Controller Number */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"CC1 Controller Number is not supported. (CH:%d VAL:%d)", p, val[7]);
|
|
break;
|
|
case 0x20: /* CC2 Controller Number */
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"CC2 Controller Number is not supported. (CH:%d VAL:%d)", p, val[7]);
|
|
break;
|
|
case 0x21: /* Chorus Send Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_CHORUS_EFFECT, p, val[7], SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
case 0x22: /* Reverb Send Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_REVERB_EFFECT, p, val[7], SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
case 0x23: /* Rx. Bank Select */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x58);
|
|
num_events++;
|
|
break;
|
|
case 0x24: /* Rx. Bank Select LSB */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x59);
|
|
num_events++;
|
|
break;
|
|
case 0x2C: /* Delay Send Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_CELESTE_EFFECT, p, val[7], SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
case 0x2A: /* Pitch Fine Tune */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x00, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[3], 0, ME_DATA_ENTRY_LSB, p, val[8], SYSEX_TAG);
|
|
num_events += 4;
|
|
break;
|
|
case 0x30: /* TONE MODIFY1: Vibrato Rate */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x08, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x31: /* TONE MODIFY2: Vibrato Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x09, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x32: /* TONE MODIFY3: TVF Cutoff Freq */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x20, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x33: /* TONE MODIFY4: TVF Resonance */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x21, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x34: /* TONE MODIFY5: TVF&TVA Env.attack */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x63, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x35: /* TONE MODIFY6: TVF&TVA Env.decay */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x64, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x36: /* TONE MODIFY7: TVF&TVA Env.release */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x66, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x37: /* TONE MODIFY8: Vibrato Delay */
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, p, 0x01, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, p, 0x0A, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x40: /* Scale Tuning */
|
|
for (i = 0; i < 12; i++) {
|
|
SETMIDIEVENT(evm[i],
|
|
0, ME_SCALE_TUNING, p, i, val[i + 7] - 64);
|
|
}
|
|
num_events += 12;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
else if ((addr & 0xFFF000) == 0x402000) {
|
|
switch (addr & 0xFF) {
|
|
case 0x00: /* MOD Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x16);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* MOD TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x17);
|
|
num_events++;
|
|
break;
|
|
case 0x02: /* MOD Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x18);
|
|
num_events++;
|
|
break;
|
|
case 0x03: /* MOD LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x19);
|
|
num_events++;
|
|
break;
|
|
case 0x04: /* MOD LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1A);
|
|
num_events++;
|
|
break;
|
|
case 0x05: /* MOD LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1B);
|
|
num_events++;
|
|
break;
|
|
case 0x06: /* MOD LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1C);
|
|
num_events++;
|
|
break;
|
|
case 0x07: /* MOD LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1D);
|
|
num_events++;
|
|
break;
|
|
case 0x08: /* MOD LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1E);
|
|
num_events++;
|
|
break;
|
|
case 0x09: /* MOD LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x1F);
|
|
num_events++;
|
|
break;
|
|
case 0x0A: /* MOD LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x20);
|
|
num_events++;
|
|
break;
|
|
case 0x10: /* !!!FIXME!!! Bend Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_RPN_MSB, p, 0, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_RPN_LSB, p, 0, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, p, (val[7] - 0x40) & 0x7F, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x21);
|
|
num_events += 4;
|
|
break;
|
|
case 0x11: /* Bend TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x22);
|
|
num_events++;
|
|
break;
|
|
case 0x12: /* Bend Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x23);
|
|
num_events++;
|
|
break;
|
|
case 0x13: /* Bend LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x24);
|
|
num_events++;
|
|
break;
|
|
case 0x14: /* Bend LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x25);
|
|
num_events++;
|
|
break;
|
|
case 0x15: /* Bend LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x26);
|
|
num_events++;
|
|
break;
|
|
case 0x16: /* Bend LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x27);
|
|
num_events++;
|
|
break;
|
|
case 0x17: /* Bend LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x28);
|
|
num_events++;
|
|
break;
|
|
case 0x18: /* Bend LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x29);
|
|
num_events++;
|
|
break;
|
|
case 0x19: /* Bend LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2A);
|
|
num_events++;
|
|
break;
|
|
case 0x1A: /* Bend LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2B);
|
|
num_events++;
|
|
break;
|
|
case 0x20: /* CAf Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x00);
|
|
num_events++;
|
|
break;
|
|
case 0x21: /* CAf TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x01);
|
|
num_events++;
|
|
break;
|
|
case 0x22: /* CAf Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x02);
|
|
num_events++;
|
|
break;
|
|
case 0x23: /* CAf LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x03);
|
|
num_events++;
|
|
break;
|
|
case 0x24: /* CAf LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x04);
|
|
num_events++;
|
|
break;
|
|
case 0x25: /* CAf LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x05);
|
|
num_events++;
|
|
break;
|
|
case 0x26: /* CAf LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x06);
|
|
num_events++;
|
|
break;
|
|
case 0x27: /* CAf LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x07);
|
|
num_events++;
|
|
break;
|
|
case 0x28: /* CAf LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x08);
|
|
num_events++;
|
|
break;
|
|
case 0x29: /* CAf LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x09);
|
|
num_events++;
|
|
break;
|
|
case 0x2A: /* CAf LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0A);
|
|
num_events++;
|
|
break;
|
|
case 0x30: /* PAf Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0B);
|
|
num_events++;
|
|
break;
|
|
case 0x31: /* PAf TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0C);
|
|
num_events++;
|
|
break;
|
|
case 0x32: /* PAf Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0D);
|
|
num_events++;
|
|
break;
|
|
case 0x33: /* PAf LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0E);
|
|
num_events++;
|
|
break;
|
|
case 0x34: /* PAf LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x0F);
|
|
num_events++;
|
|
break;
|
|
case 0x35: /* PAf LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x10);
|
|
num_events++;
|
|
break;
|
|
case 0x36: /* PAf LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x11);
|
|
num_events++;
|
|
break;
|
|
case 0x37: /* PAf LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x12);
|
|
num_events++;
|
|
break;
|
|
case 0x38: /* PAf LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x13);
|
|
num_events++;
|
|
break;
|
|
case 0x39: /* PAf LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x14);
|
|
num_events++;
|
|
break;
|
|
case 0x3A: /* PAf LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x15);
|
|
num_events++;
|
|
break;
|
|
case 0x40: /* CC1 Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2C);
|
|
num_events++;
|
|
break;
|
|
case 0x41: /* CC1 TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2D);
|
|
num_events++;
|
|
break;
|
|
case 0x42: /* CC1 Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2E);
|
|
num_events++;
|
|
break;
|
|
case 0x43: /* CC1 LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x2F);
|
|
num_events++;
|
|
break;
|
|
case 0x44: /* CC1 LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x30);
|
|
num_events++;
|
|
break;
|
|
case 0x45: /* CC1 LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x31);
|
|
num_events++;
|
|
break;
|
|
case 0x46: /* CC1 LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x32);
|
|
num_events++;
|
|
break;
|
|
case 0x47: /* CC1 LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x33);
|
|
num_events++;
|
|
break;
|
|
case 0x48: /* CC1 LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x34);
|
|
num_events++;
|
|
break;
|
|
case 0x49: /* CC1 LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x35);
|
|
num_events++;
|
|
break;
|
|
case 0x4A: /* CC1 LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x36);
|
|
num_events++;
|
|
break;
|
|
case 0x50: /* CC2 Pitch Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x37);
|
|
num_events++;
|
|
break;
|
|
case 0x51: /* CC2 TVF Cutoff Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x38);
|
|
num_events++;
|
|
break;
|
|
case 0x52: /* CC2 Amplitude Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x39);
|
|
num_events++;
|
|
break;
|
|
case 0x53: /* CC2 LFO1 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3A);
|
|
num_events++;
|
|
break;
|
|
case 0x54: /* CC2 LFO1 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3B);
|
|
num_events++;
|
|
break;
|
|
case 0x55: /* CC2 LFO1 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3C);
|
|
num_events++;
|
|
break;
|
|
case 0x56: /* CC2 LFO1 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3D);
|
|
num_events++;
|
|
break;
|
|
case 0x57: /* CC2 LFO2 Rate Control */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3E);
|
|
num_events++;
|
|
break;
|
|
case 0x58: /* CC2 LFO2 Pitch Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x3F);
|
|
num_events++;
|
|
break;
|
|
case 0x59: /* CC2 LFO2 TVF Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x40);
|
|
num_events++;
|
|
break;
|
|
case 0x5A: /* CC2 LFO2 TVA Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_LSB, p, val[7], 0x41);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
else if ((addr & 0xFFFF00) == 0x400100) {
|
|
switch (addr & 0xFF) {
|
|
case 0x30: /* Reverb Macro */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x05);
|
|
num_events++;
|
|
break;
|
|
case 0x31: /* Reverb Character */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x06);
|
|
num_events++;
|
|
break;
|
|
case 0x32: /* Reverb Pre-LPF */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x07);
|
|
num_events++;
|
|
break;
|
|
case 0x33: /* Reverb Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x08);
|
|
num_events++;
|
|
break;
|
|
case 0x34: /* Reverb Time */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x09);
|
|
num_events++;
|
|
break;
|
|
case 0x35: /* Reverb Delay Feedback */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x0A);
|
|
num_events++;
|
|
break;
|
|
case 0x36: /* Unknown Reverb Parameter */
|
|
break;
|
|
case 0x37: /* Reverb Predelay Time */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x0C);
|
|
num_events++;
|
|
break;
|
|
case 0x38: /* Chorus Macro */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x0D);
|
|
num_events++;
|
|
break;
|
|
case 0x39: /* Chorus Pre-LPF */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x0E);
|
|
num_events++;
|
|
break;
|
|
case 0x3A: /* Chorus Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x0F);
|
|
num_events++;
|
|
break;
|
|
case 0x3B: /* Chorus Feedback */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x10);
|
|
num_events++;
|
|
break;
|
|
case 0x3C: /* Chorus Delay */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x11);
|
|
num_events++;
|
|
break;
|
|
case 0x3D: /* Chorus Rate */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x12);
|
|
num_events++;
|
|
break;
|
|
case 0x3E: /* Chorus Depth */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x13);
|
|
num_events++;
|
|
break;
|
|
case 0x3F: /* Chorus Send Level to Reverb */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x14);
|
|
num_events++;
|
|
break;
|
|
case 0x40: /* Chorus Send Level to Delay */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x15);
|
|
num_events++;
|
|
break;
|
|
case 0x50: /* Delay Macro */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x16);
|
|
num_events++;
|
|
break;
|
|
case 0x51: /* Delay Pre-LPF */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x17);
|
|
num_events++;
|
|
break;
|
|
case 0x52: /* Delay Time Center */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x18);
|
|
num_events++;
|
|
break;
|
|
case 0x53: /* Delay Time Ratio Left */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x19);
|
|
num_events++;
|
|
break;
|
|
case 0x54: /* Delay Time Ratio Right */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1A);
|
|
num_events++;
|
|
break;
|
|
case 0x55: /* Delay Level Center */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1B);
|
|
num_events++;
|
|
break;
|
|
case 0x56: /* Delay Level Left */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1C);
|
|
num_events++;
|
|
break;
|
|
case 0x57: /* Delay Level Right */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1D);
|
|
num_events++;
|
|
break;
|
|
case 0x58: /* Delay Level */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1E);
|
|
num_events++;
|
|
break;
|
|
case 0x59: /* Delay Feedback */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x1F);
|
|
num_events++;
|
|
break;
|
|
case 0x5A: /* Delay Send Level to Reverb */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x20);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
else if ((addr & 0xFFFF00) == 0x400200) {
|
|
switch (addr & 0xFF) { /* EQ Parameter */
|
|
case 0x00: /* EQ LOW FREQ */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x01);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* EQ LOW GAIN */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x02);
|
|
num_events++;
|
|
break;
|
|
case 0x02: /* EQ HIGH FREQ */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x03);
|
|
num_events++;
|
|
break;
|
|
case 0x03: /* EQ HIGH GAIN */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x04);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
else if ((addr & 0xFFFF00) == 0x400300) {
|
|
switch (addr & 0xFF) { /* Insertion Effect Parameter */
|
|
case 0x00:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x27);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_GS_LSB, p, val[8], 0x28);
|
|
num_events += 2;
|
|
break;
|
|
case 0x03:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x29);
|
|
num_events++;
|
|
break;
|
|
case 0x04:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2A);
|
|
num_events++;
|
|
break;
|
|
case 0x05:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2B);
|
|
num_events++;
|
|
break;
|
|
case 0x06:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2C);
|
|
num_events++;
|
|
break;
|
|
case 0x07:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2D);
|
|
num_events++;
|
|
break;
|
|
case 0x08:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2E);
|
|
num_events++;
|
|
break;
|
|
case 0x09:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x2F);
|
|
num_events++;
|
|
break;
|
|
case 0x0A:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x30);
|
|
num_events++;
|
|
break;
|
|
case 0x0B:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x31);
|
|
num_events++;
|
|
break;
|
|
case 0x0C:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x32);
|
|
num_events++;
|
|
break;
|
|
case 0x0D:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x33);
|
|
num_events++;
|
|
break;
|
|
case 0x0E:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x34);
|
|
num_events++;
|
|
break;
|
|
case 0x0F:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x35);
|
|
num_events++;
|
|
break;
|
|
case 0x10:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x36);
|
|
num_events++;
|
|
break;
|
|
case 0x11:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x37);
|
|
num_events++;
|
|
break;
|
|
case 0x12:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x38);
|
|
num_events++;
|
|
break;
|
|
case 0x13:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x39);
|
|
num_events++;
|
|
break;
|
|
case 0x14:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3A);
|
|
num_events++;
|
|
break;
|
|
case 0x15:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3B);
|
|
num_events++;
|
|
break;
|
|
case 0x16:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3C);
|
|
num_events++;
|
|
break;
|
|
case 0x17:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3D);
|
|
num_events++;
|
|
break;
|
|
case 0x18:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3E);
|
|
num_events++;
|
|
break;
|
|
case 0x19:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x3F);
|
|
num_events++;
|
|
break;
|
|
case 0x1B:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x40);
|
|
num_events++;
|
|
break;
|
|
case 0x1C:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x41);
|
|
num_events++;
|
|
break;
|
|
case 0x1D:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x42);
|
|
num_events++;
|
|
break;
|
|
case 0x1E:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x43);
|
|
num_events++;
|
|
break;
|
|
case 0x1F:
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x44);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
else if ((addr & 0xFFF000) == 0x404000) {
|
|
switch (addr & 0xFF) {
|
|
case 0x00: /* TONE MAP NUMBER */
|
|
SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_LSB, p, val[7], SYSEX_TAG);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* TONE MAP-0 NUMBER */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x25);
|
|
num_events++;
|
|
break;
|
|
case 0x20: /* EQ ON/OFF */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x00);
|
|
num_events++;
|
|
break;
|
|
case 0x22: /* EFX ON/OFF */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB, p, val[7], 0x23);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0x41:
|
|
switch (addr & 0xF00) {
|
|
case 0x100: /* Play Note Number */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_GS_LSB, dp, val[7], 0x47);
|
|
num_events += 2;
|
|
break;
|
|
case 0x200:
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1A, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x400:
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1C, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x500:
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1D, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x600:
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1E, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x700: /* Rx. Note Off */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_LSB, dp, val[7], 0x46);
|
|
num_events += 2;
|
|
break;
|
|
case 0x800: /* Rx. Note On */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_LSB, dp, val[7], 0x47);
|
|
num_events += 2;
|
|
break;
|
|
case 0x900:
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1F, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
break;
|
|
case 0x21: /* User Drumset */
|
|
switch (addr & 0xF00) {
|
|
case 0x100: /* Play Note */
|
|
instruments->get_userdrum(64 + udn, val[6])->play_note = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_GS_LSB, dp, val[7], 0x47);
|
|
num_events += 2;
|
|
break;
|
|
case 0x200: /* Level */
|
|
instruments->get_userdrum(64 + udn, val[6])->level = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1A, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x300: /* Assign Group */
|
|
instruments->get_userdrum(64 + udn, val[6])->assign_group = val[7];
|
|
if (val[7] != 0) { instruments->recompute_userdrum_altassign(udn + 64, val[7]); }
|
|
break;
|
|
case 0x400: /* Panpot */
|
|
instruments->get_userdrum(64 + udn, val[6])->pan = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1C, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x500: /* Reverb Send Level */
|
|
instruments->get_userdrum(64 + udn, val[6])->reverb_send_level = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1D, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x600: /* Chorus Send Level */
|
|
instruments->get_userdrum(64 + udn, val[6])->chorus_send_level = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1E, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0x700: /* Rx. Note Off */
|
|
instruments->get_userdrum(64 + udn, val[6])->rx_note_off = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_LSB, dp, val[7], 0x46);
|
|
num_events += 2;
|
|
break;
|
|
case 0x800: /* Rx. Note On */
|
|
instruments->get_userdrum(64 + udn, val[6])->rx_note_on = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_MSB, dp, val[6], 0);
|
|
SETMIDIEVENT(evm[1], 0, ME_SYSEX_LSB, dp, val[7], 0x47);
|
|
num_events += 2;
|
|
break;
|
|
case 0x900: /* Delay Send Level */
|
|
instruments->get_userdrum(64 + udn, val[6])->delay_send_level = val[7];
|
|
SETMIDIEVENT(evm[0], 0, ME_NRPN_MSB, dp, 0x1F, SYSEX_TAG);
|
|
SETMIDIEVENT(evm[1], 0, ME_NRPN_LSB, dp, val[6], SYSEX_TAG);
|
|
SETMIDIEVENT(evm[2], 0, ME_DATA_ENTRY_MSB, dp, val[7], SYSEX_TAG);
|
|
num_events += 3;
|
|
break;
|
|
case 0xA00: /* Source Map */
|
|
instruments->get_userdrum(64 + udn, val[6])->source_map = val[7];
|
|
break;
|
|
case 0xB00: /* Source Prog */
|
|
instruments->get_userdrum(64 + udn, val[6])->source_prog = val[7];
|
|
break;
|
|
#if !defined(TIMIDITY_TOOLS)
|
|
case 0xC00: /* Source Note */
|
|
instruments->get_userdrum(64 + udn, val[6])->source_note = val[7];
|
|
break;
|
|
#endif
|
|
default:
|
|
//printMessage(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)", addr_h, addr_m, addr_l, val[7], val[8]);
|
|
break;
|
|
}
|
|
break;
|
|
case 0x00: /* System */
|
|
switch (addr & 0xfff0) {
|
|
case 0x0100: /* Channel Msg Rx Port (A) */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,
|
|
block_to_part(addr & 0xf, 0), val[7], 0x46);
|
|
num_events++;
|
|
break;
|
|
case 0x0110: /* Channel Msg Rx Port (B) */
|
|
SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,
|
|
block_to_part(addr & 0xf, 1), val[7], 0x46);
|
|
num_events++;
|
|
break;
|
|
default:
|
|
/* printMessage(CMSG_INFO,VERB_NOISY, "Unsupported GS SysEx. "
|
|
"(ADDR:%02X %02X %02X VAL:%02X %02X)",
|
|
addr_h, addr_m, addr_l, val[7], val[8]);*/
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Non-RealTime / RealTime Universal SysEx messages
|
|
* 0 0x7e(Non-RealTime) / 0x7f(RealTime)
|
|
* 1 SysEx device ID. Could be from 0x00 to 0x7f.
|
|
* 0x7f means disregard device.
|
|
* 2 Sub ID
|
|
* ...
|
|
* E 0xf7
|
|
*/
|
|
else if (len > 4 && val[0] >= 0x7e)
|
|
switch (val[2]) {
|
|
case 0x01: /* Sample Dump header */
|
|
case 0x02: /* Sample Dump packet */
|
|
case 0x03: /* Dump Request */
|
|
case 0x04: /* Device Control */
|
|
if (val[3] == 0x05) { /* Global Parameter Control */
|
|
if (val[7] == 0x01 && val[8] == 0x01) { /* Reverb */
|
|
for (i = 9; i < len && val[i] != 0xf7; i += 2) {
|
|
switch (val[i]) {
|
|
case 0x00: /* Reverb Type */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, 0, val[i + 1], 0x60);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* Reverb Time */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, val[i + 1], 0x09);
|
|
num_events++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (val[7] == 0x01 && val[8] == 0x02) { /* Chorus */
|
|
for (i = 9; i < len && val[i] != 0xf7; i += 2) {
|
|
switch (val[i]) {
|
|
case 0x00: /* Chorus Type */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, 0, val[i + 1], 0x61);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* Modulation Rate */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, val[i + 1], 0x12);
|
|
num_events++;
|
|
break;
|
|
case 0x02: /* Modulation Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, val[i + 1], 0x13);
|
|
num_events++;
|
|
break;
|
|
case 0x03: /* Feedback */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, val[i + 1], 0x10);
|
|
num_events++;
|
|
break;
|
|
case 0x04: /* Send To Reverb */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_GS_LSB, 0, val[i + 1], 0x14);
|
|
num_events++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 0x05: /* Sample Dump extensions */
|
|
case 0x06: /* Inquiry Message */
|
|
case 0x07: /* File Dump */
|
|
break;
|
|
case 0x08: /* MIDI Tuning Standard */
|
|
switch (val[3]) {
|
|
case 0x01:
|
|
SETMIDIEVENT(evm[0], 0, ME_BULK_TUNING_DUMP, 0, val[4], 0);
|
|
for (i = 0; i < 128; i++) {
|
|
SETMIDIEVENT(evm[i * 2 + 1], 0, ME_BULK_TUNING_DUMP,
|
|
1, i, val[i * 3 + 21]);
|
|
SETMIDIEVENT(evm[i * 2 + 2], 0, ME_BULK_TUNING_DUMP,
|
|
2, val[i * 3 + 22], val[i * 3 + 23]);
|
|
}
|
|
num_events += 257;
|
|
break;
|
|
case 0x02:
|
|
SETMIDIEVENT(evm[0], 0, ME_SINGLE_NOTE_TUNING,
|
|
0, val[4], 0);
|
|
for (i = 0; i < val[5]; i++) {
|
|
SETMIDIEVENT(evm[i * 2 + 1], 0, ME_SINGLE_NOTE_TUNING,
|
|
1, val[i * 4 + 6], val[i * 4 + 7]);
|
|
SETMIDIEVENT(evm[i * 2 + 2], 0, ME_SINGLE_NOTE_TUNING,
|
|
2, val[i * 4 + 8], val[i * 4 + 9]);
|
|
}
|
|
num_events += val[5] * 2 + 1;
|
|
break;
|
|
case 0x0b:
|
|
channel_tt = ((val[4] & 0x03) << 14 | val[5] << 7 | val[6])
|
|
<< ((val[4] >> 2) * 16);
|
|
if (val[1] == 0x7f) {
|
|
SETMIDIEVENT(evm[0], 0, ME_MASTER_TEMPER_TYPE,
|
|
0, val[7], (val[0] == 0x7f));
|
|
num_events++;
|
|
}
|
|
else {
|
|
for (i = j = 0; i < 32; i++)
|
|
if (channel_tt & 1 << i) {
|
|
SETMIDIEVENT(evm[j], 0, ME_TEMPER_TYPE,
|
|
MERGE_CHANNEL_PORT(i),
|
|
val[7], (val[0] == 0x7f));
|
|
j++;
|
|
}
|
|
num_events += j;
|
|
}
|
|
break;
|
|
case 0x0c:
|
|
SETMIDIEVENT(evm[0], 0, ME_USER_TEMPER_ENTRY,
|
|
0, val[4], val[21]);
|
|
for (i = 0; i < val[21]; i++) {
|
|
SETMIDIEVENT(evm[i * 5 + 1], 0, ME_USER_TEMPER_ENTRY,
|
|
1, val[i * 10 + 22], val[i * 10 + 23]);
|
|
SETMIDIEVENT(evm[i * 5 + 2], 0, ME_USER_TEMPER_ENTRY,
|
|
2, val[i * 10 + 24], val[i * 10 + 25]);
|
|
SETMIDIEVENT(evm[i * 5 + 3], 0, ME_USER_TEMPER_ENTRY,
|
|
3, val[i * 10 + 26], val[i * 10 + 27]);
|
|
SETMIDIEVENT(evm[i * 5 + 4], 0, ME_USER_TEMPER_ENTRY,
|
|
4, val[i * 10 + 28], val[i * 10 + 29]);
|
|
SETMIDIEVENT(evm[i * 5 + 5], 0, ME_USER_TEMPER_ENTRY,
|
|
5, val[i * 10 + 30], val[i * 10 + 31]);
|
|
}
|
|
num_events += val[21] * 5 + 1;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x09: /* General MIDI Message */
|
|
switch (val[3]) {
|
|
case 0x01: /* Channel Pressure */
|
|
for (i = 5; i < len && val[i] != 0xf7; i += 2) {
|
|
switch (val[i]) {
|
|
case 0x00: /* Pitch Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x00);
|
|
num_events++;
|
|
break;
|
|
case 0x01: /* Filter Cutoff Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x01);
|
|
num_events++;
|
|
break;
|
|
case 0x02: /* Amplitude Control */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x02);
|
|
num_events++;
|
|
break;
|
|
case 0x03: /* LFO Pitch Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x04);
|
|
num_events++;
|
|
break;
|
|
case 0x04: /* LFO Filter Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x05);
|
|
num_events++;
|
|
break;
|
|
case 0x05: /* LFO Amplitude Depth */
|
|
SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_LSB, val[4], val[i + 1], 0x06);
|
|
num_events++;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 0x7b: /* End of File */
|
|
case 0x7c: /* Handshaking Message: Wait */
|
|
case 0x7d: /* Handshaking Message: Cancel */
|
|
case 0x7e: /* Handshaking Message: NAK */
|
|
case 0x7f: /* Handshaking Message: ACK */
|
|
break;
|
|
}
|
|
|
|
return(num_events);
|
|
}
|
|
|
|
|
|
int SysexConvert::parse_sysex_event(const uint8_t *val, int32_t len, MidiEvent *ev, Instruments *instruments)
|
|
{
|
|
uint16_t vol;
|
|
|
|
if (len >= 10 &&
|
|
val[0] == 0x41 && /* Roland ID */
|
|
val[1] == 0x10 && /* Device ID */
|
|
val[2] == 0x42 && /* GS Model ID */
|
|
val[3] == 0x12) /* Data Set Command */
|
|
{
|
|
/* Roland GS-Based Synthesizers.
|
|
* val[4..6] is address, val[7..len-2] is body.
|
|
*
|
|
* GS Channel part number
|
|
* 0 10
|
|
* 1-9 1-9
|
|
* 10-15 11-16
|
|
*/
|
|
|
|
int32_t addr, checksum, i; /* SysEx address */
|
|
const uint8_t *body; /* SysEx body */
|
|
uint8_t p, gslen; /* Channel part number [0..15] */
|
|
|
|
/* check Checksum */
|
|
checksum = 0;
|
|
for (gslen = 9; gslen < len; gslen++)
|
|
if (val[gslen] == 0xF7)
|
|
break;
|
|
for (i = 4; i < gslen - 1; i++) {
|
|
checksum += val[i];
|
|
}
|
|
if (((128 - (checksum & 0x7F)) & 0x7F) != val[gslen - 1]) {
|
|
return 0;
|
|
}
|
|
|
|
addr = (((int32_t)val[4]) << 16 |
|
|
((int32_t)val[5]) << 8 |
|
|
(int32_t)val[6]);
|
|
body = val + 7;
|
|
p = (uint8_t)((addr >> 8) & 0xF);
|
|
if (p == 0)
|
|
p = 9;
|
|
else if (p <= 9)
|
|
p--;
|
|
p = MERGE_CHANNEL_PORT(p);
|
|
|
|
if (val[4] == 0x50) { /* for double module mode */
|
|
p += 16;
|
|
addr = (((int32_t)0x40) << 16 |
|
|
((int32_t)val[5]) << 8 |
|
|
(int32_t)val[6]);
|
|
}
|
|
else { /* single module mode */
|
|
addr = (((int32_t)val[4]) << 16 |
|
|
((int32_t)val[5]) << 8 |
|
|
(int32_t)val[6]);
|
|
}
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401015) /* Rhythm Parts */
|
|
{
|
|
/* GS drum part check from Masaaki Koyanagi's patch (GS_Drum_Part_Check()) */
|
|
/* Modified by Masanao Izumo */
|
|
SETMIDIEVENT(*ev, 0, ME_DRUMPART, p, *body, SYSEX_TAG);
|
|
return 1;
|
|
}
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401016) /* Key Shift */
|
|
{
|
|
SETMIDIEVENT(*ev, 0, ME_KEYSHIFT, p, *body, SYSEX_TAG);
|
|
return 1;
|
|
}
|
|
|
|
if (addr == 0x400000) /* Master Tune, not for SMF */
|
|
{
|
|
uint16_t tune = ((body[1] & 0xF) << 8) | ((body[2] & 0xF) << 4) | (body[3] & 0xF);
|
|
|
|
if (tune < 0x18)
|
|
tune = 0x18;
|
|
else if (tune > 0x7E8)
|
|
tune = 0x7E8;
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_TUNING, 0, tune & 0xFF, (tune >> 8) & 0x7F);
|
|
return 1;
|
|
}
|
|
|
|
if (addr == 0x400004) /* Master Volume */
|
|
{
|
|
vol = gs_convert_master_vol(*body);
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_VOLUME,
|
|
0, vol & 0xFF, (vol >> 8) & 0xFF);
|
|
return 1;
|
|
}
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401019) /* Volume on/off */
|
|
{
|
|
#if 0
|
|
SETMIDIEVENT(*ev, 0, ME_VOLUME_ONOFF, p, *body >= 64, SYSEX_TAG);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401002) /* Receive channel on/off */
|
|
{
|
|
#if 0
|
|
SETMIDIEVENT(*ev, 0, ME_RECEIVE_CHANNEL, (uint8_t)p, *body >= 64, SYSEX_TAG);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if (0x402000 <= addr && addr <= 0x402F5A) /* Controller Routing */
|
|
return 0;
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401040) /* Alternate Scale Tunings */
|
|
return 0;
|
|
|
|
if ((addr & 0xFFFFF0) == 0x400130) /* Changing Effects */
|
|
{
|
|
#if 0
|
|
struct chorus_text_gs_t *chorus_text = &(reverb->chorus_status_gs.text);
|
|
switch (addr & 0xF)
|
|
{
|
|
case 0x8: /* macro */
|
|
memcpy(chorus_text->macro, body, 3);
|
|
break;
|
|
case 0x9: /* PRE-LPF */
|
|
memcpy(chorus_text->pre_lpf, body, 3);
|
|
break;
|
|
case 0xa: /* level */
|
|
memcpy(chorus_text->level, body, 3);
|
|
break;
|
|
case 0xb: /* feed back */
|
|
memcpy(chorus_text->feed_back, body, 3);
|
|
break;
|
|
case 0xc: /* delay */
|
|
memcpy(chorus_text->delay, body, 3);
|
|
break;
|
|
case 0xd: /* rate */
|
|
memcpy(chorus_text->rate, body, 3);
|
|
break;
|
|
case 0xe: /* depth */
|
|
memcpy(chorus_text->depth, body, 3);
|
|
break;
|
|
case 0xf: /* send level */
|
|
memcpy(chorus_text->send_level, body, 3);
|
|
break;
|
|
default: break;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if ((addr & 0xFFF0FF) == 0x401003) /* Rx Pitch-Bend */
|
|
return 0;
|
|
|
|
if (addr == 0x400110) /* Voice Reserve */
|
|
{
|
|
#if 0
|
|
if (len >= 25)
|
|
memcpy(reverb->chorus_status_gs.text.voice_reserve, body, 18);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
if (addr == 0x40007F || /* GS Reset */
|
|
addr == 0x00007F) /* SC-88 Single Module */
|
|
{
|
|
SETMIDIEVENT(*ev, 0, ME_RESET, 0, GS_SYSTEM_MODE, SYSEX_TAG);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (len > 9 &&
|
|
val[0] == 0x41 && /* Roland ID */
|
|
val[1] == 0x10 && /* Device ID */
|
|
val[2] == 0x45 &&
|
|
val[3] == 0x12 &&
|
|
val[4] == 0x10 &&
|
|
val[5] == 0x00 &&
|
|
val[6] == 0x00)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (len > 9 && /* GS lcd event. by T.Nogami*/
|
|
val[0] == 0x41 && /* Roland ID */
|
|
val[1] == 0x10 && /* Device ID */
|
|
val[2] == 0x45 &&
|
|
val[3] == 0x12 &&
|
|
val[4] == 0x10 &&
|
|
val[5] == 0x01 &&
|
|
val[6] == 0x00)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* val[1] can have values other than 0x10 for the XG ON event, which
|
|
* work on real XG hardware. I have several midi that use 0x1f instead
|
|
* of 0x10. playmidi.h lists 0x10 - 0x13 as MU50/80/90/100. I don't
|
|
* know what real world Device Number 0x1f would correspond to, but the
|
|
* XG spec says the entire 0x1n range is valid, and 0x1f works on real
|
|
* hardware, so I have modified the check below to accept the entire
|
|
* 0x1n range.
|
|
*
|
|
* I think there are/were some hacks somewhere in playmidi.c (?) to work
|
|
* around non- 0x10 values, but this fixes the root of the problem, which
|
|
* allows the server mode to handle XG initialization properly as well.
|
|
*/
|
|
if (len >= 8 &&
|
|
val[0] == 0x43 &&
|
|
(val[1] >= 0x10 && val[1] <= 0x1f) &&
|
|
val[2] == 0x4C)
|
|
{
|
|
int addr = (val[3] << 16) | (val[4] << 8) | val[5];
|
|
|
|
if (addr == 0x00007E) /* XG SYSTEM ON */
|
|
{
|
|
SETMIDIEVENT(*ev, 0, ME_RESET, 0, XG_SYSTEM_MODE, SYSEX_TAG);
|
|
return 1;
|
|
}
|
|
else if (addr == 0x000000 && len >= 12) /* XG Master Tune */
|
|
{
|
|
uint16_t tune = ((val[7] & 0xF) << 8) | ((val[8] & 0xF) << 4) | (val[9] & 0xF);
|
|
|
|
if (tune > 0x7FF)
|
|
tune = 0x7FF;
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_TUNING, 0, tune & 0xFF, (tune >> 8) & 0x7F);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (len >= 7 && val[0] == 0x7F && val[1] == 0x7F)
|
|
{
|
|
if (val[2] == 0x04 && val[3] == 0x03) /* GM2 Master Fine Tune */
|
|
{
|
|
uint16_t tune = (val[4] & 0x7F) | (val[5] << 7) | 0x4000;
|
|
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_TUNING, 0, tune & 0xFF, (tune >> 8) & 0x7F);
|
|
return 1;
|
|
}
|
|
if (val[2] == 0x04 && val[3] == 0x04) /* GM2 Master Coarse Tune */
|
|
{
|
|
uint8_t tune = val[5];
|
|
|
|
if (tune < 0x28)
|
|
tune = 0x28;
|
|
else if (tune > 0x58)
|
|
tune = 0x58;
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_TUNING, 0, tune, 0x80);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* Non-RealTime / RealTime Universal SysEx messages
|
|
* 0 0x7e(Non-RealTime) / 0x7f(RealTime)
|
|
* 1 SysEx device ID. Could be from 0x00 to 0x7f.
|
|
* 0x7f means disregard device.
|
|
* 2 Sub ID
|
|
* ...
|
|
* E 0xf7
|
|
*/
|
|
if (len > 4 && val[0] >= 0x7e)
|
|
switch (val[2]) {
|
|
case 0x01: /* Sample Dump header */
|
|
case 0x02: /* Sample Dump packet */
|
|
case 0x03: /* Dump Request */
|
|
break;
|
|
case 0x04: /* MIDI Time Code Setup/Device Control */
|
|
switch (val[3]) {
|
|
case 0x01: /* Master Volume */
|
|
vol = gm_convert_master_vol(val[4], val[5]);
|
|
if (val[1] == 0x7f) {
|
|
SETMIDIEVENT(*ev, 0, ME_MASTER_VOLUME, 0,
|
|
vol & 0xff, vol >> 8 & 0xff);
|
|
}
|
|
else {
|
|
SETMIDIEVENT(*ev, 0, ME_MAINVOLUME,
|
|
MERGE_CHANNEL_PORT(val[1]),
|
|
vol >> 8 & 0xff, 0);
|
|
}
|
|
return 1;
|
|
}
|
|
break;
|
|
case 0x05: /* Sample Dump extensions */
|
|
case 0x06: /* Inquiry Message */
|
|
case 0x07: /* File Dump */
|
|
break;
|
|
case 0x08: /* MIDI Tuning Standard */
|
|
switch (val[3]) {
|
|
case 0x0a:
|
|
SETMIDIEVENT(*ev, 0, ME_TEMPER_KEYSIG, 0,
|
|
val[4] - 0x40 + val[5] * 16, (val[0] == 0x7f));
|
|
return 1;
|
|
}
|
|
break;
|
|
case 0x09: /* General MIDI Message */
|
|
/* GM System Enable/Disable */
|
|
if (val[3] == 1) {
|
|
printMessage(CMSG_INFO, VERB_DEBUG, "SysEx: GM System On");
|
|
SETMIDIEVENT(*ev, 0, ME_RESET, 0, GM_SYSTEM_MODE, 0);
|
|
}
|
|
else if (val[3] == 3) {
|
|
printMessage(CMSG_INFO, VERB_DEBUG, "SysEx: GM2 System On");
|
|
SETMIDIEVENT(*ev, 0, ME_RESET, 0, GM2_SYSTEM_MODE, 0);
|
|
}
|
|
else {
|
|
printMessage(CMSG_INFO, VERB_DEBUG, "SysEx: GM System Off");
|
|
SETMIDIEVENT(*ev, 0, ME_RESET, 0, DEFAULT_SYSTEM_MODE, 0);
|
|
}
|
|
return 1;
|
|
case 0x7b: /* End of File */
|
|
case 0x7c: /* Handshaking Message: Wait */
|
|
case 0x7d: /* Handshaking Message: Cancel */
|
|
case 0x7e: /* Handshaking Message: NAK */
|
|
case 0x7f: /* Handshaking Message: ACK */
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
} |