drumstick  0.5.0
qsmf.cpp
Go to the documentation of this file.
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 }