232
202
MidiTrack* mt = dynamic_cast<MidiTrack*>(*it);
233
203
if (mt == 0 || !mt->recordFlag())
235
event->setPort(mt->outPort());
236
event->setChannel(mt->outChannel());
237
205
if ((mt->inPortMask() & (1 << event->port())) && (mt->inChannelMask() & (1 << event->channel()))) {
238
if (data->state == PLAY && song->record()) {
239
if (data->loopPassed) {
207
// Add recorded events to track
209
if (state == PLAY && song->record()) {
240
211
// this is the first event in a new loop
241
212
// - erase all events from previous loop
242
213
mt->events()->clear();
244
MidiEvent* ev = new MidiEvent(*event);
215
MidiEvent* ev = new MidiEvent(event);
216
ev->setPosTick(tick);
218
if (mt->type() == Track::DRUM) {
219
int pitch = drumInmap[ev->dataA()]; //Point to the drummap-value for this in-note
245
223
mt->events()->add(ev);
248
226
// echo event to current track output
249
227
// (if not from synth gui)
251
MidiPort* mport = &midiPorts[event->port()];
252
if (!isSynth && mt->midiThruFlag() && !filterEvent(event, midiThruType, true)) {
229
MidiPort* mport = &midiPorts[mt->outPort()];
230
if (!fromSynthGui && mt->midiThruFlag() && !filterEvent(event, midiThruType, true)) {
231
// event->setPort(mt->outPort());
232
event->setChannel(mt->outChannel());
253
233
if (event->isNote() || event->isNoteOff()) {
255
int pitch = e.pitch() + mt->transposition;
234
MidiPlayEvent e(*event);
236
if (mt->type() == Track::DRUM) {
237
int instr = drumInmap[e.dataA()];
238
pitch = drumMap[instr].anote; //Map to output note for this key, since this is goes straight out to the midi port
239
e.setChannel(drumMap[instr].channel);
240
mport = &midiPorts[drumMap[instr].port];
241
//printf("Drum-track, event pitch: %d chan: %d port: %d\n",pitch, drumMap[instr].channel, drumMap[instr].port);
244
pitch = e.dataA() + mt->transposition;
263
253
// apply track values
265
255
if (!e.isNoteOff()) {
266
int velo = e.velo() + mt->velocity;
256
int velo = e.dataB() + mt->velocity;
267
257
velo = (velo * mt->compression) / 100;
274
264
mport->putEvent(&e);
277
267
mport->putEvent(event);
281
data->loopPassed = false;
284
//---------------------------------------------------------
286
// Midi Machine Control Input received
287
//---------------------------------------------------------
289
void MidiThread::mmcInput(const unsigned char* /*p*/, int /*n*/)
292
if (!extSyncFlag.value())
294
// printf("mmcInput: %x -- %02x %d %02x %02x %02x\n",
295
// this, n, p[2], p[3], p[4]);
299
printf("MMC: STOP\n");
300
if (_state == SSTATE_PLAY || _state == SSTATE_START_PLAY)
301
_state = SSTATE_STOP;
304
printf("MMC: PLAY\n");
307
printf("MMC: DEFERRED PLAY\n");
314
case 4: printf("FF\n"); break;
315
case 5: printf("REWIND\n"); break;
316
case 6: printf("REC STROBE\n"); break;
317
case 7: printf("REC EXIT\n"); break;
318
case 0xd: printf("RESET\n"); break;
321
printf("LOCATE IF\n");
324
else if (p[5] == 1) {
325
MTC mtc(p[6] & 0x1f, p[7], p[8], p[9], p[10]);
326
mmcPos = tempomap.time2tick(mtc.time());
328
printf("MMC: seek ");
332
write(data->sigFd, "G", 1);
337
printf("MMC %x %x\n", p[3], p[4]); break;
342
//---------------------------------------------------------
344
// process Quarter Frame Message
345
//---------------------------------------------------------
347
void MidiThread::mtcInputQuarter(int, unsigned char c)
349
static int hour, min, sec, frame;
351
if (!extSyncFlag.value())
355
int valH = valL << 4;
357
int _state = (c & 0x70) >> 4;
358
if (mtcState != _state)
359
mtcLost += _state - mtcState;
360
mtcState = _state + 1;
364
hour = (hour & 0x0f) | valH;
367
hour = (hour & 0xf0) | valL;
370
min = (min & 0x0f) | valH;
373
min = (min & 0xf0) | valL;
376
sec = (sec & 0x0f) | valH;
379
sec = (sec & 0xf0) | valL;
382
frame = (frame & 0x0f) | valH;
384
case 0: frame = (frame & 0xf0) | valL;
387
frame &= 0x1f; // 0-29
393
mtcValid = (mtcLost == 0);
397
mtcCurTime.set(hour, min, sec, frame);
398
mtcSyncMsg(mtcCurTime, !mtcSync);
402
else if (mtcValid && (mtcLost == 0)) {
403
mtcCurTime.incQuarter();
404
mtcSyncMsg(mtcCurTime, false);
408
//---------------------------------------------------------
410
// process Frame Message
411
//---------------------------------------------------------
413
void MidiThread::mtcInputFull(const unsigned char* p, int n)
415
if (!extSyncFlag.value())
419
if (p[3] != 2) { // silently ignore user bits
420
printf("unknown mtc msg subtype 0x%02x\n", p[3]);
430
frame &= 0x1f; // 0-29
433
// int type = (hour >> 5) & 3;
436
mtcCurTime.set(hour, min, sec, frame);
441
// printf("MTC Full ");
442
// mtcCurTime.print();
446
//---------------------------------------------------------
447
// nonRealtimeSystemSysex
448
//---------------------------------------------------------
450
void MidiThread::nonRealtimeSystemSysex(const unsigned char* p, int/* n*/)
455
printf("NRT Setup\n");
458
// printf("unknown NRT Msg 0x%02x\n", p[3]);
464
//---------------------------------------------------------
466
// process received mtc Sync
467
//---------------------------------------------------------
469
void MidiThread::mtcSyncMsg(const MTC& /*mtc*/, bool /*seekFlag*/)
472
double time = mtc.time();
473
if (seekFlag && data->state == IDLE) {
474
int tick = tempomap.time2tick(mtc.time());
477
write(data->sigFd, "1", 1);
480
double curT = curTime();
483
double cposTime = tempomap.tick2time(curTickPos, &newTempoSN);
484
if (tempoSN != newTempoSN) {
485
tempoSN = newTempoSN;
486
startTime = curT - cposTime;
490
// diff is the time in sec MusE is out of sync
492
double diff = time - (curT - startTime);
494
printf("%d %f\n", mtcState, diff);
498
//---------------------------------------------------------
500
// MidiBeat is a 14 Bit value. Each MidiBeat spans
501
// 6 MIDI Clocks. Inother words, each MIDI Beat is a
502
// 16th note (since there are 24 MIDI Clocks in a
504
//---------------------------------------------------------
506
void MidiThread::setSongPosition(int port, int midiBeat)
509
printf("set song position port:%d %d\n", port, midiBeat);
510
if (!extSyncFlag.value())
512
data->playTickPos = data->midiClick = (division * midiBeat) / 4;
513
write(data->sigFd, "G", 1);
516
//---------------------------------------------------------
517
// realtimeSystemInput
518
// real time message received
519
//---------------------------------------------------------
521
void MidiThread::realtimeSystemInput(int port, int c)
523
data->realtimeSystemInput(port, c);
526
void MidiThreadPrivate::realtimeSystemInput(int port, int c)
529
printf("realtimeSystemInput port:%d 0x%x\n", port+1, c);
531
if (midiInputTrace && (extSyncPort != port)) {
532
// printf("extSyncPort %d != received sync port %d\n",
533
// extSyncPort, port);
536
if (!extSyncFlag.value())
539
case 0xf8: // midi clock (24 ticks / quarter note)
541
double mclock0 = curTime();
544
recTick += division / 24;
545
int diff = recTick - midiTick;
546
int tempo = tempomap.tempo(0);
548
tempomap.setTempo(0, tempo);
549
midiTick = recTick; // brutal
552
double tdiff0 = mclock0 - mclock1;
553
double tdiff1 = mclock1 - mclock2;
555
midiPorts[port].device()->discardInput();
556
if ((mclock2 != 0.0) && (tdiff0 > 0.0)) {
557
int tempo0 = int(24000000.0 * tdiff0 + .5);
558
int tempo1 = int(24000000.0 * tdiff1 + .5);
559
int tempo = tempomap.tempo(0);
561
int diff0 = tempo0 - tempo;
562
int diff1 = tempo1 - tempo0;
564
int newTempo = tempo + diff0/8 + diff1/16;
565
// printf("new tempo %d -> %d (%d + %d + %d)\n",
567
// tempo, diff0/4, diff1/8);
568
tempomap.setTempo(0, newTempo);
575
case 0xf9: // midi tick (every 10 msec)
577
song->setPos(0, mcStartTick);
589
case 0xfb: // continue
590
printf("continue\n");
600
case 0xfd: // unknown
601
case 0xfe: // active sensing
602
case 0xff: // system reset