drumstick
0.5.0
|
00001 /* 00002 Standard MIDI File component 00003 Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net> 00004 00005 Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee 00006 00007 This library is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License along 00018 with this program; if not, write to the Free Software Foundation, Inc., 00019 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "qsmf.h" 00023 #include <limits> 00024 #include <QList> 00025 #include <QFile> 00026 #include <QDataStream> 00027 #include <QTextCodec> 00028 00034 namespace drumstick { 00035 00048 class QSmf::QSmfPrivate { 00049 public: 00050 QSmfPrivate(): 00051 m_Interactive(false), 00052 m_CurrTime(0), 00053 m_RealTime(0), 00054 m_DblRealTime(0), 00055 m_DblOldRealtime(0), 00056 m_Division(96), 00057 m_CurrTempo(500000), 00058 m_OldCurrTempo(500000), 00059 m_OldRealTime(0), 00060 m_OldCurrTime(0), 00061 m_RevisedTime(0), 00062 m_TempoChangeTime(0), 00063 m_ToBeRead(0), 00064 m_NumBytesWritten(0), 00065 m_Tracks(0), 00066 m_fileFormat(0), 00067 m_LastStatus(0), 00068 m_codec(0), 00069 m_IOStream(0) 00070 { } 00071 00072 bool m_Interactive; 00073 quint64 m_CurrTime; 00074 quint64 m_RealTime; 00075 double m_DblRealTime; 00076 double m_DblOldRealtime; 00077 int m_Division; 00078 quint64 m_CurrTempo; 00079 quint64 m_OldCurrTempo; 00080 quint64 m_OldRealTime; 00081 quint64 m_OldCurrTime; 00082 quint64 m_RevisedTime; 00083 quint64 m_TempoChangeTime; 00084 quint64 m_ToBeRead; 00085 quint64 m_NumBytesWritten; 00086 int m_Tracks; 00087 int m_fileFormat; 00088 int m_LastStatus; 00089 QTextCodec *m_codec; 00090 QDataStream *m_IOStream; 00091 QByteArray m_MsgBuff; 00092 QList<QSmfRecTempo> m_TempoList; 00093 }; 00094 00099 QSmf::QSmf(QObject * parent) : 00100 QObject(parent), 00101 d(new QSmfPrivate) 00102 { } 00103 00107 QSmf::~QSmf() 00108 { 00109 d->m_TempoList.clear(); 00110 delete d; 00111 } 00112 00117 bool QSmf::endOfSmf() 00118 { 00119 return d->m_IOStream->atEnd(); 00120 } 00121 00126 quint8 QSmf::getByte() 00127 { 00128 quint8 b = 0; 00129 if (!d->m_IOStream->atEnd()) 00130 { 00131 *d->m_IOStream >> b; 00132 d->m_ToBeRead--; 00133 } 00134 return b; 00135 } 00136 00141 void QSmf::putByte(quint8 value) 00142 { 00143 *d->m_IOStream << value; 00144 d->m_NumBytesWritten++; 00145 } 00146 00152 void QSmf::addTempo(quint64 tempo, quint64 time) 00153 { 00154 QSmfRecTempo tempoRec; 00155 tempoRec.tempo = tempo; 00156 tempoRec.time = time; 00157 d->m_TempoList.append(tempoRec); 00158 } 00159 00163 void QSmf::readHeader() 00164 { 00165 d->m_CurrTime = 0; 00166 d->m_RealTime = 0; 00167 d->m_Division = 96; 00168 d->m_CurrTempo = 500000; 00169 d->m_OldCurrTempo = 500000; 00170 addTempo(d->m_CurrTempo, 0); 00171 if (d->m_Interactive) 00172 { 00173 d->m_fileFormat= 0; 00174 d->m_Tracks = 1; 00175 d->m_Division = 96; 00176 } 00177 else 00178 { 00179 readExpected("MThd"); 00180 d->m_ToBeRead = read32bit(); 00181 d->m_fileFormat = read16bit(); 00182 d->m_Tracks = read16bit(); 00183 d->m_Division = read16bit(); 00184 } 00185 emit signalSMFHeader(d->m_fileFormat, d->m_Tracks, d->m_Division); 00186 00187 /* flush any extra stuff, in case the length of header is not */ 00188 while ((d->m_ToBeRead > 0) && !endOfSmf()) 00189 { 00190 getByte(); 00191 } 00192 } 00193 00197 void QSmf::readTrack() 00198 { 00199 /* This array is indexed by the high half of a status byte. It's 00200 value is either the number of bytes needed (1 or 2) for a channel 00201 message, or 0 (meaning it's not a channel message). */ 00202 static const quint8 chantype[16] = 00203 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 }; 00204 00205 quint64 lookfor; 00206 quint8 c, c1, type; 00207 bool sysexcontinue; // 1 if last message was an unfinished SysEx 00208 bool running; // 1 when running status used 00209 quint8 status; // status value (e.g. 0x90==note-on) 00210 int needed; 00211 double delta_secs; 00212 quint64 delta_ticks, save_time, save_tempo; 00213 00214 sysexcontinue = false; 00215 status = 0; 00216 if (d->m_Interactive) 00217 { 00218 d->m_ToBeRead = std::numeric_limits<unsigned long long>::max(); 00219 } 00220 else 00221 { 00222 readExpected("MTrk"); 00223 d->m_ToBeRead = read32bit(); 00224 } 00225 d->m_CurrTime = 0; 00226 d->m_RealTime = 0; 00227 d->m_DblRealTime = 0; 00228 d->m_DblOldRealtime = 0; 00229 d->m_OldCurrTime = 0; 00230 d->m_OldRealTime = 0; 00231 d->m_CurrTempo = findTempo(); 00232 00233 emit signalSMFTrackStart(); 00234 00235 while (!endOfSmf() && (d->m_Interactive || d->m_ToBeRead > 0)) 00236 { 00237 if (d->m_Interactive) 00238 { 00239 d->m_CurrTime++; 00240 } 00241 else 00242 { 00243 delta_ticks = readVarLen(); 00244 d->m_RevisedTime = d->m_CurrTime; 00245 d->m_CurrTime += delta_ticks; 00246 while (d->m_RevisedTime < d->m_CurrTime) 00247 { 00248 save_time = d->m_RevisedTime; 00249 save_tempo = d->m_CurrTempo; 00250 d->m_CurrTempo = findTempo(); 00251 if (d->m_CurrTempo != d->m_OldCurrTempo) 00252 { 00253 d->m_OldCurrTempo = d->m_CurrTempo; 00254 d->m_OldRealTime = d->m_RealTime; 00255 if (d->m_RevisedTime != d->m_TempoChangeTime) 00256 { 00257 d->m_DblOldRealtime = d->m_DblRealTime; 00258 d->m_OldCurrTime = save_time; 00259 } 00260 delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime, 00261 d->m_Division, save_tempo); 00262 d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0; 00263 d->m_RealTime = static_cast<quint64>(0.5 + d->m_DblRealTime); 00264 if (d->m_RevisedTime == d->m_TempoChangeTime) 00265 { 00266 d->m_OldCurrTime = d->m_RevisedTime; 00267 d->m_DblOldRealtime = d->m_DblRealTime; 00268 } 00269 } 00270 else 00271 { 00272 delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime, 00273 d->m_Division, d->m_CurrTempo); 00274 d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0; 00275 d->m_RealTime = static_cast<quint64>(0.5 + d->m_DblRealTime); 00276 } 00277 } 00278 } 00279 00280 c = getByte(); 00281 if (sysexcontinue && (c != end_of_sysex)) 00282 { 00283 SMFError("didn't find expected continuation of a SysEx"); 00284 } 00285 if (c < 0xf8) 00286 { 00287 if ((c & 0x80) == 0) 00288 { 00289 if (status == 0) 00290 { 00291 SMFError("unexpected running status"); 00292 } 00293 running = true; 00294 } 00295 else 00296 { 00297 status = c; 00298 running = false; 00299 } 00300 needed = chantype[status >> 4 & 0x0f]; 00301 if (needed != 0) 00302 { 00303 if (running) 00304 { 00305 c1 = c; 00306 } 00307 else 00308 { 00309 c1 = getByte(); 00310 } 00311 if (needed > 1) 00312 { 00313 channelMessage(status, c1, getByte()); 00314 } 00315 else 00316 { 00317 channelMessage(status, c1, 0); 00318 } 00319 continue; 00320 } 00321 } 00322 00323 switch (c) 00324 { 00325 case meta_event: 00326 type = getByte(); 00327 lookfor = readVarLen(); 00328 lookfor = d->m_ToBeRead - lookfor; 00329 msgInit(); 00330 while (d->m_ToBeRead > lookfor) 00331 { 00332 msgAdd(getByte()); 00333 } 00334 metaEvent(type); 00335 break; 00336 case system_exclusive: 00337 lookfor = readVarLen(); 00338 lookfor = d->m_ToBeRead - lookfor; 00339 msgInit(); 00340 msgAdd(system_exclusive); 00341 while (d->m_ToBeRead > lookfor) 00342 { 00343 c = getByte(); 00344 msgAdd(c); 00345 } 00346 if (c == end_of_sysex) 00347 { 00348 sysEx(); 00349 } 00350 else 00351 { 00352 sysexcontinue = true; 00353 } 00354 break; 00355 case end_of_sysex: 00356 lookfor = readVarLen(); 00357 lookfor = d->m_ToBeRead - lookfor; 00358 if (!sysexcontinue) 00359 { 00360 msgInit(); 00361 } 00362 while (d->m_ToBeRead > lookfor) 00363 { 00364 c = getByte(); 00365 msgAdd(c); 00366 } 00367 if (sysexcontinue) 00368 { 00369 if (c == end_of_sysex) 00370 { 00371 sysEx(); 00372 sysexcontinue = false; 00373 } 00374 } 00375 break; 00376 default: 00377 badByte(c, d->m_IOStream->device()->pos() - 1); 00378 break; 00379 } 00380 } 00381 emit signalSMFTrackEnd(); 00382 } 00383 00387 void QSmf::SMFRead() 00388 { 00389 int i; 00390 readHeader(); 00391 for ( i = d->m_Tracks; (i > 0) && !endOfSmf(); i--) 00392 { 00393 readTrack(); 00394 } 00395 } 00396 00404 void QSmf::SMFWrite() 00405 { 00406 int i; 00407 d->m_LastStatus = 0; 00408 writeHeaderChunk(d->m_fileFormat, d->m_Tracks, d->m_Division); 00409 d->m_LastStatus = 0; 00410 if (d->m_fileFormat == 1) 00411 { 00412 emit signalSMFWriteTempoTrack(); 00413 } 00414 for (i = 0; i < d->m_Tracks; ++i) 00415 { 00416 writeTrackChunk(i); 00417 } 00418 } 00419 00424 void QSmf::readFromStream(QDataStream *stream) 00425 { 00426 d->m_IOStream = stream; 00427 SMFRead(); 00428 } 00429 00434 void QSmf::readFromFile(const QString& fileName) 00435 { 00436 QFile file(fileName); 00437 file.open(QIODevice::ReadOnly); 00438 QDataStream ds(&file); 00439 readFromStream(&ds); 00440 file.close(); 00441 } 00442 00447 void QSmf::writeToStream(QDataStream *stream) 00448 { 00449 d->m_IOStream = stream; 00450 SMFWrite(); 00451 } 00452 00457 void QSmf::writeToFile(const QString& fileName) 00458 { 00459 QFile file(fileName); 00460 file.open(QIODevice::WriteOnly); 00461 QDataStream ds(&file); 00462 writeToStream(&ds); 00463 file.close(); 00464 } 00465 00472 void QSmf::writeHeaderChunk(int format, int ntracks, int division) 00473 { 00474 write32bit(MThd); 00475 write32bit(6); 00476 write16bit(format); 00477 write16bit(ntracks); 00478 write16bit(division); 00479 } 00480 00485 void QSmf::writeTrackChunk(int track) 00486 { 00487 quint32 trkhdr; 00488 quint32 trklength; 00489 qint64 offset; 00490 qint64 place_marker; 00491 00492 d->m_LastStatus = 0; 00493 trkhdr = MTrk; 00494 trklength = 0; 00495 offset = d->m_IOStream->device()->pos(); 00496 write32bit(trkhdr); 00497 write32bit(trklength); 00498 d->m_NumBytesWritten = 0; 00499 00500 emit signalSMFWriteTrack(track); 00501 00502 place_marker = d->m_IOStream->device()->pos(); 00503 d->m_IOStream->device()->seek(offset); 00504 trklength = d->m_NumBytesWritten; 00505 write32bit(trkhdr); 00506 write32bit(trklength); 00507 d->m_IOStream->device()->seek(place_marker); 00508 } 00509 00516 void QSmf::writeMetaEvent(long deltaTime, int type, const QByteArray& data) 00517 { 00518 writeVarLen(deltaTime); 00519 d->m_LastStatus = meta_event; 00520 putByte(d->m_LastStatus); 00521 putByte(type); 00522 writeVarLen(data.size()); 00523 foreach(char byte, data) 00524 putByte(byte); 00525 } 00526 00533 void QSmf::writeMetaEvent(long deltaTime, int type, const QString& data) 00534 { 00535 writeVarLen(deltaTime); 00536 putByte(d->m_LastStatus = meta_event); 00537 putByte(type); 00538 QByteArray lcldata; 00539 if (d->m_codec == NULL) 00540 lcldata = data.toLatin1(); 00541 else 00542 lcldata = d->m_codec->fromUnicode(data); 00543 writeVarLen(lcldata.length()); 00544 foreach(char byte, lcldata) 00545 putByte(byte); 00546 } 00547 00555 void QSmf::writeMetaEvent(long deltaTime, int type, int data) 00556 { 00557 writeVarLen(deltaTime); 00558 putByte(d->m_LastStatus = meta_event); 00559 putByte(type); 00560 putByte(1); 00561 putByte(data); 00562 } 00563 00569 void QSmf::writeMetaEvent(long deltaTime, int type) 00570 { 00571 writeVarLen(deltaTime); 00572 putByte(d->m_LastStatus = meta_event); 00573 putByte(type); 00574 putByte(0); 00575 } 00576 00584 void QSmf::writeMidiEvent(long deltaTime, int type, int chan, 00585 const QByteArray& data) 00586 { 00587 int i, j, size; 00588 quint8 c; 00589 writeVarLen(deltaTime); 00590 if ((type == system_exclusive) || (type == end_of_sysex)) 00591 { 00592 c = type; 00593 d->m_LastStatus = 0; 00594 } 00595 else 00596 { 00597 if (chan > 15) 00598 { 00599 SMFError("error: MIDI channel greater than 16"); 00600 } 00601 c = type | chan; 00602 } 00603 if (d->m_LastStatus != c) 00604 { 00605 d->m_LastStatus = c; 00606 putByte(c); 00607 } 00608 if (type == system_exclusive || type == end_of_sysex) 00609 { 00610 size = data.size(); 00611 if (data[0] == type) 00612 --size; 00613 writeVarLen(size); 00614 } 00615 j = (data[0] == type ? 1 : 0); 00616 for (i = j; i < data.size(); ++i) 00617 { 00618 putByte(data[i]); 00619 } 00620 } 00621 00629 void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1) 00630 { 00631 quint8 c; 00632 writeVarLen(deltaTime); 00633 if ((type == system_exclusive) || (type == end_of_sysex)) 00634 { 00635 SMFError("error: Wrong method for a system exclusive event"); 00636 } 00637 if (chan > 15) 00638 { 00639 SMFError("error: MIDI channel greater than 16"); 00640 } 00641 c = type | chan; 00642 if (d->m_LastStatus != c) 00643 { 00644 d->m_LastStatus = c; 00645 putByte(c); 00646 } 00647 putByte(b1); 00648 } 00649 00658 void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1, int b2) 00659 { 00660 quint8 c; 00661 writeVarLen(deltaTime); 00662 if ((type == system_exclusive) || (type == end_of_sysex)) 00663 { 00664 SMFError("error: Wrong method for a system exclusive event"); 00665 } 00666 if (chan > 15) 00667 { 00668 SMFError("error: MIDI channel greater than 16"); 00669 } 00670 c = type | chan; 00671 if (d->m_LastStatus != c) 00672 { 00673 d->m_LastStatus = c; 00674 putByte(c); 00675 } 00676 putByte(b1); 00677 putByte(b2); 00678 } 00679 00687 void QSmf::writeMidiEvent(long deltaTime, int type, long len, char* data) 00688 { 00689 unsigned int i, j, size; 00690 quint8 c; 00691 writeVarLen(deltaTime); 00692 if ((type != system_exclusive) && (type != end_of_sysex)) 00693 { 00694 SMFError("error: type should be system exclusive"); 00695 } 00696 d->m_LastStatus = 0; 00697 c = type; 00698 putByte(c); 00699 size = len; 00700 c = (unsigned)data[0]; 00701 if (c == type) 00702 --size; 00703 writeVarLen(size); 00704 j = (c == type ? 1 : 0); 00705 for (i = j; i < (unsigned)len; ++i) 00706 { 00707 putByte(data[i]); 00708 } 00709 } 00710 00716 void QSmf::writeSequenceNumber(long deltaTime, int seqnum) 00717 { 00718 writeVarLen(deltaTime); 00719 d->m_LastStatus = meta_event; 00720 putByte(d->m_LastStatus); 00721 putByte(sequence_number); 00722 putByte(2); 00723 putByte((seqnum >> 8) & 0xff); 00724 putByte(seqnum & 0xff); 00725 } 00726 00732 void QSmf::writeTempo(long deltaTime, long tempo) 00733 { 00734 writeVarLen(deltaTime); 00735 putByte(d->m_LastStatus = meta_event); 00736 putByte(set_tempo); 00737 putByte(3); 00738 putByte((tempo >> 16) & 0xff); 00739 putByte((tempo >> 8) & 0xff); 00740 putByte(tempo & 0xff); 00741 } 00742 00748 void QSmf::writeBpmTempo(long deltaTime, int tempo) 00749 { 00750 long us_tempo = 60000000l / tempo; 00751 writeTempo(deltaTime, us_tempo); 00752 } 00753 00762 void QSmf::writeTimeSignature(long deltaTime, int num, int den, int cc, int bb) 00763 { 00764 writeVarLen(deltaTime); 00765 putByte(d->m_LastStatus = meta_event); 00766 putByte(time_signature); 00767 putByte(4); 00768 putByte(num & 0xff); 00769 putByte(den & 0xff); 00770 putByte(cc & 0xff); 00771 putByte(bb & 0xff); 00772 } 00773 00780 void QSmf::writeKeySignature(long deltaTime, int tone, int mode) 00781 { 00782 writeVarLen(deltaTime); 00783 putByte(d->m_LastStatus = meta_event); 00784 putByte(key_signature); 00785 putByte(2); 00786 putByte((char)tone); 00787 putByte(mode & 0x01); 00788 } 00789 00794 void QSmf::writeVarLen(quint64 value) 00795 { 00796 quint64 buffer; 00797 00798 buffer = value & 0x7f; 00799 while ((value >>= 7) > 0) 00800 { 00801 buffer <<= 8; 00802 buffer |= 0x80; 00803 buffer += (value & 0x7f); 00804 } 00805 while (true) 00806 { 00807 putByte(buffer & 0xff); 00808 if (buffer & 0x80) 00809 buffer >>= 8; 00810 else 00811 break; 00812 } 00813 } 00814 00815 /* These routines are used to make sure that the byte order of 00816 the various data types remains constant between machines. */ 00817 void QSmf::write32bit(quint32 data) 00818 { 00819 putByte((data >> 24) & 0xff); 00820 putByte((data >> 16) & 0xff); 00821 putByte((data >> 8) & 0xff); 00822 putByte(data & 0xff); 00823 } 00824 00825 void QSmf::write16bit(quint16 data) 00826 { 00827 putByte((data >> 8) & 0xff); 00828 putByte(data & 0xff); 00829 } 00830 00831 quint16 QSmf::to16bit(quint8 c1, quint8 c2) 00832 { 00833 quint16 value; 00834 value = (c1 << 8); 00835 value += c2; 00836 return value; 00837 } 00838 00839 quint32 QSmf::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4) 00840 { 00841 quint32 value; 00842 value = (c1 << 24); 00843 value += (c2 << 16); 00844 value += (c3 << 8); 00845 value += c4; 00846 return value; 00847 } 00848 00849 quint16 QSmf::read16bit() 00850 { 00851 quint8 c1, c2; 00852 c1 = getByte(); 00853 c2 = getByte(); 00854 return to16bit(c1, c2); 00855 } 00856 00857 quint32 QSmf::read32bit() 00858 { 00859 quint8 c1, c2, c3, c4; 00860 c1 = getByte(); 00861 c2 = getByte(); 00862 c3 = getByte(); 00863 c4 = getByte(); 00864 return to32bit(c1, c2, c3, c4); 00865 } 00866 00867 long QSmf::readVarLen() 00868 { 00869 long value; 00870 quint8 c; 00871 00872 c = getByte(); 00873 value = c; 00874 if ((c & 0x80) != 0) 00875 { 00876 value &= 0x7f; 00877 do 00878 { 00879 c = getByte(); 00880 value = (value << 7) + (c & 0x7f); 00881 } while ((c & 0x80) != 0); 00882 } 00883 return value; 00884 } 00885 00886 void QSmf::readExpected(const QString& s) 00887 { 00888 int j; 00889 quint8 b; 00890 for (j = 0; j < s.length(); ++j) 00891 { 00892 b = getByte(); 00893 if (QChar(b) != s[j]) 00894 { 00895 SMFError(QString("Invalid (%1) SMF format at %2").arg(b, 0, 16).arg(d->m_IOStream->device()->pos())); 00896 break; 00897 } 00898 } 00899 } 00900 00901 quint64 QSmf::findTempo() 00902 { 00903 quint64 result, old_tempo, new_tempo; 00904 QSmfRecTempo rec = d->m_TempoList.last(); 00905 old_tempo = d->m_CurrTempo; 00906 new_tempo = d->m_CurrTempo; 00907 QList<QSmfRecTempo>::Iterator it; 00908 for( it = d->m_TempoList.begin(); it != d->m_TempoList.end(); ++it ) 00909 { 00910 rec = (*it); 00911 if (rec.time <= d->m_CurrTime) 00912 { 00913 old_tempo = rec.tempo; 00914 } 00915 new_tempo = rec.tempo; 00916 if (rec.time > d->m_RevisedTime) 00917 { 00918 break; 00919 } 00920 } 00921 if ((rec.time <= d->m_RevisedTime) || (rec.time > d->m_CurrTime)) 00922 { 00923 d->m_RevisedTime = d->m_CurrTime; 00924 result = old_tempo; 00925 } 00926 else 00927 { 00928 d->m_RevisedTime = rec.time; 00929 d->m_TempoChangeTime = d->m_RevisedTime; 00930 result = new_tempo; 00931 } 00932 return result; 00933 } 00934 00935 /* This routine converts delta times in ticks into seconds. The 00936 else statement is needed because the formula is different for tracks 00937 based on notes and tracks based on SMPTE times. */ 00938 double QSmf::ticksToSecs(quint64 ticks, quint16 division, quint64 tempo) 00939 { 00940 double result; 00941 double smpte_format; 00942 double smpte_resolution; 00943 00944 if (division > 0) 00945 { 00946 result = static_cast<double>(ticks * tempo)/(division * 1000000.0); 00947 } 00948 else 00949 { 00950 smpte_format = upperByte(division); 00951 smpte_resolution = lowerByte(division); 00952 result = static_cast<double>(ticks)/(smpte_format * smpte_resolution 00953 * 1000000.0); 00954 } 00955 return result; 00956 } 00957 00958 void QSmf::SMFError(const QString& s) 00959 { 00960 emit signalSMFError(s); 00961 } 00962 00963 void QSmf::channelMessage(quint8 status, quint8 c1, quint8 c2) 00964 { 00965 quint8 chan; 00966 int k; 00967 chan = status & midi_channel_mask; 00968 if (c1 > 127) 00969 { 00970 SMFError(QString("ChannelMessage with bad c1 = %1").arg(c1)); 00971 //c1 &= 127; 00972 } 00973 if (c2 > 127) 00974 { 00975 SMFError(QString("ChannelMessage with bad c2 = %1").arg(c2)); 00976 //c2 &= 127; 00977 } 00978 switch (status & midi_command_mask) 00979 { 00980 case note_off: 00981 emit signalSMFNoteOff(chan, c1, c2); 00982 break; 00983 case note_on: 00984 emit signalSMFNoteOn(chan, c1, c2); 00985 break; 00986 case poly_aftertouch: 00987 emit signalSMFKeyPress(chan, c1, c2); 00988 break; 00989 case control_change: 00990 emit signalSMFCtlChange(chan, c1, c2); 00991 break; 00992 case program_chng: 00993 emit signalSMFProgram(chan, c1); 00994 break; 00995 case channel_aftertouch: 00996 emit signalSMFChanPress(chan, c1); 00997 break; 00998 case pitch_wheel: 00999 k = c1 + (c2 << 7) - 8192; 01000 emit signalSMFPitchBend(chan, k); 01001 break; 01002 default: 01003 SMFError(QString("Invalid MIDI status %1. Unhandled event").arg(status)); 01004 break; 01005 } 01006 } 01007 01008 void QSmf::metaEvent(quint8 b) 01009 { 01010 QSmfRecTempo rec; 01011 QByteArray m(d->m_MsgBuff); 01012 01013 switch (b) 01014 { 01015 case sequence_number: 01016 emit signalSMFSequenceNum(to16bit(m[0], m[1])); 01017 break; 01018 case text_event: 01019 case copyright_notice: 01020 case sequence_name: 01021 case instrument_name: 01022 case lyric: 01023 case marker: 01024 case cue_point: { 01025 QString s; 01026 if (d->m_codec == NULL) 01027 s = QString(m); 01028 else 01029 s = d->m_codec->toUnicode(m); 01030 emit signalSMFText(b, s); 01031 } 01032 break; 01033 case forced_channel: 01034 emit signalSMFforcedChannel(m[0]); 01035 break; 01036 case forced_port: 01037 emit signalSMFforcedPort(m[0]); 01038 break; 01039 case end_of_track: 01040 emit signalSMFendOfTrack(); 01041 break; 01042 case set_tempo: 01043 d->m_CurrTempo = to32bit(0, m[0], m[1], m[2]); 01044 emit signalSMFTempo(d->m_CurrTempo); 01045 rec = d->m_TempoList.last(); 01046 if (rec.tempo == d->m_CurrTempo) 01047 { 01048 return; 01049 } 01050 if (rec.time > d->m_CurrTime) 01051 { 01052 return; 01053 } 01054 addTempo(d->m_CurrTempo, d->m_CurrTime); 01055 break; 01056 case smpte_offset: 01057 emit signalSMFSmpte(m[0], m[1], m[2], m[3], m[4]); 01058 break; 01059 case time_signature: 01060 emit signalSMFTimeSig(m[0], m[1], m[2], m[3]); 01061 break; 01062 case key_signature: 01063 emit signalSMFKeySig(m[0], m[1]); 01064 break; 01065 case sequencer_specific: 01066 emit signalSMFSeqSpecific(m); 01067 break; 01068 default: 01069 emit signalSMFMetaUnregistered(b, m); 01070 break; 01071 } 01072 emit signalSMFMetaMisc(b, m); 01073 } 01074 01075 void QSmf::sysEx() 01076 { 01077 QByteArray varr(d->m_MsgBuff); 01078 emit signalSMFSysex(varr); 01079 } 01080 01081 void QSmf::badByte(quint8 b, int p) 01082 { 01083 SMFError(QString("Unexpected byte (%1) at %2").arg(b, 2, 16).arg(p)); 01084 } 01085 01086 quint8 QSmf::lowerByte(quint16 x) 01087 { 01088 return (x & 0xff); 01089 } 01090 01091 quint8 QSmf::upperByte(quint16 x) 01092 { 01093 return ((x >> 8) & 0xff); 01094 } 01095 01096 void QSmf::msgInit() 01097 { 01098 d->m_MsgBuff.truncate(0); 01099 } 01100 01101 void QSmf::msgAdd(quint8 b) 01102 { 01103 int s = d->m_MsgBuff.size(); 01104 d->m_MsgBuff.resize(s + 1); 01105 d->m_MsgBuff[s] = b; 01106 } 01107 01108 /* public properties (accessors) */ 01109 01114 long QSmf::getCurrentTime() 01115 { 01116 return d->m_CurrTime; 01117 } 01118 01123 long QSmf::getCurrentTempo() 01124 { 01125 return d->m_CurrTempo; 01126 } 01127 01132 long QSmf::getRealTime() 01133 { 01134 return d->m_RealTime; 01135 } 01136 01141 int QSmf::getDivision() 01142 { 01143 return d->m_Division; 01144 } 01145 01150 void QSmf::setDivision(int division) 01151 { 01152 d->m_Division = division; 01153 } 01154 01159 int QSmf::getTracks() 01160 { 01161 return d->m_Tracks; 01162 } 01163 01168 void QSmf::setTracks(int tracks) 01169 { 01170 d->m_Tracks = tracks; 01171 } 01172 01177 int QSmf::getFileFormat() 01178 { 01179 return d->m_fileFormat; 01180 } 01181 01186 void QSmf::setFileFormat(int fileFormat) 01187 { 01188 d->m_fileFormat = fileFormat; 01189 } 01190 01195 long QSmf::getFilePos() 01196 { 01197 return (long) d->m_IOStream->device()->pos(); 01198 } 01199 01205 QTextCodec* QSmf::getTextCodec() 01206 { 01207 return d->m_codec; 01208 } 01209 01217 void QSmf::setTextCodec(QTextCodec *codec) 01218 { 01219 d->m_codec = codec; 01220 } 01221 01222 }