00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "XMidiSequence.h"
00022 #include "XMidiSequenceHandler.h"
00023 #include "XMidiFile.h"
00024
00025
00026
00027
00028
00029
00030 #define XMIDISEQUENCER_NO_CATCHUP_WAIT_OVER 1200
00031
00032 const uint16 XMidiSequence::ChannelShadow::centre_value = 0x2000;
00033 const uint8 XMidiSequence::ChannelShadow::fine_value = centre_value & 127;
00034 const uint8 XMidiSequence::ChannelShadow::coarse_value = centre_value >> 7;
00035 const uint16 XMidiSequence::ChannelShadow::combined_value = (coarse_value << 8) | fine_value;
00036
00037 XMidiSequence::XMidiSequence(XMidiSequenceHandler *Handler, uint16 seq_id, XMidiEventList *events,
00038 bool Repeat, int volume, int branch) :
00039 handler(Handler), sequence_id(seq_id), evntlist(events), event(0),
00040 repeat(Repeat), notes_on(), last_tick(0), loop_num(-1), vol_multi(volume),
00041 paused(false), speed(100)
00042 {
00043 std::memset(loop_event,0,XMIDI_MAX_FOR_LOOP_COUNT*sizeof(int));
00044 std::memset(loop_count,0,XMIDI_MAX_FOR_LOOP_COUNT*sizeof(int));
00045 event = evntlist->events;
00046
00047 for (int i = 0; i < 16; i++)
00048 {
00049 shadows[i].reset();
00050 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (XMIDI_CONTROLLER_BANK_CHANGE << 8));
00051 }
00052
00053
00054 XMidiEvent *brnch = events->findBranchEvent(branch);
00055 if (brnch)
00056 {
00057 last_tick = brnch->time;
00058 event = brnch;
00059
00060 XMidiEvent *event = evntlist->events;
00061 while (event != brnch)
00062 {
00063 updateShadowForEvent(event);
00064 event=event->next;
00065 }
00066 for (int i = 0; i < 16; i++) gainChannel(i);
00067 }
00068
00069 initClock();
00070 }
00071
00072 XMidiSequence::~XMidiSequence()
00073 {
00074
00075 while (XMidiEvent *note = notes_on.Pop())
00076 handler->sequenceSendEvent(sequence_id, note->status + (note->data[0] << 8));
00077
00078 for (int i = 0; i < 16; i++)
00079 {
00080 shadows[i].reset();
00081 applyShadow(i);
00082 }
00083
00084
00085 evntlist->decerementCounter();
00086 }
00087
00088 void XMidiSequence::ChannelShadow::reset()
00089 {
00090 pitchWheel = combined_value;
00091
00092 program = -1;
00093
00094
00095 bank[0] = 0;
00096 bank[1] = 0;
00097
00098
00099 modWheel[0] = coarse_value;
00100 modWheel[1] = fine_value;
00101
00102
00103 footpedal[0] = 0;
00104 footpedal[1] = 0;
00105
00106
00107 volumes[0] = coarse_value;
00108 volumes[1] = fine_value;
00109
00110
00111 pan[0] = coarse_value;
00112 pan[1] = fine_value;
00113
00114
00115 balance[0] = coarse_value;
00116 balance[1] = fine_value;
00117
00118
00119 expression[0] = 127;
00120 expression[1] = 0;
00121
00122
00123 sustain = 0;
00124
00125
00126 effects = 0;
00127
00128
00129 chorus = 0;
00130
00131
00132 xbank = 0;
00133 }
00134
00135 int XMidiSequence::playEvent()
00136 {
00137 XMidiEvent *note;
00138
00139
00140 while ((note = notes_on.PopTime(getRealTime())) != 0)
00141 handler->sequenceSendEvent(sequence_id, note->status + (note->data[0] << 8));
00142
00143
00144 if (!event)
00145 {
00146 if (notes_on.GetNotes()) return 1;
00147 else return -1;
00148 }
00149
00150
00151 if (speed <= 0 || paused) return 1;
00152
00153
00154 sint32 aim = ((event->time-last_tick)*5000)/speed;
00155 sint32 diff = aim - getTime ();
00156
00157 if (diff > 5) return 1;
00158
00159 addOffset(aim);
00160
00161 last_tick = event->time;
00162
00163 #ifdef XMIDISEQUENCER_NO_CATCHUP_WAIT_OVER
00164 if (diff < -XMIDISEQUENCER_NO_CATCHUP_WAIT_OVER) addOffset(-diff);
00165 #endif
00166
00167
00168 while ((note = notes_on.PopTime(getRealTime())) != 0)
00169 handler->sequenceSendEvent(sequence_id, note->status + (note->data[0] << 8));
00170
00171
00172 if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_FOR_LOOP)
00173 {
00174 if (loop_num < XMIDI_MAX_FOR_LOOP_COUNT) loop_num++;
00175
00176 loop_count[loop_num] = event->data[1];
00177 loop_event[loop_num] = event;
00178
00179 }
00180 else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_NEXT_BREAK)
00181 {
00182 if (loop_num != -1)
00183 {
00184 if (event->data[1] < 64)
00185 {
00186 loop_num--;
00187 }
00188 }
00189 else
00190 {
00191
00192
00193 XMidiEvent *branch = evntlist->findBranchEvent(126);
00194
00195 if (branch)
00196 {
00197 loop_num = 0;
00198 loop_count[loop_num] = 1;
00199 loop_event[loop_num] = branch;
00200 }
00201 }
00202 event = NULL;
00203 }
00204 else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_CALLBACK_TRIG)
00205 {
00206 handler->handleCallbackTrigger(sequence_id, event->data[1]);
00207 }
00208 else if (event->status < 0xF0)
00209 {
00210 sendEvent();
00211 }
00212
00213 else if (event->status != 0xFF)
00214 {
00215 handler->sequenceSendSysEx(sequence_id, event->status,
00216 event->ex.sysex_data.buffer, event->ex.sysex_data.len);
00217 }
00218
00219
00220 if (event) event = event->next;
00221
00222
00223 if (!event)
00224 {
00225
00226 if (loop_num != -1)
00227 {
00228 event = loop_event[loop_num]->next;
00229 last_tick = loop_event[loop_num]->time;
00230
00231 if (loop_count[loop_num])
00232 if (!--loop_count[loop_num])
00233 loop_num--;
00234 }
00235
00236
00237 else if (repeat)
00238 {
00239 event = evntlist->events;
00240 if (last_tick == 0) return 1;
00241 last_tick = 0;
00242 }
00243
00244 else
00245 {
00246 if (notes_on.GetNotes()) return 1;
00247 return -1;
00248 }
00249 }
00250
00251 if (!event)
00252 {
00253 if (notes_on.GetNotes()) return 1;
00254 else return -1;
00255 }
00256
00257 aim = ((event->time-last_tick)*5000)/speed;
00258 diff = aim - getTime ();
00259
00260 if (diff < 0) return 0;
00261 return 1;
00262 }
00263
00264 sint32 XMidiSequence::timeTillNext()
00265 {
00266 sint32 sixthoToNext = 0x7FFFFFFF;
00267
00268
00269 XMidiEvent *note;
00270 if (note = notes_on.GetNotes()) {
00271 sint32 diff = note->ex.note_on.note_time - getRealTime();
00272 if (diff < sixthoToNext) sixthoToNext = diff;
00273 }
00274
00275
00276 if (speed > 0 && event && !paused)
00277 {
00278 sint32 aim = ((event->time-last_tick)*5000)/speed;
00279 sint32 diff = aim - getTime ();
00280
00281 if (diff < sixthoToNext) sixthoToNext = diff;
00282 }
00283 return sixthoToNext/6;
00284 }
00285
00286 void XMidiSequence::updateShadowForEvent(XMidiEvent *event)
00287 {
00288 unsigned int chan = event->status & 0xF;
00289 unsigned int type = event->status >> 4;
00290 uint32 data = event->data[0] | (event->data[1] << 8);
00291
00292
00293
00294
00295
00296
00297 if (type == MIDI_STATUS_CONTROLLER) {
00298
00299 if (event->data[0] == 7) {
00300 shadows[chan].volumes[0] = event->data[1];
00301 }
00302 else if (event->data[0] == 39) {
00303 shadows[chan].volumes[1] = event->data[1];
00304 }
00305
00306 else if (event->data[0] == 0 || event->data[0] == 32) {
00307 shadows[chan].bank[event->data[0]/32] = event->data[1];
00308 }
00309
00310 else if (event->data[0] == 1 || event->data[0] == 33) {
00311 shadows[chan].modWheel[event->data[0]/32] = event->data[1];
00312 }
00313
00314 else if (event->data[0] == 4 || event->data[0] == 36) {
00315 shadows[chan].footpedal[event->data[0]/32] = event->data[1];
00316 }
00317
00318 else if (event->data[0] == 9 || event->data[0] == 41) {
00319 shadows[chan].pan[event->data[0]/32] = event->data[1];
00320 }
00321
00322 else if (event->data[0] == 10 || event->data[0] == 42) {
00323 shadows[chan].balance[event->data[0]/32] = event->data[1];
00324 }
00325
00326 else if (event->data[0] == 11 || event->data[0] == 43) {
00327 shadows[chan].expression[event->data[0]/32] = event->data[1];
00328 }
00329
00330 else if (event->data[0] == 64) {
00331 shadows[chan].effects = event->data[1];
00332 }
00333
00334 else if (event->data[0] == 91) {
00335 shadows[chan].effects = event->data[1];
00336 }
00337
00338 else if (event->data[0] == 93) {
00339 shadows[chan].chorus = event->data[1];
00340 }
00341
00342 else if (event->data[0] == XMIDI_CONTROLLER_BANK_CHANGE) {
00343 shadows[chan].xbank = event->data[1];
00344 }
00345 }
00346 else if (type == MIDI_STATUS_PROG_CHANGE)
00347 {
00348 shadows[chan].program = data;
00349 }
00350 else if (type == MIDI_STATUS_PITCH_WHEEL)
00351 {
00352 shadows[chan].pitchWheel = data;
00353 }
00354 }
00355
00356 void XMidiSequence::sendEvent()
00357 {
00358 unsigned int chan = event->status & 0xF;
00359 unsigned int type = event->status >> 4;
00360 uint32 data = event->data[0] | (event->data[1] << 8);
00361
00362
00363
00364
00365
00366 updateShadowForEvent(event);
00367
00368 if (type == MIDI_STATUS_CONTROLLER) {
00369
00370 if (event->data[0] == 7) {
00371 data = event->data[0] | (((event->data[1] * vol_multi)/0xFF)<<8);
00372 }
00373 }
00374 else if (type == MIDI_STATUS_AFTERTOUCH) {
00375 notes_on.SetAftertouch(event);
00376 }
00377
00378 if ((type != MIDI_STATUS_NOTE_ON || event->data[1]) && type != MIDI_STATUS_NOTE_OFF) {
00379
00380 if (type == MIDI_STATUS_NOTE_ON) {
00381
00382 if (!event->data[1]) return;
00383
00384 notes_on.Remove(event);
00385
00386 handler->sequenceSendEvent(sequence_id, event->status | (data<<8));
00387 event->ex.note_on.actualvel = event->data[1];
00388
00389 notes_on.Push (event, ((event->ex.note_on.duration-1)*5000/speed) + getStart());
00390 }
00391
00392 else
00393 handler->sequenceSendEvent(sequence_id, event->status | (data<<8));
00394 }
00395 }
00396
00397 #define SendController(ctrl,name) \
00398 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (ctrl << 8) | (shadows[i].name[0] << 16)); \
00399 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | ((ctrl+32) << 8) | (shadows[i].name[1] << 16));
00400
00401 void XMidiSequence::applyShadow(int i)
00402 {
00403
00404 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_PITCH_WHEEL << 4) | (shadows[i].pitchWheel << 8));
00405
00406
00407 SendController(1,modWheel);
00408
00409
00410 SendController(4,footpedal);
00411
00412
00413 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (7 << 8) | (((shadows[i].volumes[0]*vol_multi)/0xFF) << 16));
00414 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (39 << 8) | (shadows[i].volumes[1] << 16));
00415
00416
00417 SendController(9,pan);
00418
00419
00420 SendController(10,balance);
00421
00422
00423 SendController(11,expression);
00424
00425
00426 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (64 << 8) | (shadows[i].sustain << 16));
00427
00428
00429 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (91 << 8) | (shadows[i].effects << 16));
00430
00431
00432 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (93 << 8) | (shadows[i].chorus << 16));
00433
00434
00435 handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_CONTROLLER << 4) | (XMIDI_CONTROLLER_BANK_CHANGE << 8) | (shadows[i].xbank << 16));
00436
00437
00438 if (shadows[i].program != -1) handler->sequenceSendEvent(sequence_id, i | (MIDI_STATUS_PROG_CHANGE << 4) | (shadows[i].program << 8));
00439 SendController(0,bank);
00440 }
00441
00442 void XMidiSequence::setVolume(int new_volume)
00443 {
00444 vol_multi = new_volume;
00445 new_volume = -1;
00446
00447
00448 for (int i = 0; i < 16; i++) if (evntlist->chan_mask & (1 << i)) {
00449 uint32 message = i;
00450 message |= MIDI_STATUS_CONTROLLER << 4;
00451 message |= 7 << 8;
00452 message |= ((shadows[i].volumes[0] * vol_multi)/0xFF)<<16;
00453 handler->sequenceSendEvent(sequence_id, message);
00454 }
00455 }
00456
00457 void XMidiSequence::loseChannel(int i)
00458 {
00459
00460 XMidiEvent* note = notes_on.GetNotes();
00461 while (note)
00462 {
00463 if ((note->status&0xF) == i)
00464 handler->sequenceSendEvent(sequence_id, note->status + (note->data[0] << 8));
00465 note = note->ex.note_on.next_note;
00466 }
00467
00468 }
00469
00470 void XMidiSequence::gainChannel(int i)
00471 {
00472 applyShadow(i);
00473
00474
00475 XMidiEvent* note = notes_on.GetNotes();
00476 while (note)
00477 {
00478 if ((note->status&0xF) == i)
00479 handler->sequenceSendEvent(sequence_id, note->status | (note->data[0] << 8) | (note->ex.note_on.actualvel << 16));
00480 note = note->ex.note_on.next_note;
00481 }
00482 }
00483
00484 void XMidiSequence::pause()
00485 {
00486 paused = true;
00487 for (int i = 0; i < 16; i++)
00488 if (evntlist->chan_mask & (1 << i))
00489 loseChannel(i);
00490 }
00491
00492 void XMidiSequence::unpause()
00493 {
00494 paused = false;
00495 for (int i = 0; i < 16; i++)
00496 if (evntlist->chan_mask & (1 << i))
00497 applyShadow(i);
00498 }
00499
00500 int XMidiSequence::countNotesOn(int chan)
00501 {
00502 if (paused) return 0;
00503
00504 int ret = 0;
00505 XMidiEvent* note = notes_on.GetNotes();
00506 while (note)
00507 {
00508 if ((note->status&0xF) == chan)
00509 ret++;
00510 note = note->ex.note_on.next_note;
00511 }
00512 return ret;
00513 }
00514
00515