24 #include <QDataStream>
47 class QSmf::QSmfPrivate {
57 m_OldCurrTempo(500000),
75 double m_DblOldRealtime;
78 quint64 m_OldCurrTempo;
79 quint64 m_OldRealTime;
80 quint64 m_OldCurrTime;
81 quint64 m_RevisedTime;
82 quint64 m_TempoChangeTime;
84 quint64 m_NumBytesWritten;
89 QDataStream *m_IOStream;
91 QList<QSmfRecTempo> m_TempoList;
108 d->m_TempoList.clear();
116 bool QSmf::endOfSmf()
118 return d->m_IOStream->atEnd();
125 quint8 QSmf::getByte()
140 void QSmf::putByte(quint8 value)
142 *d->m_IOStream << value;
143 d->m_NumBytesWritten++;
151 void QSmf::addTempo(quint64 tempo, quint64 time)
153 QSmfRecTempo tempoRec;
154 tempoRec.tempo = tempo;
155 tempoRec.time = time;
156 d->m_TempoList.append(tempoRec);
162 void QSmf::readHeader()
167 d->m_CurrTempo = 500000;
168 d->m_OldCurrTempo = 500000;
169 addTempo(d->m_CurrTempo, 0);
170 if (d->m_Interactive)
178 readExpected(
"MThd");
179 d->m_ToBeRead = read32bit();
180 d->m_fileFormat = read16bit();
181 d->m_Tracks = read16bit();
182 d->m_Division = read16bit();
187 while ((d->m_ToBeRead > 0) && !endOfSmf())
191 if (d->m_ToBeRead > 0)
193 SMFError(
"Unexpected end of input");
200 void QSmf::readTrack()
205 static const quint8 chantype[16] =
206 { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 };
215 quint64 delta_ticks, save_time, save_tempo;
217 sysexcontinue =
false;
219 if (d->m_Interactive)
221 d->m_ToBeRead = std::numeric_limits<unsigned long long>::max();
225 readExpected(
"MTrk");
226 d->m_ToBeRead = read32bit();
230 d->m_DblRealTime = 0;
231 d->m_DblOldRealtime = 0;
232 d->m_OldCurrTime = 0;
233 d->m_OldRealTime = 0;
234 d->m_CurrTempo = findTempo();
238 while (!endOfSmf() && (d->m_Interactive || d->m_ToBeRead > 0))
241 if (d->m_Interactive)
247 delta_ticks = unsigned(readVarLen());
248 d->m_RevisedTime = d->m_CurrTime;
249 d->m_CurrTime += delta_ticks;
250 while (d->m_RevisedTime < d->m_CurrTime)
252 save_time = d->m_RevisedTime;
253 save_tempo = d->m_CurrTempo;
254 d->m_CurrTempo = findTempo();
255 if (d->m_CurrTempo != d->m_OldCurrTempo)
257 d->m_OldCurrTempo = d->m_CurrTempo;
258 d->m_OldRealTime = d->m_RealTime;
259 if (d->m_RevisedTime != d->m_TempoChangeTime)
261 d->m_DblOldRealtime = d->m_DblRealTime;
262 d->m_OldCurrTime = save_time;
264 delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime,
265 quint16(d->m_Division), save_tempo);
266 d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0;
267 d->m_RealTime = quint64(0.5 + d->m_DblRealTime);
268 if (d->m_RevisedTime == d->m_TempoChangeTime)
270 d->m_OldCurrTime = d->m_RevisedTime;
271 d->m_DblOldRealtime = d->m_DblRealTime;
276 delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime,
277 quint16(d->m_Division), d->m_CurrTempo);
278 d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0;
279 d->m_RealTime = quint64(0.5 + d->m_DblRealTime);
287 SMFError(
"didn't find expected continuation of a SysEx");
295 SMFError(
"unexpected running status");
304 needed = chantype[status >> 4 & 0x0f];
317 channelMessage(status, c1, getByte());
321 channelMessage(status, c1, 0);
331 lookfor = quint64(readVarLen());
332 lookfor = d->m_ToBeRead - lookfor;
334 while ((d->m_ToBeRead > lookfor) && !endOfSmf())
341 lookfor = quint64(readVarLen());
342 lookfor = d->m_ToBeRead - lookfor;
345 while ((d->m_ToBeRead > lookfor) && !endOfSmf())
356 sysexcontinue =
true;
360 lookfor = readVarLen();
361 lookfor = d->m_ToBeRead - lookfor;
366 while ((d->m_ToBeRead > lookfor) && !endOfSmf())
376 sysexcontinue =
false;
381 badByte(c, d->m_IOStream->device()->pos() - 1);
384 if ((d->m_ToBeRead > lookfor) && endOfSmf())
386 SMFError(
"Unexpected end of input");
399 for ( i = d->m_Tracks; (i > 0) && !endOfSmf(); i--)
412 void QSmf::SMFWrite()
416 writeHeaderChunk(d->m_fileFormat, d->m_Tracks, d->m_Division);
418 if (d->m_fileFormat == 1)
422 for (i = 0; i < d->m_Tracks; ++i)
434 d->m_IOStream = stream;
444 QFile file(fileName);
445 file.open(QIODevice::ReadOnly);
446 QDataStream ds(&file);
457 d->m_IOStream = stream;
467 QFile file(fileName);
468 file.open(QIODevice::WriteOnly);
469 QDataStream ds(&file);
480 void QSmf::writeHeaderChunk(
int format,
int ntracks,
int division)
484 write16bit(quint16(format));
485 write16bit(quint16(ntracks));
486 write16bit(quint16(division));
493 void QSmf::writeTrackChunk(
int track)
503 offset = d->m_IOStream->device()->pos();
505 write32bit(trklength);
506 d->m_NumBytesWritten = 0;
510 place_marker = d->m_IOStream->device()->pos();
511 d->m_IOStream->device()->seek(offset);
512 trklength = d->m_NumBytesWritten;
514 write32bit(trklength);
515 d->m_IOStream->device()->seek(place_marker);
526 writeVarLen(deltaTime);
528 putByte(d->m_LastStatus);
530 writeVarLen(data.size());
531 foreach(
char byte, data)
543 writeVarLen(deltaTime);
547 if (d->m_codec ==
nullptr)
548 lcldata = data.toLatin1();
550 lcldata = d->m_codec->fromUnicode(data);
551 writeVarLen(lcldata.length());
552 foreach(
char byte, lcldata)
565 writeVarLen(deltaTime);
579 writeVarLen(deltaTime);
593 const QByteArray& data)
597 writeVarLen(deltaTime);
607 SMFError(
"error: MIDI channel greater than 16");
611 if (d->m_LastStatus != c)
623 j = (data[0] == type ? 1 : 0);
624 for (i = j; i < data.size(); ++i)
640 writeVarLen(deltaTime);
643 SMFError(
"error: Wrong method for a system exclusive event");
647 SMFError(
"error: MIDI channel greater than 16");
650 if (d->m_LastStatus != c)
669 writeVarLen(deltaTime);
672 SMFError(
"error: Wrong method for a system exclusive event");
676 SMFError(
"error: MIDI channel greater than 16");
679 if (d->m_LastStatus != c)
697 unsigned int i, j, size;
699 writeVarLen(quint64(deltaTime));
702 SMFError(
"error: type should be system exclusive");
707 size = unsigned(len);
712 j = (c == type ? 1 : 0);
713 for (i = j; i < unsigned(len); ++i)
715 putByte(quint8(data[i]));
726 writeVarLen(deltaTime);
728 putByte(d->m_LastStatus);
731 putByte((seqnum >> 8) & 0xff);
732 putByte(seqnum & 0xff);
742 writeVarLen(deltaTime);
746 putByte((tempo >> 16) & 0xff);
747 putByte((tempo >> 8) & 0xff);
748 putByte(tempo & 0xff);
758 long us_tempo = 60000000l / tempo;
772 writeVarLen(deltaTime);
790 writeVarLen(quint64(deltaTime));
794 putByte(quint8(tone));
795 putByte(mode & 0x01);
802 void QSmf::writeVarLen(quint64 value)
806 buffer = value & 0x7f;
807 while ((value >>= 7) > 0)
811 buffer += (value & 0x7f);
815 putByte(buffer & 0xff);
825 void QSmf::write32bit(quint32 data)
827 putByte((data >> 24) & 0xff);
828 putByte((data >> 16) & 0xff);
829 putByte((data >> 8) & 0xff);
830 putByte(data & 0xff);
833 void QSmf::write16bit(quint16 data)
835 putByte((data >> 8) & 0xff);
836 putByte(data & 0xff);
839 quint16 QSmf::to16bit(quint8 c1, quint8 c2)
842 value = quint16(c1 << 8);
847 quint32 QSmf::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
850 value = unsigned(c1 << 24);
851 value += unsigned(c2 << 16);
852 value += unsigned(c3 << 8);
857 quint16 QSmf::read16bit()
862 return to16bit(c1, c2);
865 quint32 QSmf::read32bit()
867 quint8 c1, c2, c3, c4;
872 return to32bit(c1, c2, c3, c4);
875 long QSmf::readVarLen()
888 value = (value << 7) + (c & 0x7f);
889 }
while ((c & 0x80) != 0);
894 void QSmf::readExpected(
const QString& s)
898 for (j = 0; j < s.length(); ++j)
901 if (QChar(b) != s[j])
903 SMFError(QString(
"Invalid (%1) SMF format at %2").arg(b, 0, 16).arg(d->m_IOStream->device()->pos()));
909 quint64 QSmf::findTempo()
911 quint64 result, old_tempo, new_tempo;
912 QSmfRecTempo rec = d->m_TempoList.last();
913 old_tempo = d->m_CurrTempo;
914 new_tempo = d->m_CurrTempo;
915 QList<QSmfRecTempo>::Iterator it;
916 for( it = d->m_TempoList.begin(); it != d->m_TempoList.end(); ++it )
919 if (rec.time <= d->m_CurrTime)
921 old_tempo = rec.tempo;
923 new_tempo = rec.tempo;
924 if (rec.time > d->m_RevisedTime)
929 if ((rec.time <= d->m_RevisedTime) || (rec.time > d->m_CurrTime))
931 d->m_RevisedTime = d->m_CurrTime;
936 d->m_RevisedTime = rec.time;
937 d->m_TempoChangeTime = d->m_RevisedTime;
946 double QSmf::ticksToSecs(quint64 ticks, quint16 division, quint64 tempo)
950 double smpte_resolution;
954 result = double(ticks * tempo)/(division * 1000000.0);
958 smpte_format = upperByte(division);
959 smpte_resolution = lowerByte(division);
960 result = double(ticks)/(smpte_format * smpte_resolution
966 void QSmf::SMFError(
const QString& s)
971 void QSmf::channelMessage(quint8 status, quint8 c1, quint8 c2)
978 SMFError(QString(
"ChannelMessage with bad c1 = %1").arg(c1));
983 SMFError(QString(
"ChannelMessage with bad c2 = %1").arg(c2));
1007 k = c1 + (c2 << 7) - 8192;
1011 SMFError(QString(
"Invalid MIDI status %1. Unhandled event").arg(status));
1016 void QSmf::metaEvent(quint8 b)
1019 QByteArray m(d->m_MsgBuff);
1034 if (d->m_codec ==
nullptr)
1037 s = d->m_codec->toUnicode(m);
1051 d->m_CurrTempo = to32bit(0, m[0], m[1], m[2]);
1053 rec = d->m_TempoList.last();
1054 if (rec.tempo == d->m_CurrTempo)
1058 if (rec.time > d->m_CurrTime)
1062 addTempo(d->m_CurrTempo, d->m_CurrTime);
1085 QByteArray varr(d->m_MsgBuff);
1089 void QSmf::badByte(quint8 b,
int p)
1091 SMFError(QString(
"Unexpected byte (%1) at %2").arg(b, 2, 16).arg(p));
1094 quint8 QSmf::lowerByte(quint16 x)
1099 quint8 QSmf::upperByte(quint16 x)
1101 return ((x >> 8) & 0xff);
1104 void QSmf::msgInit()
1106 d->m_MsgBuff.truncate(0);
1109 void QSmf::msgAdd(quint8 b)
1111 int s = d->m_MsgBuff.size();
1112 d->m_MsgBuff.resize(s + 1);
1113 d->m_MsgBuff[s] = b;
1124 return d->m_CurrTime;
1133 return d->m_CurrTempo;
1142 return d->m_RealTime;
1151 return d->m_Division;
1160 d->m_Division = division;
1178 d->m_Tracks = tracks;
1187 return d->m_fileFormat;
1196 d->m_fileFormat = fileFormat;
1205 return long(d->m_IOStream->device()->pos());