drumstick  0.5.0
qsmf.cpp
Go to the documentation of this file.
1 /*
2  Standard MIDI File component
3  Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5  Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee
6 
7  This library is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 
22 #include "qsmf.h"
23 #include <limits>
24 #include <QList>
25 #include <QFile>
26 #include <QDataStream>
27 #include <QTextCodec>
28 
34 namespace drumstick {
35 
48 class QSmf::QSmfPrivate {
49 public:
50  QSmfPrivate():
51  m_Interactive(false),
52  m_CurrTime(0),
53  m_RealTime(0),
54  m_DblRealTime(0),
55  m_DblOldRealtime(0),
56  m_Division(96),
57  m_CurrTempo(500000),
58  m_OldCurrTempo(500000),
59  m_OldRealTime(0),
60  m_OldCurrTime(0),
61  m_RevisedTime(0),
62  m_TempoChangeTime(0),
63  m_ToBeRead(0),
64  m_NumBytesWritten(0),
65  m_Tracks(0),
66  m_fileFormat(0),
67  m_LastStatus(0),
68  m_codec(0),
69  m_IOStream(0)
70  { }
71 
72  bool m_Interactive;
73  quint64 m_CurrTime;
74  quint64 m_RealTime;
75  double m_DblRealTime;
76  double m_DblOldRealtime;
77  int m_Division;
78  quint64 m_CurrTempo;
79  quint64 m_OldCurrTempo;
80  quint64 m_OldRealTime;
81  quint64 m_OldCurrTime;
82  quint64 m_RevisedTime;
83  quint64 m_TempoChangeTime;
84  quint64 m_ToBeRead;
85  quint64 m_NumBytesWritten;
86  int m_Tracks;
87  int m_fileFormat;
88  int m_LastStatus;
89  QTextCodec *m_codec;
90  QDataStream *m_IOStream;
91  QByteArray m_MsgBuff;
92  QList<QSmfRecTempo> m_TempoList;
93 };
94 
99 QSmf::QSmf(QObject * parent) :
100  QObject(parent),
101  d(new QSmfPrivate)
102 { }
103 
108 {
109  d->m_TempoList.clear();
110  delete d;
111 }
112 
117 bool QSmf::endOfSmf()
118 {
119  return d->m_IOStream->atEnd();
120 }
121 
126 quint8 QSmf::getByte()
127 {
128  quint8 b = 0;
129  if (!d->m_IOStream->atEnd())
130  {
131  *d->m_IOStream >> b;
132  d->m_ToBeRead--;
133  }
134  return b;
135 }
136 
141 void QSmf::putByte(quint8 value)
142 {
143  *d->m_IOStream << value;
144  d->m_NumBytesWritten++;
145 }
146 
152 void QSmf::addTempo(quint64 tempo, quint64 time)
153 {
154  QSmfRecTempo tempoRec;
155  tempoRec.tempo = tempo;
156  tempoRec.time = time;
157  d->m_TempoList.append(tempoRec);
158 }
159 
163 void QSmf::readHeader()
164 {
165  d->m_CurrTime = 0;
166  d->m_RealTime = 0;
167  d->m_Division = 96;
168  d->m_CurrTempo = 500000;
169  d->m_OldCurrTempo = 500000;
170  addTempo(d->m_CurrTempo, 0);
171  if (d->m_Interactive)
172  {
173  d->m_fileFormat= 0;
174  d->m_Tracks = 1;
175  d->m_Division = 96;
176  }
177  else
178  {
179  readExpected("MThd");
180  d->m_ToBeRead = read32bit();
181  d->m_fileFormat = read16bit();
182  d->m_Tracks = read16bit();
183  d->m_Division = read16bit();
184  }
185  emit signalSMFHeader(d->m_fileFormat, d->m_Tracks, d->m_Division);
186 
187  /* flush any extra stuff, in case the length of header is not */
188  while ((d->m_ToBeRead > 0) && !endOfSmf())
189  {
190  getByte();
191  }
192 }
193 
197 void QSmf::readTrack()
198 {
199  /* This array is indexed by the high half of a status byte. It's
200  value is either the number of bytes needed (1 or 2) for a channel
201  message, or 0 (meaning it's not a channel message). */
202  static const quint8 chantype[16] =
203  { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 };
204 
205  quint64 lookfor;
206  quint8 c, c1, type;
207  bool sysexcontinue; // 1 if last message was an unfinished SysEx
208  bool running; // 1 when running status used
209  quint8 status; // status value (e.g. 0x90==note-on)
210  int needed;
211  double delta_secs;
212  quint64 delta_ticks, save_time, save_tempo;
213 
214  sysexcontinue = false;
215  status = 0;
216  if (d->m_Interactive)
217  {
218  d->m_ToBeRead = std::numeric_limits<unsigned long long>::max();
219  }
220  else
221  {
222  readExpected("MTrk");
223  d->m_ToBeRead = read32bit();
224  }
225  d->m_CurrTime = 0;
226  d->m_RealTime = 0;
227  d->m_DblRealTime = 0;
228  d->m_DblOldRealtime = 0;
229  d->m_OldCurrTime = 0;
230  d->m_OldRealTime = 0;
231  d->m_CurrTempo = findTempo();
232 
233  emit signalSMFTrackStart();
234 
235  while (!endOfSmf() && (d->m_Interactive || d->m_ToBeRead > 0))
236  {
237  if (d->m_Interactive)
238  {
239  d->m_CurrTime++;
240  }
241  else
242  {
243  delta_ticks = readVarLen();
244  d->m_RevisedTime = d->m_CurrTime;
245  d->m_CurrTime += delta_ticks;
246  while (d->m_RevisedTime < d->m_CurrTime)
247  {
248  save_time = d->m_RevisedTime;
249  save_tempo = d->m_CurrTempo;
250  d->m_CurrTempo = findTempo();
251  if (d->m_CurrTempo != d->m_OldCurrTempo)
252  {
253  d->m_OldCurrTempo = d->m_CurrTempo;
254  d->m_OldRealTime = d->m_RealTime;
255  if (d->m_RevisedTime != d->m_TempoChangeTime)
256  {
257  d->m_DblOldRealtime = d->m_DblRealTime;
258  d->m_OldCurrTime = save_time;
259  }
260  delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime,
261  d->m_Division, save_tempo);
262  d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0;
263  d->m_RealTime = static_cast<quint64>(0.5 + d->m_DblRealTime);
264  if (d->m_RevisedTime == d->m_TempoChangeTime)
265  {
266  d->m_OldCurrTime = d->m_RevisedTime;
267  d->m_DblOldRealtime = d->m_DblRealTime;
268  }
269  }
270  else
271  {
272  delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime,
273  d->m_Division, d->m_CurrTempo);
274  d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0;
275  d->m_RealTime = static_cast<quint64>(0.5 + d->m_DblRealTime);
276  }
277  }
278  }
279 
280  c = getByte();
281  if (sysexcontinue && (c != end_of_sysex))
282  {
283  SMFError("didn't find expected continuation of a SysEx");
284  }
285  if (c < 0xf8)
286  {
287  if ((c & 0x80) == 0)
288  {
289  if (status == 0)
290  {
291  SMFError("unexpected running status");
292  }
293  running = true;
294  }
295  else
296  {
297  status = c;
298  running = false;
299  }
300  needed = chantype[status >> 4 & 0x0f];
301  if (needed != 0)
302  {
303  if (running)
304  {
305  c1 = c;
306  }
307  else
308  {
309  c1 = getByte();
310  }
311  if (needed > 1)
312  {
313  channelMessage(status, c1, getByte());
314  }
315  else
316  {
317  channelMessage(status, c1, 0);
318  }
319  continue;
320  }
321  }
322 
323  switch (c)
324  {
325  case meta_event:
326  type = getByte();
327  lookfor = readVarLen();
328  lookfor = d->m_ToBeRead - lookfor;
329  msgInit();
330  while (d->m_ToBeRead > lookfor)
331  {
332  msgAdd(getByte());
333  }
334  metaEvent(type);
335  break;
336  case system_exclusive:
337  lookfor = readVarLen();
338  lookfor = d->m_ToBeRead - lookfor;
339  msgInit();
340  msgAdd(system_exclusive);
341  while (d->m_ToBeRead > lookfor)
342  {
343  c = getByte();
344  msgAdd(c);
345  }
346  if (c == end_of_sysex)
347  {
348  sysEx();
349  }
350  else
351  {
352  sysexcontinue = true;
353  }
354  break;
355  case end_of_sysex:
356  lookfor = readVarLen();
357  lookfor = d->m_ToBeRead - lookfor;
358  if (!sysexcontinue)
359  {
360  msgInit();
361  }
362  while (d->m_ToBeRead > lookfor)
363  {
364  c = getByte();
365  msgAdd(c);
366  }
367  if (sysexcontinue)
368  {
369  if (c == end_of_sysex)
370  {
371  sysEx();
372  sysexcontinue = false;
373  }
374  }
375  break;
376  default:
377  badByte(c, d->m_IOStream->device()->pos() - 1);
378  break;
379  }
380  }
381  emit signalSMFTrackEnd();
382 }
383 
387 void QSmf::SMFRead()
388 {
389  int i;
390  readHeader();
391  for ( i = d->m_Tracks; (i > 0) && !endOfSmf(); i--)
392  {
393  readTrack();
394  }
395 }
396 
404 void QSmf::SMFWrite()
405 {
406  int i;
407  d->m_LastStatus = 0;
408  writeHeaderChunk(d->m_fileFormat, d->m_Tracks, d->m_Division);
409  d->m_LastStatus = 0;
410  if (d->m_fileFormat == 1)
411  {
413  }
414  for (i = 0; i < d->m_Tracks; ++i)
415  {
416  writeTrackChunk(i);
417  }
418 }
419 
424 void QSmf::readFromStream(QDataStream *stream)
425 {
426  d->m_IOStream = stream;
427  SMFRead();
428 }
429 
434 void QSmf::readFromFile(const QString& fileName)
435 {
436  QFile file(fileName);
437  file.open(QIODevice::ReadOnly);
438  QDataStream ds(&file);
439  readFromStream(&ds);
440  file.close();
441 }
442 
447 void QSmf::writeToStream(QDataStream *stream)
448 {
449  d->m_IOStream = stream;
450  SMFWrite();
451 }
452 
457 void QSmf::writeToFile(const QString& fileName)
458 {
459  QFile file(fileName);
460  file.open(QIODevice::WriteOnly);
461  QDataStream ds(&file);
462  writeToStream(&ds);
463  file.close();
464 }
465 
472 void QSmf::writeHeaderChunk(int format, int ntracks, int division)
473 {
474  write32bit(MThd);
475  write32bit(6);
476  write16bit(format);
477  write16bit(ntracks);
478  write16bit(division);
479 }
480 
485 void QSmf::writeTrackChunk(int track)
486 {
487  quint32 trkhdr;
488  quint32 trklength;
489  qint64 offset;
490  qint64 place_marker;
491 
492  d->m_LastStatus = 0;
493  trkhdr = MTrk;
494  trklength = 0;
495  offset = d->m_IOStream->device()->pos();
496  write32bit(trkhdr);
497  write32bit(trklength);
498  d->m_NumBytesWritten = 0;
499 
500  emit signalSMFWriteTrack(track);
501 
502  place_marker = d->m_IOStream->device()->pos();
503  d->m_IOStream->device()->seek(offset);
504  trklength = d->m_NumBytesWritten;
505  write32bit(trkhdr);
506  write32bit(trklength);
507  d->m_IOStream->device()->seek(place_marker);
508 }
509 
516 void QSmf::writeMetaEvent(long deltaTime, int type, const QByteArray& data)
517 {
518  writeVarLen(deltaTime);
519  d->m_LastStatus = meta_event;
520  putByte(d->m_LastStatus);
521  putByte(type);
522  writeVarLen(data.size());
523  foreach(char byte, data)
524  putByte(byte);
525 }
526 
533 void QSmf::writeMetaEvent(long deltaTime, int type, const QString& data)
534 {
535  writeVarLen(deltaTime);
536  putByte(d->m_LastStatus = meta_event);
537  putByte(type);
538  QByteArray lcldata;
539  if (d->m_codec == NULL)
540  lcldata = data.toLatin1();
541  else
542  lcldata = d->m_codec->fromUnicode(data);
543  writeVarLen(lcldata.length());
544  foreach(char byte, lcldata)
545  putByte(byte);
546 }
547 
555 void QSmf::writeMetaEvent(long deltaTime, int type, int data)
556 {
557  writeVarLen(deltaTime);
558  putByte(d->m_LastStatus = meta_event);
559  putByte(type);
560  putByte(1);
561  putByte(data);
562 }
563 
569 void QSmf::writeMetaEvent(long deltaTime, int type)
570 {
571  writeVarLen(deltaTime);
572  putByte(d->m_LastStatus = meta_event);
573  putByte(type);
574  putByte(0);
575 }
576 
584 void QSmf::writeMidiEvent(long deltaTime, int type, int chan,
585  const QByteArray& data)
586 {
587  int i, j, size;
588  quint8 c;
589  writeVarLen(deltaTime);
590  if ((type == system_exclusive) || (type == end_of_sysex))
591  {
592  c = type;
593  d->m_LastStatus = 0;
594  }
595  else
596  {
597  if (chan > 15)
598  {
599  SMFError("error: MIDI channel greater than 16");
600  }
601  c = type | chan;
602  }
603  if (d->m_LastStatus != c)
604  {
605  d->m_LastStatus = c;
606  putByte(c);
607  }
608  if (type == system_exclusive || type == end_of_sysex)
609  {
610  size = data.size();
611  if (data[0] == type)
612  --size;
613  writeVarLen(size);
614  }
615  j = (data[0] == type ? 1 : 0);
616  for (i = j; i < data.size(); ++i)
617  {
618  putByte(data[i]);
619  }
620 }
621 
629 void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1)
630 {
631  quint8 c;
632  writeVarLen(deltaTime);
633  if ((type == system_exclusive) || (type == end_of_sysex))
634  {
635  SMFError("error: Wrong method for a system exclusive event");
636  }
637  if (chan > 15)
638  {
639  SMFError("error: MIDI channel greater than 16");
640  }
641  c = type | chan;
642  if (d->m_LastStatus != c)
643  {
644  d->m_LastStatus = c;
645  putByte(c);
646  }
647  putByte(b1);
648 }
649 
658 void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1, int b2)
659 {
660  quint8 c;
661  writeVarLen(deltaTime);
662  if ((type == system_exclusive) || (type == end_of_sysex))
663  {
664  SMFError("error: Wrong method for a system exclusive event");
665  }
666  if (chan > 15)
667  {
668  SMFError("error: MIDI channel greater than 16");
669  }
670  c = type | chan;
671  if (d->m_LastStatus != c)
672  {
673  d->m_LastStatus = c;
674  putByte(c);
675  }
676  putByte(b1);
677  putByte(b2);
678 }
679 
687 void QSmf::writeMidiEvent(long deltaTime, int type, long len, char* data)
688 {
689  unsigned int i, j, size;
690  quint8 c;
691  writeVarLen(deltaTime);
692  if ((type != system_exclusive) && (type != end_of_sysex))
693  {
694  SMFError("error: type should be system exclusive");
695  }
696  d->m_LastStatus = 0;
697  c = type;
698  putByte(c);
699  size = len;
700  c = (unsigned)data[0];
701  if (c == type)
702  --size;
703  writeVarLen(size);
704  j = (c == type ? 1 : 0);
705  for (i = j; i < (unsigned)len; ++i)
706  {
707  putByte(data[i]);
708  }
709 }
710 
716 void QSmf::writeSequenceNumber(long deltaTime, int seqnum)
717 {
718  writeVarLen(deltaTime);
719  d->m_LastStatus = meta_event;
720  putByte(d->m_LastStatus);
721  putByte(sequence_number);
722  putByte(2);
723  putByte((seqnum >> 8) & 0xff);
724  putByte(seqnum & 0xff);
725 }
726 
732 void QSmf::writeTempo(long deltaTime, long tempo)
733 {
734  writeVarLen(deltaTime);
735  putByte(d->m_LastStatus = meta_event);
736  putByte(set_tempo);
737  putByte(3);
738  putByte((tempo >> 16) & 0xff);
739  putByte((tempo >> 8) & 0xff);
740  putByte(tempo & 0xff);
741 }
742 
748 void QSmf::writeBpmTempo(long deltaTime, int tempo)
749 {
750  long us_tempo = 60000000l / tempo;
751  writeTempo(deltaTime, us_tempo);
752 }
753 
762 void QSmf::writeTimeSignature(long deltaTime, int num, int den, int cc, int bb)
763 {
764  writeVarLen(deltaTime);
765  putByte(d->m_LastStatus = meta_event);
766  putByte(time_signature);
767  putByte(4);
768  putByte(num & 0xff);
769  putByte(den & 0xff);
770  putByte(cc & 0xff);
771  putByte(bb & 0xff);
772 }
773 
780 void QSmf::writeKeySignature(long deltaTime, int tone, int mode)
781 {
782  writeVarLen(deltaTime);
783  putByte(d->m_LastStatus = meta_event);
784  putByte(key_signature);
785  putByte(2);
786  putByte((char)tone);
787  putByte(mode & 0x01);
788 }
789 
794 void QSmf::writeVarLen(quint64 value)
795 {
796  quint64 buffer;
797 
798  buffer = value & 0x7f;
799  while ((value >>= 7) > 0)
800  {
801  buffer <<= 8;
802  buffer |= 0x80;
803  buffer += (value & 0x7f);
804  }
805  while (true)
806  {
807  putByte(buffer & 0xff);
808  if (buffer & 0x80)
809  buffer >>= 8;
810  else
811  break;
812  }
813 }
814 
815 /* These routines are used to make sure that the byte order of
816  the various data types remains constant between machines. */
817 void QSmf::write32bit(quint32 data)
818 {
819  putByte((data >> 24) & 0xff);
820  putByte((data >> 16) & 0xff);
821  putByte((data >> 8) & 0xff);
822  putByte(data & 0xff);
823 }
824 
825 void QSmf::write16bit(quint16 data)
826 {
827  putByte((data >> 8) & 0xff);
828  putByte(data & 0xff);
829 }
830 
831 quint16 QSmf::to16bit(quint8 c1, quint8 c2)
832 {
833  quint16 value;
834  value = (c1 << 8);
835  value += c2;
836  return value;
837 }
838 
839 quint32 QSmf::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
840 {
841  quint32 value;
842  value = (c1 << 24);
843  value += (c2 << 16);
844  value += (c3 << 8);
845  value += c4;
846  return value;
847 }
848 
849 quint16 QSmf::read16bit()
850 {
851  quint8 c1, c2;
852  c1 = getByte();
853  c2 = getByte();
854  return to16bit(c1, c2);
855 }
856 
857 quint32 QSmf::read32bit()
858 {
859  quint8 c1, c2, c3, c4;
860  c1 = getByte();
861  c2 = getByte();
862  c3 = getByte();
863  c4 = getByte();
864  return to32bit(c1, c2, c3, c4);
865 }
866 
867 long QSmf::readVarLen()
868 {
869  long value;
870  quint8 c;
871 
872  c = getByte();
873  value = c;
874  if ((c & 0x80) != 0)
875  {
876  value &= 0x7f;
877  do
878  {
879  c = getByte();
880  value = (value << 7) + (c & 0x7f);
881  } while ((c & 0x80) != 0);
882  }
883  return value;
884 }
885 
886 void QSmf::readExpected(const QString& s)
887 {
888  int j;
889  quint8 b;
890  for (j = 0; j < s.length(); ++j)
891  {
892  b = getByte();
893  if (QChar(b) != s[j])
894  {
895  SMFError(QString("Invalid (%1) SMF format at %2").arg(b, 0, 16).arg(d->m_IOStream->device()->pos()));
896  break;
897  }
898  }
899 }
900 
901 quint64 QSmf::findTempo()
902 {
903  quint64 result, old_tempo, new_tempo;
904  QSmfRecTempo rec = d->m_TempoList.last();
905  old_tempo = d->m_CurrTempo;
906  new_tempo = d->m_CurrTempo;
907  QList<QSmfRecTempo>::Iterator it;
908  for( it = d->m_TempoList.begin(); it != d->m_TempoList.end(); ++it )
909  {
910  rec = (*it);
911  if (rec.time <= d->m_CurrTime)
912  {
913  old_tempo = rec.tempo;
914  }
915  new_tempo = rec.tempo;
916  if (rec.time > d->m_RevisedTime)
917  {
918  break;
919  }
920  }
921  if ((rec.time <= d->m_RevisedTime) || (rec.time > d->m_CurrTime))
922  {
923  d->m_RevisedTime = d->m_CurrTime;
924  result = old_tempo;
925  }
926  else
927  {
928  d->m_RevisedTime = rec.time;
929  d->m_TempoChangeTime = d->m_RevisedTime;
930  result = new_tempo;
931  }
932  return result;
933 }
934 
935 /* This routine converts delta times in ticks into seconds. The
936  else statement is needed because the formula is different for tracks
937  based on notes and tracks based on SMPTE times. */
938 double QSmf::ticksToSecs(quint64 ticks, quint16 division, quint64 tempo)
939 {
940  double result;
941  double smpte_format;
942  double smpte_resolution;
943 
944  if (division > 0)
945  {
946  result = static_cast<double>(ticks * tempo)/(division * 1000000.0);
947  }
948  else
949  {
950  smpte_format = upperByte(division);
951  smpte_resolution = lowerByte(division);
952  result = static_cast<double>(ticks)/(smpte_format * smpte_resolution
953  * 1000000.0);
954  }
955  return result;
956 }
957 
958 void QSmf::SMFError(const QString& s)
959 {
960  emit signalSMFError(s);
961 }
962 
963 void QSmf::channelMessage(quint8 status, quint8 c1, quint8 c2)
964 {
965  quint8 chan;
966  int k;
967  chan = status & midi_channel_mask;
968  if (c1 > 127)
969  {
970  SMFError(QString("ChannelMessage with bad c1 = %1").arg(c1));
971  //c1 &= 127;
972  }
973  if (c2 > 127)
974  {
975  SMFError(QString("ChannelMessage with bad c2 = %1").arg(c2));
976  //c2 &= 127;
977  }
978  switch (status & midi_command_mask)
979  {
980  case note_off:
981  emit signalSMFNoteOff(chan, c1, c2);
982  break;
983  case note_on:
984  emit signalSMFNoteOn(chan, c1, c2);
985  break;
986  case poly_aftertouch:
987  emit signalSMFKeyPress(chan, c1, c2);
988  break;
989  case control_change:
990  emit signalSMFCtlChange(chan, c1, c2);
991  break;
992  case program_chng:
993  emit signalSMFProgram(chan, c1);
994  break;
995  case channel_aftertouch:
996  emit signalSMFChanPress(chan, c1);
997  break;
998  case pitch_wheel:
999  k = c1 + (c2 << 7) - 8192;
1000  emit signalSMFPitchBend(chan, k);
1001  break;
1002  default:
1003  SMFError(QString("Invalid MIDI status %1. Unhandled event").arg(status));
1004  break;
1005  }
1006 }
1007 
1008 void QSmf::metaEvent(quint8 b)
1009 {
1010  QSmfRecTempo rec;
1011  QByteArray m(d->m_MsgBuff);
1012 
1013  switch (b)
1014  {
1015  case sequence_number:
1016  emit signalSMFSequenceNum(to16bit(m[0], m[1]));
1017  break;
1018  case text_event:
1019  case copyright_notice:
1020  case sequence_name:
1021  case instrument_name:
1022  case lyric:
1023  case marker:
1024  case cue_point: {
1025  QString s;
1026  if (d->m_codec == NULL)
1027  s = QString(m);
1028  else
1029  s = d->m_codec->toUnicode(m);
1030  emit signalSMFText(b, s);
1031  }
1032  break;
1033  case forced_channel:
1034  emit signalSMFforcedChannel(m[0]);
1035  break;
1036  case forced_port:
1037  emit signalSMFforcedPort(m[0]);
1038  break;
1039  case end_of_track:
1040  emit signalSMFendOfTrack();
1041  break;
1042  case set_tempo:
1043  d->m_CurrTempo = to32bit(0, m[0], m[1], m[2]);
1044  emit signalSMFTempo(d->m_CurrTempo);
1045  rec = d->m_TempoList.last();
1046  if (rec.tempo == d->m_CurrTempo)
1047  {
1048  return;
1049  }
1050  if (rec.time > d->m_CurrTime)
1051  {
1052  return;
1053  }
1054  addTempo(d->m_CurrTempo, d->m_CurrTime);
1055  break;
1056  case smpte_offset:
1057  emit signalSMFSmpte(m[0], m[1], m[2], m[3], m[4]);
1058  break;
1059  case time_signature:
1060  emit signalSMFTimeSig(m[0], m[1], m[2], m[3]);
1061  break;
1062  case key_signature:
1063  emit signalSMFKeySig(m[0], m[1]);
1064  break;
1065  case sequencer_specific:
1066  emit signalSMFSeqSpecific(m);
1067  break;
1068  default:
1069  emit signalSMFMetaUnregistered(b, m);
1070  break;
1071  }
1072  emit signalSMFMetaMisc(b, m);
1073 }
1074 
1075 void QSmf::sysEx()
1076 {
1077  QByteArray varr(d->m_MsgBuff);
1078  emit signalSMFSysex(varr);
1079 }
1080 
1081 void QSmf::badByte(quint8 b, int p)
1082 {
1083  SMFError(QString("Unexpected byte (%1) at %2").arg(b, 2, 16).arg(p));
1084 }
1085 
1086 quint8 QSmf::lowerByte(quint16 x)
1087 {
1088  return (x & 0xff);
1089 }
1090 
1091 quint8 QSmf::upperByte(quint16 x)
1092 {
1093  return ((x >> 8) & 0xff);
1094 }
1095 
1096 void QSmf::msgInit()
1097 {
1098  d->m_MsgBuff.truncate(0);
1099 }
1100 
1101 void QSmf::msgAdd(quint8 b)
1102 {
1103  int s = d->m_MsgBuff.size();
1104  d->m_MsgBuff.resize(s + 1);
1105  d->m_MsgBuff[s] = b;
1106 }
1107 
1108 /* public properties (accessors) */
1109 
1115 {
1116  return d->m_CurrTime;
1117 }
1118 
1124 {
1125  return d->m_CurrTempo;
1126 }
1127 
1133 {
1134  return d->m_RealTime;
1135 }
1136 
1142 {
1143  return d->m_Division;
1144 }
1145 
1150 void QSmf::setDivision(int division)
1151 {
1152  d->m_Division = division;
1153 }
1154 
1160 {
1161  return d->m_Tracks;
1162 }
1163 
1168 void QSmf::setTracks(int tracks)
1169 {
1170  d->m_Tracks = tracks;
1171 }
1172 
1178 {
1179  return d->m_fileFormat;
1180 }
1181 
1186 void QSmf::setFileFormat(int fileFormat)
1187 {
1188  d->m_fileFormat = fileFormat;
1189 }
1190 
1196 {
1197  return (long) d->m_IOStream->device()->pos();
1198 }
1199 
1205 QTextCodec* QSmf::getTextCodec()
1206 {
1207  return d->m_codec;
1208 }
1209 
1217 void QSmf::setTextCodec(QTextCodec *codec)
1218 {
1219  d->m_codec = codec;
1220 }
1221 
1222 }
void signalSMFNoteOff(int chan, int pitch, int vol)
Emitted after reading a Note Off message.
void signalSMFSeqSpecific(const QByteArray &data)
Emitted after reading a Sequencer specific message.
long getRealTime()
Gets the real time in seconds.
Definition: qsmf.cpp:1132
#define forced_port
SMF Forced MIDI port.
Definition: qsmf.h:53
void writeTempo(long deltaTime, long tempo)
Writes a Tempo change message.
Definition: qsmf.cpp:732
#define midi_command_mask
Mask to extract the command from the status byte.
Definition: qsmf.h:72
void signalSMFHeader(int format, int ntrks, int division)
Emitted after reading a SMF header.
#define forced_channel
SMF Forced MIDI channel.
Definition: qsmf.h:52
void signalSMFforcedPort(int port)
Emitted after reading a Forced port message.
void writeToStream(QDataStream *stream)
Writes a SMF stream.
Definition: qsmf.cpp:447
void setTextCodec(QTextCodec *codec)
Sets the text codec for text meta-events.
Definition: qsmf.cpp:1217
#define marker
SMF Marker.
Definition: qsmf.h:50
#define channel_aftertouch
MIDI event Channel after-touch.
Definition: qsmf.h:67
long getCurrentTime()
Gets the current time in ticks.
Definition: qsmf.cpp:1114
void signalSMFText(int typ, const QString &data)
Emitted after reading a SMF text message.
The QObject class is the base class of all Qt objects.
void signalSMFTrackStart()
Emitted after reading a track prefix.
void writeTimeSignature(long deltaTime, int num, int den, int cc, int bb)
Writes a Time Signature message.
Definition: qsmf.cpp:762
#define key_signature
SMF Key signature.
Definition: qsmf.h:58
void signalSMFforcedChannel(int channel)
Emitted after reading a Forced channel message.
QSmf(QObject *parent=0)
Constructor.
Definition: qsmf.cpp:99
int getTracks()
Gets the number of tracks.
Definition: qsmf.cpp:1159
void signalSMFSmpte(int b0, int b1, int b2, int b3, int b4)
Emitted after reading a SMPT offset message.
void signalSMFWriteTrack(int track)
Emitted to request the user to write a track.
long getFilePos()
Gets the position in the SMF stream.
Definition: qsmf.cpp:1195
void setTracks(int tracks)
Sets the number of tracks.
Definition: qsmf.cpp:1168
#define control_change
MIDI event Control change.
Definition: qsmf.h:65
long getCurrentTempo()
Gets the current tempo.
Definition: qsmf.cpp:1123
void signalSMFPitchBend(int chan, int value)
Emitted after reading a Bender message.
void signalSMFProgram(int chan, int patch)
Emitted after reading a Program change message.
void signalSMFError(const QString &errorStr)
Emitted for a SMF read or write error.
#define sequencer_specific
SMF Sequencer specific.
Definition: qsmf.h:59
#define MTrk
SMF Track prefix.
Definition: qsmf.h:40
virtual ~QSmf()
Destructor.
Definition: qsmf.cpp:107
void writeToFile(const QString &fileName)
Writes a SMF stream to a disk file.
Definition: qsmf.cpp:457
void signalSMFKeyPress(int chan, int pitch, int press)
Emitted after reading a Polyphonic Aftertouch message.
void signalSMFNoteOn(int chan, int pitch, int vol)
Emitted after reading a Note On message.
void readFromStream(QDataStream *stream)
Reads a SMF stream.
Definition: qsmf.cpp:424
#define time_signature
SMF Time signature.
Definition: qsmf.h:57
#define smpte_offset
SMF SMPTE offset.
Definition: qsmf.h:56
void writeKeySignature(long deltaTime, int tone, int mode)
Writes a key Signature message.
Definition: qsmf.cpp:780
void signalSMFSequenceNum(int seq)
Emitted after reading a Sequence number message.
void signalSMFSysex(const QByteArray &data)
Emitted after reading a System Exclusive message.
int getFileFormat()
Gets the SMF file format.
Definition: qsmf.cpp:1177
#define end_of_track
SMF End of track.
Definition: qsmf.h:54
void signalSMFKeySig(int b0, int b1)
Emitted after reading a SMF Key Signature smessage.
#define sequence_number
SMF Sequence number.
Definition: qsmf.h:44
void signalSMFTempo(int tempo)
Emitted after reading a Tempo Change message.
void signalSMFWriteTempoTrack()
Emitted to request the user to write the tempo track.
#define text_event
SMF Text event.
Definition: qsmf.h:45
#define note_off
MIDI event Note Off.
Definition: qsmf.h:62
void signalSMFTrackEnd()
Emitted after a track has finished.
#define poly_aftertouch
MIDI event Polyphonic pressure.
Definition: qsmf.h:64
#define end_of_sysex
MIDI event System Exclusive end.
Definition: qsmf.h:70
void signalSMFChanPress(int chan, int press)
Emitted after reading a Channel Aftertouch message.
#define meta_event
SMF Meta Event prefix.
Definition: qsmf.h:43
#define pitch_wheel
MIDI event Bender.
Definition: qsmf.h:68
void signalSMFMetaMisc(int typ, const QByteArray &data)
Emitted after reading any SMF Meta message.
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
Definition: qsmf.cpp:1205
void signalSMFMetaUnregistered(int typ, const QByteArray &data)
Emitted after reading an unregistered SMF Meta message.
#define set_tempo
SMF Tempo change.
Definition: qsmf.h:55
void writeSequenceNumber(long deltaTime, int seqnum)
Writes a MIDI Sequence number.
Definition: qsmf.cpp:716
#define instrument_name
SMF Instrument name.
Definition: qsmf.h:48
void setDivision(int division)
Sets the resolution.
Definition: qsmf.cpp:1150
void writeMidiEvent(long deltaTime, int type, int chan, int b1)
Writes a MIDI message with a single parameter.
Definition: qsmf.cpp:629
void signalSMFTimeSig(int b0, int b1, int b2, int b3)
Emitted after reading a SMF Time signature message.
#define lyric
SMF Lyric.
Definition: qsmf.h:49
void writeMetaEvent(long deltaTime, int type, const QByteArray &data)
Writes a variable length Meta Event.
Definition: qsmf.cpp:516
#define midi_channel_mask
Mask to extract the channel from the status byte.
Definition: qsmf.h:73
void signalSMFCtlChange(int chan, int ctl, int value)
Emitted after reading a Control Change message.
void readFromFile(const QString &fileName)
Reads a SMF stream from a disk file.
Definition: qsmf.cpp:434
void writeBpmTempo(long deltaTime, int tempo)
Writes a Tempo change message.
Definition: qsmf.cpp:748
void signalSMFendOfTrack()
Emitted after reading a End-Of-Track message.
#define note_on
MIDI event Note On.
Definition: qsmf.h:63
#define system_exclusive
MIDI event System Exclusive begin.
Definition: qsmf.h:69
#define cue_point
SMF Cue point.
Definition: qsmf.h:51
void setFileFormat(int fileFormat)
Sets the SMF file format.
Definition: qsmf.cpp:1186
#define program_chng
MIDI event Program change.
Definition: qsmf.h:66
#define sequence_name
SMF Sequence name.
Definition: qsmf.h:47
Standard MIDI Files Input/Output.
int getDivision()
Gets the resolution.
Definition: qsmf.cpp:1141
#define MThd
SMF Header prefix.
Definition: qsmf.h:39
#define copyright_notice
SMF Copyright notice.
Definition: qsmf.h:46