33
34
extern void dump(const unsigned char* p, int n);
35
const unsigned char gmOnMsg[] = { 0x7e, 0x7f, 0x09, 0x01 };
36
const unsigned char gsOnMsg[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41 };
37
const unsigned char xgOnMsg[] = { 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00 };
38
const unsigned int gmOnMsgLen = sizeof(gmOnMsg);
39
const unsigned int gsOnMsgLen = sizeof(gsOnMsg);
40
const unsigned int xgOnMsgLen = sizeof(xgOnMsg);
36
const unsigned char gmOnMsg[] = { 0x7e, 0x7f, 0x09, 0x01 };
37
const unsigned char gsOnMsg[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41 };
38
const unsigned char gsOnMsg2[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x33, 0x50, 0x3c };
39
const unsigned char gsOnMsg3[] = { 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x34, 0x50, 0x3b };
40
const unsigned char xgOnMsg[] = { 0x43, 0x10, 0x4c, 0x00, 0x00, 0x7e, 0x00 };
41
const unsigned int gmOnMsgLen = sizeof(gmOnMsg);
42
const unsigned int gsOnMsgLen = sizeof(gsOnMsg);
43
const unsigned int gsOnMsg2Len = sizeof(gsOnMsg2);
44
const unsigned int gsOnMsg3Len = sizeof(gsOnMsg3);
45
const unsigned int xgOnMsgLen = sizeof(xgOnMsg);
47
const unsigned char mmcDeferredPlayMsg[] = { 0x7f, 0x7f, 0x06, 0x03 };
48
const unsigned char mmcStopMsg[] = { 0x7f, 0x7f, 0x06, 0x01 };
49
const unsigned char mmcLocateMsg[] = { 0x7f, 0x7f, 0x06, 0x44, 0x06, 0x01, 0, 0, 0, 0, 0 };
51
const unsigned int mmcDeferredPlayMsgLen = sizeof(mmcDeferredPlayMsg);
52
const unsigned int mmcStopMsgLen = sizeof(mmcStopMsg);
53
const unsigned int mmcLocateMsgLen = sizeof(mmcLocateMsg);
42
55
#define CALC_TICK(the_tick) lrintf((float(the_tick) * float(config.division) + float(div/2)) / float(div));
43
56
/*---------------------------------------------------------
941
1005
if (track->recordFlag())
943
1007
//int portMask = track->inPortMask();
944
unsigned int portMask = track->inPortMask();
945
int channelMask = track->inChannelMask();
1009
//unsigned int portMask = track->inPortMask();
1010
//int channelMask = track->inChannelMask();
946
1012
MPEventList* rl = track->mpevents();
947
1013
MidiPort* tport = &midiPorts[port];
949
for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
1016
//for (iMidiDevice id = midiDevices.begin(); id != midiDevices.end(); ++id)
1018
RouteList* irl = track->inRoutes();
1019
for(ciRoute r = irl->begin(); r != irl->end(); ++r)
951
MidiDevice* dev = *id;
953
int devport = dev->midiPort();
1021
//if(!r->isValid() || (r->type != Route::ALSA_MIDI_ROUTE && r->type != Route::JACK_MIDI_ROUTE))
1022
//if(!r->isValid() || (r->type != Route::MIDI_DEVICE_ROUTE))
1023
if(!r->isValid() || (r->type != Route::MIDI_PORT_ROUTE)) // p3.3.49
1026
int devport = r->midiPort; // p3.3.49
1030
//MidiDevice* dev = *id;
1031
//MidiDevice* dev = r->device;
1032
MidiDevice* dev = midiPorts[devport].device(); // p3.3.49
1038
//int channel = r->channel;
1039
// NOTE: TODO: Special for input device sysex 'channel' marked as -1, ** IF we end up going with that method **.
1040
// This would mean having a separate 'System' channel listed in the routing popups.
1041
// The other alternative is to accept sysex from a device as long as ANY regular channel is routed from it,
1042
// this does not require a 'System' channel listed in the routing popups.
1043
// But that requires more code below... Done.
1045
//channel = MIDI_CHANNELS; // Special channel '17'
1048
//int devport = dev->midiPort();
955
1050
// record only from ports marked in portMask:
956
if (devport == -1 || !(portMask & (1 << devport)))
1051
//if (devport == -1 || !(portMask & (1 << devport)))
1052
//if (devport == -1)
959
MREventList* el = dev->recordEvents();
960
for (iMREvent ie = el->begin(); ie != el->end(); ++ie)
1055
//MREventList* el = dev->recordEvents();
1056
//MidiFifo& rf = dev->recordEvents();
1059
int channelMask = r->channel; // p3.3.50
1060
if(channelMask == -1 || channelMask == 0)
1062
for(int channel = 0; channel < MIDI_CHANNELS; ++channel) // p3.3.50
962
int channel = ie->channel();
963
int defaultPort = devport;
964
if (!(channelMask & (1 << channel)))
969
MidiPlayEvent event(*ie);
970
int drumRecPitch=0; //prevent compiler warning: variable used without initialization
971
MidiController *mc = 0;
975
// TODO: Clean up a bit around here when it comes to separate events for rec & for playback.
976
// But not before 0.7 (ml)
978
int prePitch = 0, preVelo = 0;
980
event.setChannel(track->outChannel());
982
if (event.isNote() || event.isNoteOff())
985
// apply track values
989
if (track->type() == Track::DRUM)
991
int pitch = event.dataA();
992
//Map note that is played according to drumInmap
993
drumRecPitch = drumMap[(unsigned int)drumInmap[pitch]].enote;
994
devport = drumMap[(unsigned int)drumInmap[pitch]].port;
995
event.setPort(devport);
996
channel = drumMap[(unsigned int)drumInmap[pitch]].channel;
997
event.setA(drumMap[(unsigned int)drumInmap[pitch]].anote);
998
event.setChannel(channel);
1001
{ //Track transpose if non-drum
1002
prePitch = event.dataA();
1003
int pitch = prePitch + track->transposition;
1011
if (!event.isNoteOff())
1013
preVelo = event.dataB();
1014
int velo = preVelo + track->velocity;
1015
velo = (velo * track->compression) / 100;
1025
if(event.type() == ME_CONTROLLER)
1027
if(track->type() == Track::DRUM)
1029
ctl = event.dataA();
1030
// Regardless of what port the event came from, is it a drum controller event
1031
// according to the track port's instrument?
1032
mc = tport->drumController(ctl);
1035
int pitch = ctl & 0x7f;
1037
int dmindex = drumInmap[pitch] & 0x7f;
1038
//Map note that is played according to drumInmap
1039
drumRecPitch = drumMap[dmindex].enote;
1040
devport = drumMap[dmindex].port;
1041
event.setPort(devport);
1042
channel = drumMap[dmindex].channel;
1043
event.setA(ctl | drumMap[dmindex].anote);
1044
event.setChannel(channel);
1049
unsigned time = event.time() + segmentSize*(segmentCount-1);
1050
event.setTime(time);
1064
if(!(channelMask & (1 << channel)))
1067
if(!dev->sysexFIFOProcessed())
1069
// Set to the sysex fifo at first.
1070
MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
1071
// Get the frozen snapshot of the size.
1072
int count = dev->tmpRecordCount(MIDI_CHANNELS);
1074
for(int i = 0; i < count; ++i)
1076
MidiPlayEvent event(rf.peek(i));
1078
//unsigned time = event.time() + segmentSize*(segmentCount-1);
1079
//unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
1080
//unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
1081
//event.setTime(time);
1083
// event.setTime(event.time() + segmentSize*(segmentCount-1));
1085
event.setPort(port);
1052
1087
// dont't echo controller changes back to software
1053
1088
// synthesizer:
1055
if (!dev->isSynti())
1057
// Added by Tim. p3.3.8
1058
if(track->recEcho())
1061
//Check if we're outputting to another port than default:
1062
if (devport == defaultPort) {
1063
event.setPort(port);
1065
playEvents->add(event);
1068
// Hmm, this appears to work, but... Will this induce trouble with md->setNextPlayEvent??
1069
MidiDevice* mdAlt = midiPorts[devport].device();
1071
mdAlt->playEvents()->add(event);
1074
// Shall we activate meters even while rec echo is off? Sure, why not...
1075
if(event.isNote() && event.dataB() > track->activity())
1076
track->setActivity(event.dataB());
1089
if(!dev->isSynti() && md && track->recEcho())
1090
playEvents->add(event);
1079
time = tempomap.frame2tick(event.time());
1080
event.setTime(time); // set tick time
1082
// Special handling of events stored in rec-lists. a bit hACKish. TODO: Clean up (after 0.7)! :-/ (ml)
1092
// If syncing externally the event time is already in units of ticks, set above.
1085
// In these next steps, it is essential to set the recorded event's port
1086
// to the track port so buildMidiEventList will accept it. Even though
1087
// the port may have no device "<none>".
1089
if (track->type() == Track::DRUM)
1095
//time = tempomap.frame2tick(event.time());
1096
//event.setTime(time); // set tick time
1097
event.setTime(tempomap.frame2tick(event.time())); // set tick time
1104
dev->setSysexFIFOProcessed(true);
1107
// Set to the sysex fifo at first.
1108
///MidiFifo& rf = dev->recordEvents(MIDI_CHANNELS);
1109
// Get the frozen snapshot of the size.
1110
///int count = dev->tmpRecordCount(MIDI_CHANNELS);
1112
// Iterate once for sysex fifo (if needed), once for channel fifos.
1113
///for(int sei = 0; sei < 2; ++sei)
1115
// If on first pass, do sysex fifo.
1119
// Ignore any further channel routes on this device if already done here.
1120
if(dev->sysexFIFOProcessed())
1122
// Go ahead and set this now.
1123
dev->setSysexFIFOProcessed(true);
1124
// Allow it to fall through with the sysex fifo and count...
1128
// We're on the second pass, do channel fifos.
1129
rf = dev->recordEvents(channel);
1130
// Get the frozen snapshot of the size.
1131
count = dev->tmpRecordCount(channel);
1135
MidiFifo& rf = dev->recordEvents(channel);
1136
int count = dev->tmpRecordCount(channel);
1138
//for (iMREvent ie = el->begin(); ie != el->end(); ++ie)
1139
for(int i = 0; i < count; ++i)
1141
MidiPlayEvent event(rf.peek(i));
1143
//int channel = ie->channel();
1144
///int channel = event.channel();
1146
int defaultPort = devport;
1147
///if (!(channelMask & (1 << channel)))
1152
//MidiPlayEvent event(*ie);
1153
int drumRecPitch=0; //prevent compiler warning: variable used without initialization
1154
MidiController *mc = 0;
1158
// TODO: Clean up a bit around here when it comes to separate events for rec & for playback.
1159
// But not before 0.7 (ml)
1161
int prePitch = 0, preVelo = 0;
1163
event.setChannel(track->outChannel());
1165
if (event.isNote() || event.isNoteOff())
1168
// apply track values
1172
if (track->type() == Track::DRUM)
1174
int pitch = event.dataA();
1175
//Map note that is played according to drumInmap
1176
drumRecPitch = drumMap[(unsigned int)drumInmap[pitch]].enote;
1177
devport = drumMap[(unsigned int)drumInmap[pitch]].port;
1178
event.setPort(devport);
1179
channel = drumMap[(unsigned int)drumInmap[pitch]].channel;
1180
event.setA(drumMap[(unsigned int)drumInmap[pitch]].anote);
1181
event.setChannel(channel);
1184
{ //Track transpose if non-drum
1185
prePitch = event.dataA();
1186
int pitch = prePitch + track->transposition;
1194
if (!event.isNoteOff())
1196
preVelo = event.dataB();
1197
int velo = preVelo + track->velocity;
1198
velo = (velo * track->compression) / 100;
1208
if(event.type() == ME_CONTROLLER)
1210
if(track->type() == Track::DRUM)
1091
// Is it a drum controller event?
1212
ctl = event.dataA();
1213
// Regardless of what port the event came from, is it a drum controller event
1214
// according to the track port's instrument?
1215
mc = tport->drumController(ctl);
1094
MidiPlayEvent drumRecEvent = event;
1095
drumRecEvent.setA(ctl | drumRecPitch);
1096
// In this case, preVelo is simply the controller value.
1097
drumRecEvent.setB(preVelo);
1098
drumRecEvent.setPort(port); //rec-event to current port
1099
drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1100
rl->add(drumRecEvent);
1105
MidiPlayEvent drumRecEvent = event;
1106
drumRecEvent.setA(drumRecPitch);
1107
drumRecEvent.setB(preVelo);
1109
// Tested: Events were not being recorded for a drum map entry pointing to a
1110
// different port. This must have been wrong - buildMidiEventList would ignore this.
1111
//drumRecEvent.setPort(devport);
1112
drumRecEvent.setPort(port); //rec-event to current port
1218
int pitch = ctl & 0x7f;
1220
int dmindex = drumInmap[pitch] & 0x7f;
1221
//Map note that is played according to drumInmap
1222
drumRecPitch = drumMap[dmindex].enote;
1223
devport = drumMap[dmindex].port;
1224
event.setPort(devport);
1225
channel = drumMap[dmindex].channel;
1226
event.setA(ctl | drumMap[dmindex].anote);
1227
event.setChannel(channel);
1233
// MusE uses a fixed clocks per quarternote of 24.
1234
// At standard 384 ticks per quarternote for example,
1235
// 384/24=16 for a division of 16 sub-frames (16 MusE 'ticks').
1236
// That is what we'll use if syncing externally.
1237
//unsigned time = event.time() + segmentSize*(segmentCount-1);
1238
//unsigned time = event.time() + (extsync ? config.division/24 : segmentSize*(segmentCount-1));
1240
// Oops, use the current tick.
1241
//unsigned time = extsync ? curTickPos : (event.time() + segmentSize*(segmentCount-1));
1242
//event.setTime(time);
1244
// If ext sync, events are now time-stamped with last tick in MidiDevice::recordEvent().
1245
// TODO: Tested, but record resolution not so good. Switch to wall clock based separate list in MidiDevice.
1248
// event.setTime(event.time() + segmentSize*(segmentCount-1));
1250
// dont't echo controller changes back to software
1253
if (!dev->isSynti())
1255
//Check if we're outputting to another port than default:
1256
if (devport == defaultPort) {
1257
event.setPort(port);
1258
if(md && track->recEcho())
1259
playEvents->add(event);
1262
// Hmm, this appears to work, but... Will this induce trouble with md->setNextPlayEvent??
1263
MidiDevice* mdAlt = midiPorts[devport].device();
1264
if(mdAlt && track->recEcho())
1265
mdAlt->playEvents()->add(event);
1267
// Shall we activate meters even while rec echo is off? Sure, why not...
1268
if(event.isNote() && event.dataB() > track->activity())
1269
track->setActivity(event.dataB());
1273
// If syncing externally the event time is already in units of ticks, set above.
1277
//time = tempomap.frame2tick(event.time());
1278
//event.setTime(time); // set tick time
1279
event.setTime(tempomap.frame2tick(event.time())); // set tick time
1282
// Special handling of events stored in rec-lists. a bit hACKish. TODO: Clean up (after 0.7)! :-/ (ml)
1285
// In these next steps, it is essential to set the recorded event's port
1286
// to the track port so buildMidiEventList will accept it. Even though
1287
// the port may have no device "<none>".
1289
if (track->type() == Track::DRUM)
1291
// Is it a drum controller event?
1294
MidiPlayEvent drumRecEvent = event;
1295
drumRecEvent.setA(ctl | drumRecPitch);
1296
// In this case, preVelo is simply the controller value.
1297
drumRecEvent.setB(preVelo);
1298
drumRecEvent.setPort(port); //rec-event to current port
1299
drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1300
rl->add(drumRecEvent);
1114
drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1115
rl->add(drumRecEvent);
1120
// Restore record-pitch to non-transposed value since we don't want the note transposed twice next
1121
MidiPlayEvent recEvent = event;
1123
recEvent.setA(prePitch);
1125
recEvent.setB(preVelo);
1126
recEvent.setPort(port);
1127
recEvent.setChannel(track->outChannel());
1305
MidiPlayEvent drumRecEvent = event;
1306
drumRecEvent.setA(drumRecPitch);
1307
drumRecEvent.setB(preVelo);
1309
// Tested: Events were not being recorded for a drum map entry pointing to a
1310
// different port. This must have been wrong - buildMidiEventList would ignore this.
1311
//drumRecEvent.setPort(devport);
1312
drumRecEvent.setPort(port); //rec-event to current port
1314
drumRecEvent.setChannel(track->outChannel()); //rec-event to current channel
1315
rl->add(drumRecEvent);
1320
// Restore record-pitch to non-transposed value since we don't want the note transposed twice next
1321
MidiPlayEvent recEvent = event;
1323
recEvent.setA(prePitch);
1325
recEvent.setB(preVelo);
1326
recEvent.setPort(port);
1327
recEvent.setChannel(track->outChannel());