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