void MidiFile::writeEvent(const MidiEvent& event) { switch(event.type()) { case ME_NOTEON: writeStatus(ME_NOTEON, event.channel()); put(event.pitch()); put(event.velo()); break; case ME_NOTEOFF: writeStatus(ME_NOTEOFF, event.channel()); put(event.pitch()); put(event.velo()); break; case ME_CONTROLLER: switch(event.controller()) { case CTRL_PROGRAM: writeStatus(ME_PROGRAM, event.channel()); put(event.value() & 0x7f); break; case CTRL_PITCH: { writeStatus(ME_PITCHBEND, event.channel()); int v = event.value() + 8192; put(v & 0x7f); put((v >> 7) & 0x7f); } break; case CTRL_PRESS: writeStatus(ME_AFTERTOUCH, event.channel()); put(event.value() & 0x7f); break; default: writeStatus(ME_CONTROLLER, event.channel()); put(event.controller()); put(event.value() & 0x7f); break; } break; case ME_META: put(ME_META); put(event.metaType()); putvl(event.len()); write(event.edata(), event.len()); resetRunningStatus(); // really ?! break; case ME_SYSEX: put(ME_SYSEX); putvl(event.len() + 1); // including 0xf7 write(event.edata(), event.len()); put(ME_ENDSYSEX); resetRunningStatus(); break; } }
bool MidiFile::readTrack() { char tmp[4]; read(tmp, 4); if (memcmp(tmp, "MTrk", 4)) throw(QString("bad midifile: MTrk expected")); int len = readLong(); // len qint64 endPos = curPos + len; status = -1; sstatus = -1; // running status, will not be reset on meta or sysex click = 0; _tracks.push_back(MidiTrack()); int port = 0; _tracks.back().setOutPort(port); _tracks.back().setOutChannel(-1); for (;;) { MidiEvent event; if (!readEvent(&event)) return true; // check for end of track: if ((event.type() == ME_META) && (event.metaType() == META_EOT)) break; _tracks.back().insert(click, event); } if (curPos != endPos) { qWarning("bad track len: %lld != %lld, %lld bytes too much\n", endPos, curPos, endPos - curPos); if (curPos < endPos) { qWarning(" skip %lld\n", endPos-curPos); skip(endPos - curPos); } } return false; }
bool isLyricEvent(const MidiEvent &e) { return e.type() == ME_META && (e.metaType() == META_TEXT || e.metaType() == META_LYRIC); }
void MTrack::processMeta(int tick, const MidiEvent& mm) { if (!staff) { qDebug("processMeta: no staff"); return; } const uchar* data = (uchar*)mm.edata(); int staffIdx = staff->idx(); Score* cs = staff->score(); switch (mm.metaType()) { case META_TEXT: case META_LYRIC: { QString s((char*)data); cs->addLyrics(tick, staffIdx, s); } break; case META_TRACK_NAME: name = (const char*)data; break; case META_TEMPO: { unsigned tempo = data[2] + (data[1] << 8) + (data[0] <<16); double t = 1000000.0 / double(tempo); cs->setTempo(tick, t); // TODO: create TempoText } break; case META_KEY_SIGNATURE: { int key = ((const char*)data)[0]; if (key < -7 || key > 7) { qDebug("ImportMidi: illegal key %d", key); break; } KeySigEvent ks; ks.setAccidentalType(key); (*staff->keymap())[tick] = ks; hasKey = true; } break; case META_COMPOSER: // mscore extension case META_POET: case META_TRANSLATOR: case META_SUBTITLE: case META_TITLE: { Text* text = new Text(cs); switch(mm.metaType()) { case META_COMPOSER: text->setTextStyleType(TEXT_STYLE_COMPOSER); break; case META_TRANSLATOR: text->setTextStyleType(TEXT_STYLE_TRANSLATOR); break; case META_POET: text->setTextStyleType(TEXT_STYLE_POET); break; case META_SUBTITLE: text->setTextStyleType(TEXT_STYLE_SUBTITLE); break; case META_TITLE: text->setTextStyleType(TEXT_STYLE_TITLE); break; } text->setText((const char*)(mm.edata())); MeasureBase* measure = cs->first(); if (measure->type() != Element::VBOX) { measure = new VBox(cs); measure->setTick(0); measure->setNext(cs->first()); cs->add(measure); } measure->add(text); } break; case META_COPYRIGHT: cs->setMetaTag("Copyright", QString((const char*)(mm.edata()))); break; case META_TIME_SIGNATURE: qDebug("midi: meta timesig: %d, division %d", tick, MScore::division); cs->sigmap()->add(tick, Fraction(data[0], 1 << data[1])); break; default: if (MScore::debugMode) qDebug("unknown meta type 0x%02x", mm.metaType()); break; } }