1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2007-2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "midifile.h"
14 #include "libmscore/xml.h"
15 #include "libmscore/part.h"
16 #include "libmscore/note.h"
17 #include "libmscore/drumset.h"
18 #include "libmscore/utils.h"
19
20 namespace Ms {
21
22 static const uchar gmOnMsg[] = {
23 0x7e, // Non-Real Time header
24 0x7f, // ID of target device (7f = all devices)
25 0x09,
26 0x01
27 };
28 static const uchar gsOnMsg[] = {
29 0x41, // roland id
30 0x10, // Id of target device (default = 10h for roland)
31 0x42, // model id (42h = gs devices)
32 0x12, // command id (12h = data set)
33 0x40, // address & value
34 0x00,
35 0x7f,
36 0x00,
37 0x41 // checksum?
38 };
39 static const uchar xgOnMsg[] = {
40 0x43, // yamaha id
41 0x10, // device number (0)
42 0x4c, // model id
43 0x00, // address (high, mid, low)
44 0x00,
45 0x7e,
46 0x00 // data
47 };
48
49 const int gmOnMsgLen = sizeof(gmOnMsg);
50 const int gsOnMsgLen = sizeof(gsOnMsg);
51 const int xgOnMsgLen = sizeof(xgOnMsg);
52
53 //---------------------------------------------------------
54 // MidiFile
55 //---------------------------------------------------------
56
MidiFile()57 MidiFile::MidiFile()
58 {
59 fp = 0;
60 _division = 0;
61 _isDivisionInTps = false;
62 _format = 1;
63 _midiType = MidiType::UNKNOWN;
64 _noRunningStatus = false;
65
66 status = 0;
67 sstatus = 0;
68 click = 0;
69 curPos = 0;
70 }
71
72 //---------------------------------------------------------
73 // write
74 // returns true on error
75 //---------------------------------------------------------
76
write(QIODevice * out)77 bool MidiFile::write(QIODevice* out)
78 {
79 fp = out;
80 write("MThd", 4);
81 writeLong(6); // header len
82 writeShort(_format); // format
83 writeShort(_tracks.size());
84 writeShort(_division);
85 for (const auto &t: qAsConst(_tracks)) {
86 if (writeTrack(t))
87 return true;
88 }
89 return false;
90 }
91
92 //---------------------------------------------------------
93 // write
94 //---------------------------------------------------------
95
writeEvent(const MidiEvent & event)96 void MidiFile::writeEvent(const MidiEvent& event)
97 {
98 switch(event.type()) {
99 case ME_NOTEON:
100 writeStatus(ME_NOTEON, event.channel());
101 put(event.pitch());
102 put(event.velo());
103 break;
104
105 case ME_NOTEOFF:
106 writeStatus(ME_NOTEOFF, event.channel());
107 put(event.pitch());
108 put(event.velo());
109 break;
110
111 case ME_PITCHBEND:
112 writeStatus(ME_PITCHBEND, event.channel());
113 put(event.dataA());
114 put(event.dataB());
115 break;
116
117 case ME_CONTROLLER:
118 switch(event.controller()) {
119 case CTRL_PROGRAM:
120 writeStatus(ME_PROGRAM, event.channel());
121 put(event.value() & 0x7f);
122 break;
123 case CTRL_PRESS:
124 writeStatus(ME_AFTERTOUCH, event.channel());
125 put(event.value() & 0x7f);
126 break;
127 default:
128 writeStatus(ME_CONTROLLER, event.channel());
129 put(event.controller());
130 put(event.value() & 0x7f);
131 break;
132 }
133 break;
134
135 case ME_META:
136 put(ME_META);
137 put(event.metaType());
138 putvl(event.len());
139 write(event.edata(), event.len());
140 resetRunningStatus(); // really ?!
141 break;
142
143 case ME_SYSEX:
144 put(ME_SYSEX);
145 putvl(event.len() + 1); // including 0xf7
146 write(event.edata(), event.len());
147 put(ME_ENDSYSEX);
148 resetRunningStatus();
149 break;
150 }
151 }
152
153 //---------------------------------------------------------
154 // writeTrack
155 //---------------------------------------------------------
156
writeTrack(const MidiTrack & t)157 bool MidiFile::writeTrack(const MidiTrack &t)
158 {
159 write("MTrk", 4);
160 qint64 lenpos = fp->pos();
161 writeLong(0); // dummy len
162
163 status = -1;
164 int tick = 0;
165 for (auto i : t.events()) {
166 int ntick = i.first;
167 putvl(ntick - tick); // write tick delta
168 //
169 // if track channel != -1, then use this
170 // channel for all events in this track
171 //
172 if (t.outChannel() != -1)
173 writeEvent(i.second);
174 tick = ntick;
175 }
176
177 //---------------------------------------------------
178 // write "End Of Track" Meta
179 // write Track Len
180 //
181
182 putvl(1);
183 put(0xff); // Meta
184 put(0x2f); // EOT
185 putvl(0); // len 0
186 qint64 endpos = fp->pos();
187 fp->seek(lenpos);
188 writeLong(endpos-lenpos-4); // tracklen
189 fp->seek(endpos);
190 return false;
191 }
192
193 //---------------------------------------------------------
194 // writeStatus
195 //---------------------------------------------------------
196
writeStatus(int nstat,int c)197 void MidiFile::writeStatus(int nstat, int c)
198 {
199 nstat |= (c & 0xf);
200 //
201 // running status; except for Sysex- and Meta Events
202 //
203 if (_noRunningStatus || (((nstat & 0xf0) != 0xf0) && (nstat != status))) {
204 status = nstat;
205 put(nstat);
206 }
207 }
208
209 //---------------------------------------------------------
210 // readMidi
211 // return false on error
212 //---------------------------------------------------------
213
read(QIODevice * in)214 bool MidiFile::read(QIODevice* in)
215 {
216 fp = in;
217 _tracks.clear();
218 curPos = 0;
219
220 // === Read header_chunk = "MThd" + <header_length> + <format> + <n> + <division>
221 //
222 // "MThd" 4 bytes
223 // the literal string MThd, or in hexadecimal notation: 0x4d546864.
224 // These four characters at the start of the MIDI file
225 // indicate that this is a MIDI file.
226 // <header_length> 4 bytes
227 // length of the header chunk (always =6 bytes long - the size of the next
228 // three fields which are considered the header chunk).
229 // Although the header chunk currently always contains 6 bytes of data,
230 // this should not be assumed, this value should always be read and acted upon,
231 // to allow for possible future extension to the standard.
232 // <format> 2 bytes
233 // 0 = single track file format
234 // 1 = multiple track file format
235 // 2 = multiple song file format (i.e., a series of type 0 files)
236 // <n> 2 bytes
237 // number of track chunks that follow the header chunk
238 // <division> 2 bytes
239 // unit of time for delta timing. If the value is positive, then it represents
240 // the units per beat. For example, +96 would mean 96 ticks per beat.
241 // If the value is negative, delta times are in SMPTE compatible units.
242
243 char tmp[4];
244
245 read(tmp, 4);
246 int len = readLong();
247 if (memcmp(tmp, "MThd", 4) || len < 6)
248 throw(QString("bad midifile: MThd expected"));
249
250 if (len > 6)
251 throw(QString("unsupported MIDI header data size: %1 instead of 6").arg(len));
252
253 _format = readShort();
254 int ntracks = readShort();
255
256 // ================ Read MIDI division =================
257 //
258 // 2 bytes
259 // +-------+---+-------------------+-----------------+
260 // | bit |15 | 14 8 | 7 0 |
261 // +-------+---+-------------------------------------+
262 // | | 0 | ticks per quarter note |
263 // | value +---+-------------------------------------+
264 // | | 1 | -frames/second | ticks/frame |
265 // +-------+---+-------------------+-----------------+
266
267 char firstByte;
268 fp->getChar(&firstByte);
269 char secondByte;
270 fp->getChar(&secondByte);
271 const char topBit = (firstByte & 0x80) >> 7;
272
273 if (topBit == 0) { // ticks per beat
274 _isDivisionInTps = false;
275 _division = (firstByte << 8) | (secondByte & 0xff);
276 }
277 else { // ticks per second = fps * ticks per frame
278 _isDivisionInTps = true;
279 const int framesPerSecond = -((signed char) firstByte);
280 const int ticksPerFrame = secondByte;
281 if (framesPerSecond == 29)
282 _division = qRound(29.97 * ticksPerFrame);
283 else
284 _division = framesPerSecond * ticksPerFrame;
285 }
286
287 // =====================================================
288
289 switch (_format) {
290 case 0:
291 if (readTrack())
292 return false;
293 break;
294 case 1:
295 for (int i = 0; i < ntracks; i++) {
296 if (readTrack())
297 return false;
298 }
299 break;
300 default:
301 throw(QString("midi file format %1 not implemented").arg(_format));
302
303 // Prevent "unreachable code" warning
304 // return false;
305 }
306 return true;
307 }
308
309 //---------------------------------------------------------
310 // readTrack
311 // return true on error
312 //---------------------------------------------------------
313
readTrack()314 bool MidiFile::readTrack()
315 {
316 char tmp[4];
317 read(tmp, 4);
318 if (memcmp(tmp, "MTrk", 4))
319 throw(QString("bad midifile: MTrk expected"));
320 int len = readLong(); // len
321 qint64 endPos = curPos + len;
322 status = -1;
323 sstatus = -1; // running status, will not be reset on meta or sysex
324 click = 0;
325 _tracks.push_back(MidiTrack());
326
327 int port = 0;
328 _tracks.back().setOutPort(port);
329 _tracks.back().setOutChannel(-1);
330
331 for (;;) {
332 MidiEvent event;
333 if (!readEvent(&event))
334 return true;
335
336 // check for end of track:
337 if ((event.type() == ME_META) && (event.metaType() == META_EOT))
338 break;
339 _tracks.back().insert(click, event);
340 }
341 if (curPos != endPos) {
342 qWarning("bad track len: %lld != %lld, %lld bytes too much\n", endPos, curPos, endPos - curPos);
343 if (curPos < endPos) {
344 qWarning(" skip %lld\n", endPos-curPos);
345 skip(endPos - curPos);
346 }
347 }
348 return false;
349 }
350
351 /*---------------------------------------------------------
352 * read
353 * return false on error
354 *---------------------------------------------------------*/
355
read(void * p,qint64 len)356 void MidiFile::read(void* p, qint64 len)
357 {
358 curPos += len;
359 qint64 rv = fp->read((char*)p, len);
360 if (rv != len)
361 throw(QString("bad midifile: unexpected EOF"));
362 }
363
364 //---------------------------------------------------------
365 // write
366 //---------------------------------------------------------
367
write(const void * p,qint64 len)368 bool MidiFile::write(const void* p, qint64 len)
369 {
370 qint64 rv = fp->write((char*)p, len);
371 if (rv == len)
372 return false;
373 qDebug("write midifile failed: %s", fp->errorString().toLatin1().data());
374 return true;
375 }
376
377 //---------------------------------------------------------
378 // readShort
379 //---------------------------------------------------------
380
readShort()381 int MidiFile::readShort()
382 {
383 char c;
384 int val = 0;
385 for (int i = 0; i < 2; ++i) {
386 fp->getChar(&c);
387 val <<= 8;
388 val += (c & 0xff);
389 }
390 return val;
391 }
392
393 //---------------------------------------------------------
394 // writeShort
395 //---------------------------------------------------------
396
writeShort(int i)397 void MidiFile::writeShort(int i)
398 {
399 fp->putChar(i >> 8);
400 fp->putChar(i);
401 }
402
403 //---------------------------------------------------------
404 // readLong
405 // writeLong
406 //---------------------------------------------------------
407
readLong()408 int MidiFile::readLong()
409 {
410 char c;
411 int val = 0;
412 for (int i = 0; i < 4; ++i) {
413 fp->getChar(&c);
414 val <<= 8;
415 val += (c & 0xff);
416 }
417 return val;
418 }
419
420 //---------------------------------------------------------
421 // writeLong
422 //---------------------------------------------------------
423
writeLong(int i)424 void MidiFile::writeLong(int i)
425 {
426 fp->putChar(i >> 24);
427 fp->putChar(i >> 16);
428 fp->putChar(i >> 8);
429 fp->putChar(i);
430 }
431
432 /*---------------------------------------------------------
433 * skip
434 * This is meant for skipping a few bytes in a
435 * file or fifo.
436 *---------------------------------------------------------*/
437
skip(qint64 len)438 void MidiFile::skip(qint64 len)
439 {
440 // Note: if MS is updated to use Qt 5.10, this can be implemented with QIODevice::skip(), which should be more efficient
441 // as bytes do not need to be moved around.
442 if (len <= 0)
443 return;
444 #if (!defined (_MSCVER) && !defined (_MSC_VER))
445 char tmp[len];
446 read(tmp, len);
447 #else
448 const int tmp_size = 256; // Size of fixed-length temporary buffer. MSVC does not support VLA.
449 char tmp[tmp_size];
450 while(len > tmp_size) {
451 read(tmp, len);
452 len -= tmp_size;
453 }
454 // Now len is <= tmp_size, last read fits in the buffer.
455 read(tmp, tmp_size);
456 #endif
457 }
458
459 /*---------------------------------------------------------
460 * getvl
461 * Read variable-length number (7 bits per byte, MSB first)
462 *---------------------------------------------------------*/
463
getvl()464 int MidiFile::getvl()
465 {
466 int l = 0;
467 for (int i = 0; i < 16; i++) {
468 uchar c;
469 read(&c, 1);
470 l += (c & 0x7f);
471 if (!(c & 0x80)) {
472 return l;
473 }
474 l <<= 7;
475 }
476 return -1;
477 }
478
479 /*---------------------------------------------------------
480 * putvl
481 * Write variable-length number (7 bits per byte, MSB first)
482 *---------------------------------------------------------*/
483
putvl(unsigned val)484 void MidiFile::putvl(unsigned val)
485 {
486 unsigned long buf = val & 0x7f;
487 while ((val >>= 7) > 0) {
488 buf <<= 8;
489 buf |= 0x80;
490 buf += (val & 0x7f);
491 }
492 for (;;) {
493 put(buf);
494 if (buf & 0x80)
495 buf >>= 8;
496 else
497 break;
498 }
499 }
500
501 //---------------------------------------------------------
502 // MidiTrack
503 //---------------------------------------------------------
504
MidiTrack()505 MidiTrack::MidiTrack()
506 {
507 _outChannel = -1;
508 _outPort = -1;
509 _drumTrack = false;
510 }
511
~MidiTrack()512 MidiTrack::~MidiTrack()
513 {
514 }
515
516 //---------------------------------------------------------
517 // insert
518 //---------------------------------------------------------
519
insert(int tick,const MidiEvent & event)520 void MidiTrack::insert(int tick, const MidiEvent& event)
521 {
522 _events.insert({tick, event});
523 }
524
525 //---------------------------------------------------------
526 // readEvent
527 // return true on success
528 //---------------------------------------------------------
529
readEvent(MidiEvent * event)530 bool MidiFile::readEvent(MidiEvent* event)
531 {
532 uchar me, a, b;
533
534 int nclick = getvl();
535 if (nclick == -1) {
536 qDebug("readEvent: error 1(getvl)");
537 return false;
538 }
539 click += nclick;
540 for (;;) {
541 read(&me, 1);
542 if (me >= 0xf1 && me <= 0xfe && me != 0xf7) {
543 qDebug("Midi: Unknown Message 0x%02x", me & 0xff);
544 }
545 else
546 break;
547 }
548
549 unsigned char* data;
550 int dataLen;
551
552 if (me == 0xf0 || me == 0xf7) {
553 status = -1; // no running status
554 int len = getvl();
555 if (len == -1) {
556 qDebug("readEvent: error 3");
557 return false;
558 }
559 data = new unsigned char[len+1];
560 dataLen = len;
561 read(data, len);
562 data[dataLen] = 0; // always terminate with zero
563 if (data[len-1] != 0xf7) {
564 qDebug("SYSEX does not end with 0xf7!");
565 // more to come?
566 }
567 else
568 dataLen--; // don't count 0xf7
569 event->setType(ME_SYSEX);
570 event->setEData(data);
571 event->setLen(dataLen);
572 return true;
573 }
574
575 if (me == ME_META) {
576 status = -1; // no running status
577 uchar type;
578 read(&type, 1);
579 dataLen = getvl(); // read len
580 if (dataLen == -1) {
581 qDebug("readEvent: error 6");
582 return false;
583 }
584 data = new unsigned char[dataLen + 1];
585 if (dataLen)
586 read(data, dataLen);
587 data[dataLen] = 0; // always terminate with zero so we get valid C++ strings
588
589 event->setType(ME_META);
590 event->setMetaType(type);
591 event->setLen(dataLen);
592 event->setEData(data);
593 return true;
594 }
595
596 if (me & 0x80) { // status byte
597 status = me;
598 sstatus = status;
599 read(&a, 1);
600 }
601 else {
602 if (status == -1) {
603 qDebug("readEvent: no running status, read 0x%02x", me);
604 qDebug("sstatus ist 0x%02x", sstatus);
605 if (sstatus == -1) {
606 return 0;
607 }
608 status = sstatus;
609 }
610 a = me;
611 }
612 int channel = status & 0x0f;
613 b = 0;
614 switch (status & 0xf0) {
615 case ME_NOTEOFF:
616 case ME_NOTEON:
617 case ME_POLYAFTER:
618 case ME_CONTROLLER: // controller
619 case ME_PITCHBEND: // pitch bend
620 read(&b, 1);
621 break;
622 }
623 event->setType(status & 0xf0);
624 event->setChannel(channel);
625 switch (status & 0xf0) {
626 case ME_NOTEOFF:
627 event->setDataA(a & 0x7f);
628 event->setDataB(b & 0x7f);
629 break;
630 case ME_NOTEON:
631 event->setDataA(a & 0x7f);
632 event->setDataB(b & 0x7f);
633 break;
634 case ME_POLYAFTER:
635 event->setType(ME_CONTROLLER);
636 event->setController(CTRL_POLYAFTER);
637 event->setValue(((a & 0x7f) << 8) + (b & 0x7f));
638 break;
639 case ME_CONTROLLER: // controller
640 event->setController(a & 0x7f);
641 event->setValue(b & 0x7f);
642 break;
643 case ME_PITCHBEND: // pitch bend
644 event->setDataA(a & 0x7f);
645 event->setDataB(b & 0x7f);
646 break;
647 case ME_PROGRAM:
648 event->setValue(a & 0x7f);
649 break;
650 case ME_AFTERTOUCH:
651 event->setType(ME_CONTROLLER);
652 event->setController(CTRL_PRESS);
653 event->setValue(a & 0x7f);
654 break;
655 default: // f1 f2 f3 f4 f5 f6 f7 f8 f9
656 qDebug("BAD STATUS 0x%02x, me 0x%02x", status, me);
657 return false;
658 }
659
660 if ((a & 0x80) || (b & 0x80)) {
661 qDebug("8't bit in data set(%02x %02x): tick %d read 0x%02x status:0x%02x",
662 a & 0xff, b & 0xff, click, me, status);
663 qDebug("readEvent: error 16");
664 if (b & 0x80) {
665 // Try to fix: interpret as channel byte
666 status = b;
667 sstatus = status;
668 return true;
669 }
670 return false;
671 }
672 return true;
673 }
674
675 //---------------------------------------------------------
676 // setOutChannel
677 //---------------------------------------------------------
678
setOutChannel(int n)679 void MidiTrack::setOutChannel(int n)
680 {
681 _outChannel = n;
682 if (_outChannel == 9)
683 _drumTrack = true;
684 }
685
686 //---------------------------------------------------------
687 // mergeNoteOnOffAndFindMidiType
688 // - find matching note on / note off events and merge
689 // into a note event with tick duration
690 // - find MIDI type
691 //---------------------------------------------------------
692
mergeNoteOnOffAndFindMidiType(MidiType * mt)693 void MidiTrack::mergeNoteOnOffAndFindMidiType(MidiType *mt)
694 {
695 std::multimap<int, MidiEvent> el;
696
697 int hbank = 0xff;
698 int lbank = 0xff;
699 int rpnh = -1;
700 int rpnl = -1;
701 int datah = 0;
702 int datal = 0;
703 int dataType = 0; // 0 : disabled, 0x20000 : rpn, 0x30000 : nrpn;
704
705 for (auto i = _events.begin(); i != _events.end(); ++i) {
706 MidiEvent& ev = i->second;
707 if (ev.type() == ME_INVALID)
708 continue;
709 if ((ev.type() != ME_NOTEON) && (ev.type() != ME_NOTEOFF)) {
710 if (ev.type() == ME_CONTROLLER) {
711 int val = ev.value();
712 int cn = ev.controller();
713 if (cn == CTRL_HBANK) {
714 hbank = val;
715 ev.setType(ME_INVALID);
716 continue;
717 }
718 else if (cn == CTRL_LBANK) {
719 lbank = val;
720 ev.setType(ME_INVALID);
721 continue;
722 }
723 else if (cn == CTRL_HDATA) {
724 datah = val;
725
726 // check if a CTRL_LDATA follows
727 // e.g. wie have a 14 bit controller:
728 auto ii = i;
729 ++ii;
730 bool found = false;
731 for (; ii != _events.end(); ++ii) {
732 MidiEvent& ev1 = ii->second;
733 if (ev1.type() == ME_CONTROLLER) {
734 if (ev1.controller() == CTRL_LDATA) {
735 // handle later
736 found = true;
737 }
738 break;
739 }
740 }
741 if (!found) {
742 if (rpnh == -1 || rpnl == -1) {
743 qDebug("parameter number not defined, data 0x%x", datah);
744 ev.setType(ME_INVALID);
745 continue;
746 }
747 else {
748 ev.setController(dataType | (rpnh << 8) | rpnl);
749 ev.setValue(datah);
750 }
751 }
752 else {
753 ev.setType(ME_INVALID);
754 continue;
755 }
756 }
757 else if (cn == CTRL_LDATA) {
758 datal = val;
759
760 if (rpnh == -1 || rpnl == -1) {
761 qDebug("parameter number not defined, data 0x%x 0x%x, tick %d, channel %d",
762 datah, datal, i->first, ev.channel());
763 continue;
764 }
765 // assume that the sequence is always
766 // CTRL_HDATA - CTRL_LDATA
767 // eg. that LDATA is always send last
768
769 // 14 Bit RPN/NRPN
770 ev.setController((dataType+0x30000) | (rpnh << 8) | rpnl);
771 ev.setValue((datah << 7) | datal);
772 }
773 else if (cn == CTRL_HRPN) {
774 rpnh = val;
775 dataType = 0x20000;
776 ev.setType(ME_INVALID);
777 continue;
778 }
779 else if (cn == CTRL_LRPN) {
780 rpnl = val;
781 dataType = 0x20000;
782 ev.setType(ME_INVALID);
783 continue;
784 }
785 else if (cn == CTRL_HNRPN) {
786 rpnh = val;
787 dataType = 0x30000;
788 ev.setType(ME_INVALID);
789 continue;
790 }
791 else if (cn == CTRL_LNRPN) {
792 rpnl = val;
793 dataType = 0x30000;
794 ev.setType(ME_INVALID);
795 continue;
796 }
797 else if (cn == CTRL_PROGRAM) {
798 ev.setValue((hbank << 16) | (lbank << 8) | ev.value());
799 // TODO el.insert(ev);
800 ev.setType(ME_INVALID);
801 continue;
802 }
803 }
804 else if (ev.type() == ME_SYSEX) {
805 int len = ev.len();
806 const uchar* buffer = ev.edata();
807 if ((len == gmOnMsgLen) && memcmp(buffer, gmOnMsg, gmOnMsgLen) == 0) {
808 *mt = MidiType::GM;
809 ev.setType(ME_INVALID);
810 continue;
811 }
812 if ((len == gsOnMsgLen) && memcmp(buffer, gsOnMsg, gsOnMsgLen) == 0) {
813 *mt = MidiType::GS;
814 ev.setType(ME_INVALID);
815 continue;
816 }
817 if ((len == xgOnMsgLen) && memcmp(buffer, xgOnMsg, xgOnMsgLen) == 0) {
818 *mt = MidiType::XG;
819 ev.setType(ME_INVALID);
820 continue;
821 }
822 if (buffer[0] == 0x43) { // Yamaha
823 *mt = MidiType::XG;
824 int type = buffer[1] & 0xf0;
825 if (type == 0x10) {
826 //TODO if (buffer[1] != 0x10) {
827 // buffer[1] = 0x10; // fix to Device 1
828 // }
829 if ((len == xgOnMsgLen) && memcmp(buffer, xgOnMsg, xgOnMsgLen) == 0) {
830 *mt = MidiType::XG;
831 ev.setType(ME_INVALID);
832 continue;
833 }
834 if (len == 7 && buffer[2] == 0x4c && buffer[3] == 0x08 && buffer[5] == 7) {
835 // part mode
836 // 0 - normal
837 // 1 - DRUM
838 // 2 - DRUM 1
839 // 3 - DRUM 2
840 // 4 - DRUM 3
841 // 5 - DRUM 4
842 if (buffer[6] != 0 && buffer[4] == ev.channel()) {
843 _drumTrack = true;
844 }
845 ev.setType(ME_INVALID);
846 continue;
847 }
848 }
849 }
850 }
851 el.insert(std::pair<int,MidiEvent>(i->first, ev));
852 ev.setType(ME_INVALID);
853 continue;
854 }
855 int tick = i->first;
856 if (ev.type() == ME_NOTEOFF || ev.velo() == 0) {
857 qDebug("-extra note off at %d", tick);
858 ev.setType(ME_INVALID);
859 continue;
860 }
861 MidiEvent note(ME_NOTE, ev.channel(), ev.dataA(), ev.dataB());
862
863 auto k = i;
864 ++k;
865 for (; k != _events.end(); ++k) {
866 MidiEvent& e = k->second;
867 if (e.type() != ME_NOTEON && e.type() != ME_NOTEOFF)
868 continue;
869 if ((e.type() == ME_NOTEOFF || (e.type() == ME_NOTEON && e.velo() == 0))
870 && (e.pitch() == note.pitch())) {
871 int t = k->first - tick;
872 if (t <= 0)
873 t = 1;
874 note.setLen(t);
875 e.setType(ME_INVALID);
876 break;
877 }
878 }
879 if (k == _events.end()) {
880 qDebug("-no note-off for note at %d", tick);
881 note.setLen(1);
882 }
883 el.insert(std::pair<int,MidiEvent>(tick, note));
884 ev.setType(ME_INVALID);
885 }
886 _events = el;
887 }
888
889 //---------------------------------------------------------
890 // separateChannel
891 // if a track contains events for different midi channels,
892 // then split events into separate tracks
893 //---------------------------------------------------------
894
separateChannel()895 void MidiFile::separateChannel()
896 {
897 for (int i = 0; i < _tracks.size(); ++i) {
898 // create a list of channels used in current track
899 QList<int> channel;
900 MidiTrack &mt = _tracks[i]; // current track
901 for (const auto& ie : mt.events()) {
902 const MidiEvent& e = ie.second;
903 if (e.isChannelEvent() && !channel.contains(e.channel()))
904 channel.append(e.channel());
905 }
906 mt.setOutChannel(channel.empty() ? 0 : channel[0]);
907 int nn = channel.size();
908 if (nn <= 1)
909 continue;
910 std::sort(channel.begin(), channel.end());
911 // -- split --
912 // insert additional tracks, assign to them found channels
913 for (int ii = 1; ii < nn; ++ii) {
914 MidiTrack t;
915 t.setOutChannel(channel[ii]);
916 _tracks.insert(i + ii, t);
917 }
918 // extract all different channel events from current track to inserted tracks
919 for (auto ie = mt.events().begin(); ie != mt.events().end(); ) {
920 const MidiEvent& e = ie->second;
921 if (e.isChannelEvent()) {
922 int ch = e.channel();
923 int idx = channel.indexOf(ch);
924 MidiTrack &t = _tracks[i + idx];
925 if (&t != &mt) {
926 t.insert(ie->first, e);
927 ie = mt.events().erase(ie);
928 continue;
929 }
930 }
931 ++ie;
932 }
933 i += nn - 1;
934 }
935 }
936
937 } // namespace Ms
938