20 #include <QDataStream>
23 #include <QStringList>
25 #include <QTextStream>
48 class QWrk::QWrkPrivate {
63 m_StopTime(4294967295U),
76 m_PunchEnabled(false),
106 quint8 m_CurTempoOfs;
111 quint32 m_PunchInTime;
112 quint32 m_PunchOutTime;
113 quint32 m_EndAllTime;
117 QDataStream *m_IOStream;
118 QByteArray m_lastChunkData;
119 QList<RecTempo> m_tempos;
121 qint64 m_lastChunkPos;
122 qint64 internalFilePos();
167 return d->m_lastChunkData;
173 void QWrk::readRawData(
int size)
176 d->m_lastChunkData = d->m_IOStream->device()->read(size);
178 d->m_lastChunkData.clear();
234 return d->m_AutoSave;
243 return d->m_PlayDelay;
252 return d->m_ZeroCtrls;
270 return d->m_SendCont;
279 return d->m_PatchSearch;
288 return d->m_AutoStop;
297 return d->m_StopTime;
306 return d->m_AutoRewind;
315 return d->m_RewindTime;
324 return d->m_MetroPlay;
333 return d->m_MetroRecord;
342 return d->m_MetroAccent;
369 return d->m_AutoRestart;
378 return d->m_CurTempoOfs;
397 return d->m_TempoOfs1;
416 return d->m_TempoOfs2;
435 return d->m_TempoOfs3;
444 return d->m_PunchEnabled;
453 return d->m_PunchInTime;
462 return d->m_PunchOutTime;
471 return d->m_EndAllTime;
478 quint8 QWrk::readByte()
481 if (!d->m_IOStream->atEnd())
492 quint16 QWrk::to16bit(quint8 c1, quint8 c2)
494 quint16 value = (c1 << 8);
507 quint32 QWrk::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
509 quint32 value = (c1 << 24);
520 quint16 QWrk::read16bit()
525 return to16bit(c2, c1);
532 quint32 QWrk::read24bit()
538 return to32bit(0, c3, c2, c1);
545 quint32 QWrk::read32bit()
547 quint8 c1, c2, c3, c4;
552 return to32bit(c4, c3, c2, c1);
559 QString QWrk::readString(
int len)
563 QByteArray data = readByteArray(len);
564 if (d->m_codec ==
nullptr) {
565 s = QString::fromLatin1(data);
567 s = d->m_codec->toUnicode(data);
577 QByteArray QWrk::readByteArray(
int len)
582 for (
int i = 0; i < len && c != 0 && !atEnd(); ++i ) {
596 QString QWrk::readVarString()
599 QByteArray data = readVarByteArray();
600 if (d->m_codec ==
nullptr) {
601 s = QString::fromLatin1(data);
603 s = d->m_codec->toUnicode(data);
612 QByteArray QWrk::readVarByteArray()
620 }
while (b != 0 && !atEnd());
630 return d->internalFilePos();
637 void QWrk::seek(qint64 pos)
639 if (!d->m_IOStream->device()->seek(pos)) {
650 return d->m_IOStream->atEnd();
657 void QWrk::readGap(
int size)
660 seek( d->internalFilePos() + size );
669 d->m_IOStream = stream;
679 QFile file(fileName);
680 file.open(QIODevice::ReadOnly);
681 QDataStream ds(&file);
686 void QWrk::processTrackChunk()
700 trackno = read16bit();
701 for(
int i=0; i<2; ++i) {
702 namelen = readByte();
703 if (d->m_codec ==
nullptr) {
704 data[i] = readByteArray(namelen);
706 name[i] = readString(namelen);
709 channel = readByte() & 0x0f;
711 velocity = readByte();
713 quint8 flags = readByte();
714 selected = ((flags & 1) != 0);
715 muted = ((flags & 2) != 0);
716 loop = ((flags & 4) != 0);
717 if (d->m_codec ==
nullptr) {
719 trackno, channel, pitch,
720 velocity, port, selected,
724 trackno, channel, pitch,
725 velocity, port, selected,
730 void QWrk::processVarsChunk()
732 d->m_Now = read32bit();
733 d->m_From = read32bit();
734 d->m_Thru = read32bit();
735 d->m_KeySig = readByte();
736 d->m_Clock = readByte();
737 d->m_AutoSave = readByte();
738 d->m_PlayDelay = readByte();
740 d->m_ZeroCtrls = (readByte() != 0);
741 d->m_SendSPP = (readByte() != 0);
742 d->m_SendCont = (readByte() != 0);
743 d->m_PatchSearch = (readByte() != 0);
744 d->m_AutoStop = (readByte() != 0);
745 d->m_StopTime = read32bit();
746 d->m_AutoRewind = (readByte() != 0);
747 d->m_RewindTime = read32bit();
748 d->m_MetroPlay = (readByte() != 0);
749 d->m_MetroRecord = (readByte() != 0);
750 d->m_MetroAccent = (readByte() != 0);
751 d->m_CountIn = readByte();
753 d->m_ThruOn = (readByte() != 0);
755 d->m_AutoRestart = (readByte() != 0);
756 d->m_CurTempoOfs = readByte();
757 d->m_TempoOfs1 = readByte();
758 d->m_TempoOfs2 = readByte();
759 d->m_TempoOfs3 = readByte();
761 d->m_PunchEnabled = (readByte() != 0);
762 d->m_PunchInTime = read32bit();
763 d->m_PunchOutTime = read32bit();
764 d->m_EndAllTime = read32bit();
769 void QWrk::processTimebaseChunk()
771 quint16 timebase = read16bit();
772 d->m_division = timebase;
776 void QWrk::processNoteArray(
int track,
int events)
779 quint8 status = 0, data1 = 0, data2 = 0, i = 0;
781 int value = 0, type = 0, channel = 0, len = 0;
784 for ( i = 0; (i < events) && (d->internalFilePos() < d->m_lastChunkPos) && !atEnd(); ++i ) {
788 if (status >= 0x90) {
789 type = status & 0xf0;
790 channel = status & 0x0f;
792 if (type == 0x90 || type == 0xA0 || type == 0xB0 || type == 0xE0)
798 Q_EMIT
signalWRKNote(track, time, channel, data1, data2, dur);
813 value = (data2 << 7) + data1 - 8192;
820 }
else if (status == 5) {
821 int code = read16bit();
823 if (d->m_codec ==
nullptr) {
824 data = readByteArray(len);
827 text = readString(len);
830 }
else if (status == 6) {
831 int code = read16bit();
835 }
else if (status == 7) {
837 text = readString(len);
839 for(
int j=0; j<13; ++j) {
840 int byte = readByte();
844 }
else if (status == 8) {
847 for(
int j=0; j<len; ++j) {
848 int byte = readByte();
854 if (d->m_codec ==
nullptr) {
855 data = readByteArray(len);
858 text = readString(len);
863 if ((i < events) && atEnd()) {
869 void QWrk::processStreamChunk()
872 int dur = 0, value = 0, type = 0, channel = 0, i = 0;
873 quint8 status = 0, data1 = 0, data2 = 0;
874 quint16 track = read16bit();
875 int events = read16bit();
876 for ( i = 0; (i < events) && (d->internalFilePos() < d->m_lastChunkPos) && !atEnd(); ++i ) {
882 type = status & 0xf0;
883 channel = status & 0x0f;
886 Q_EMIT
signalWRKNote(track, time, channel, data1, data2, dur);
901 value = (data2 << 7) + data1 - 8192;
909 if ((i < events) && atEnd()) {
915 void QWrk::processMeterChunk()
917 int count = read16bit();
918 for (
int i = 0; i < count; ++i) {
920 int measure = read16bit();
921 int num = readByte();
922 int den = pow(2.0, readByte());
928 void QWrk::processMeterKeyChunk()
930 int count = read16bit();
931 for (
int i = 0; i < count; ++i) {
932 int measure = read16bit();
933 int num = readByte();
934 int den = pow(2.0, readByte());
935 qint8 alt = readByte();
941 double QWrk::getRealTime(
long ticks)
const
943 double division = 1.0 * d->m_division;
948 if (!d->m_tempos.isEmpty()) {
949 foreach(
const RecTempo& rec, d->m_tempos) {
950 if (rec.time >= ticks)
955 return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo));
958 void QWrk::processTempoChunk(
int factor)
960 double division = 1.0 * d->m_division;
961 int count = read16bit();
963 for (
int i = 0; i < count; ++i) {
965 long time = read32bit();
967 long tempo = read16bit() * factor;
971 next.tempo = tempo / 100.0;
974 last.tempo = next.tempo;
976 if (! d->m_tempos.isEmpty()) {
977 foreach(
const RecTempo& rec, d->m_tempos) {
978 if (rec.time >= time)
982 next.seconds = last.seconds +
983 (((time - last.time) / division) * (60.0 / last.tempo));
985 d->m_tempos.append(next);
991 void QWrk::processSysexChunk()
996 int bank = readByte();
997 int length = read16bit();
998 bool autosend = (readByte() != 0);
999 int namelen = readByte();
1000 name = readString(namelen);
1001 for(j=0; j<length; ++j) {
1002 int byte = readByte();
1008 void QWrk::processSysex2Chunk()
1013 int bank = read16bit();
1014 int length = read32bit();
1015 quint8 b = readByte();
1016 int port = ( b & 0xf0 ) >> 4;
1017 bool autosend = ( (b & 0x0f) != 0);
1018 int namelen = readByte();
1019 name = readString(namelen);
1020 for(j=0; j<length; ++j) {
1021 int byte = readByte();
1027 void QWrk::processNewSysexChunk()
1032 int bank = read16bit();
1033 int length = read32bit();
1034 int port = read16bit();
1035 bool autosend = (readByte() != 0);
1036 int namelen = readByte();
1037 name = readString(namelen);
1038 for(j=0; j<length; ++j) {
1039 int byte = readByte();
1045 void QWrk::processThruChunk()
1048 qint8 port = readByte();
1049 qint8 channel = readByte();
1050 qint8 keyPlus = readByte();
1051 qint8 velPlus = readByte();
1052 qint8 localPort = readByte();
1053 qint8 mode = readByte();
1054 Q_EMIT
signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort);
1057 void QWrk::processTrackOffset()
1059 quint16 track = read16bit();
1060 qint16 offset = read16bit();
1064 void QWrk::processTrackReps()
1066 quint16 track = read16bit();
1067 quint16 reps = read16bit();
1071 void QWrk::processTrackPatch()
1073 quint16 track = read16bit();
1074 qint8 patch = readByte();
1078 void QWrk::processTimeFormat()
1080 quint16 fmt = read16bit();
1081 quint16 ofs = read16bit();
1085 void QWrk::processComments()
1087 int len = read16bit();
1088 if (d->m_codec ==
nullptr) {
1089 QByteArray data = readByteArray(len);
1092 QString text = readString(len);
1097 void QWrk::processVariableRecord(
int max)
1099 int datalen = max - 32;
1101 QString name = readVarString();
1102 readGap(31 - name.length());
1103 for (
int i = 0; i < datalen; ++i )
1108 void QWrk::processUnknown(
int id)
1113 void QWrk::processNewTrack()
1125 bool selected =
false;
1128 quint16 track = read16bit();
1129 quint8 len = readByte();
1130 if (d->m_codec ==
nullptr) {
1131 data = readByteArray(len);
1133 name = readString(len);
1136 patch = read16bit();
1143 channel = readByte();
1144 muted = (readByte() != 0);
1145 if (d->m_codec ==
nullptr) {
1146 Q_EMIT
signalWRKNewTrack2(data, track, channel, key, vel, port, selected, muted, loop);
1148 Q_EMIT
signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop);
1160 void QWrk::processSoftVer()
1162 int len = readByte();
1163 QString vers = readString(len);
1167 void QWrk::processTrackName()
1169 int track = read16bit();
1170 int len = readByte();
1171 if (d->m_codec ==
nullptr) {
1172 QByteArray data = readByteArray(len);
1175 QString name = readString(len);
1180 void QWrk::processStringTable()
1182 if (d->m_codec ==
nullptr) {
1183 QList<QByteArray> table;
1184 int rows = read16bit();
1185 for (
int i = 0; i < rows; ++i) {
1186 int len = readByte();
1187 QByteArray name = readByteArray(len);
1188 int idx = readByte();
1189 table.insert(idx, name);
1194 int rows = read16bit();
1195 for (
int i = 0; i < rows; ++i) {
1196 int len = readByte();
1197 QString name = readString(len);
1198 int idx = readByte();
1199 table.insert(idx, name);
1205 void QWrk::processLyricsStream()
1207 quint16 track = read16bit();
1208 int events = read32bit();
1209 processNoteArray(track, events);
1212 void QWrk::processTrackVol()
1214 quint16 track = read16bit();
1215 int vol = read16bit();
1219 void QWrk::processNewTrackOffset()
1221 quint16 track = read16bit();
1222 int offset = read32bit();
1226 void QWrk::processTrackBank()
1228 quint16 track = read16bit();
1229 int bank = read16bit();
1233 void QWrk::processSegmentChunk()
1237 int track = read16bit();
1238 int offset = read32bit();
1240 int len = readByte();
1241 if (d->m_codec ==
nullptr) {
1242 data = readByteArray(len);
1244 name = readString(len);
1247 if (d->m_codec ==
nullptr) {
1252 int events = read32bit();
1253 processNoteArray(track, events);
1256 void QWrk::processNewStream()
1260 int track = read16bit();
1261 int len = readByte();
1262 if (d->m_codec ==
nullptr) {
1263 data = readByteArray(len);
1266 name = readString(len);
1269 int events = read32bit();
1270 processNoteArray(track, events);
1273 void QWrk::processEndChunk()
1278 int QWrk::readChunk()
1280 qint64 start_pos = d->internalFilePos();
1281 int ck = readByte();
1283 quint32 ck_len = read32bit();
1284 if (ck_len > d->m_IOStream->device()->bytesAvailable()) {
1289 start_pos = d->internalFilePos();
1290 d->m_lastChunkPos = start_pos + ck_len;
1291 readRawData(ck_len);
1295 processTrackChunk();
1301 processTimebaseChunk();
1304 processStreamChunk();
1307 processMeterChunk();
1310 processTempoChunk(100);
1313 processTempoChunk();
1316 processSysexChunk();
1322 processTrackOffset();
1328 processTrackPatch();
1331 processTimeFormat();
1337 processVariableRecord(ck_len);
1349 processStringTable();
1352 processLyricsStream();
1358 processNewTrackOffset();
1364 processMeterKeyChunk();
1367 processSysex2Chunk();
1370 processNewSysexChunk();
1373 processSegmentChunk();
1381 if (d->internalFilePos() != d->m_lastChunkPos) {
1383 seek(d->m_lastChunkPos);
1389 void QWrk::wrkRead()
1391 QByteArray hdr(
HEADER.length(),
' ');
1392 d->m_tempos.clear();
1393 d->m_IOStream->device()->read(hdr.data(),
HEADER.length());
1402 ck_id = readChunk();
1403 }
while ((ck_id !=
END_CHUNK) && !atEnd());
1406 readRawData(d->m_IOStream->device()->bytesAvailable());
1407 processUnknown(ck_id);
1414 qint64 QWrk::QWrkPrivate::internalFilePos()
1416 return m_IOStream->device()->pos();
1419 const QByteArray
QWrk::HEADER = QByteArrayLiteral(
"CAKEWALK");
The QObject class is the base class of all Qt objects.
void signalWRKTrackPatch(int track, int patch)
Emitted after reading a track patch chunk.
bool getMetroRecord() const
Metronome on during recording?
bool getPunchEnabled() const
Auto-Punch enabled?
void signalWRKText(int track, long time, int type, const QString &data)
Emitted after reading a text message.
int getRewindTime() const
Auto-rewind time.
bool getZeroCtrls() const
Zero continuous controllers?
void signalWRKTrack(const QString &name1, const QString &name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a track prefix chunk.
QWrk(QObject *parent=nullptr)
Constructor.
void signalWRKProgram(int track, long time, int chan, int patch)
Emitted after reading a Program change message.
void signalWRKChord(int track, long time, const QString &name, const QByteArray &data)
Emitted after reading a chord diagram chunk.
static const QByteArray HEADER
Cakewalk WRK file format header string id.
void setTextCodec(QTextCodec *codec)
Sets the text codec for text meta-events.
void signalWRKHeader(int verh, int verl)
Emitted after reading a WRK header.
void signalWRKSysexEvent(int track, long time, int bank)
Emitted after reading a System Exclusive event.
int getAutoSave() const
Auto save (0=disabled, 1..256=minutes)
long getFilePos()
Current position in the data stream.
bool getThruOn() const
MIDI Thru enabled? (only used if no THRU rec)
void signalWRKGlobalVars()
Emitted after reading the global variables chunk.
void signalWRKSoftVer(const QString &version)
Emitted after reading a software version chunk.
void signalWRKSegment2(int track, long time, const QByteArray &name)
Emitted after reading a segment prefix chunk.
int getNow() const
Now marker time.
int getPunchOutTime() const
Punch-out time.
void signalWRKComments(const QString &data)
Emitted after reading a comments chunk.
void signalWRKTrackOffset(int track, int offset)
Emitted after reading a track offset chunk.
void signalWRKChanPress(int track, long time, int chan, int press)
Emitted after reading a Channel Aftertouch message.
void signalWRKStreamEnd(long time)
Emitted after reading the last event of a event stream.
void signalWRKText2(int track, long time, int type, const QByteArray &data)
Emitted after reading a text message This signal is emitted when getTextCodec() is nullptr.
bool getAutoStop() const
Auto-stop?
int getEndAllTime() const
Time of latest event (incl.
void signalWRKKeyPress(int track, long time, int chan, int pitch, int press)
Emitted after reading a Polyphonic Aftertouch message.
void signalWRKVariableRecord(const QString &name, const QByteArray &data)
Emitted after reading a variable chunk.
void signalWRKTrackVol(int track, int vol)
Emitted after reading a track volume chunk.
void signalWRKExpression2(int track, long time, int code, const QByteArray &text)
Emitted after reading an expression indication (notation) chunk.
void signalWRKTrackName2(int track, const QByteArray &name)
Emitted after reading a track name chunk.
void signalWRKStringTable(const QStringList &strs)
Emitted after reading a string event types chunk.
int getPlayDelay() const
Play Delay.
bool getSendSPP() const
Send Song Position Pointer?
void signalWRKTrack2(const QByteArray &name1, const QByteArray &name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a track prefix chunk This signal is emitted when getTextCodec() is nullptr.
void signalWRKError(const QString &errorStr)
Emitted for a WRK file read error.
virtual ~QWrk()
Destructor.
void signalWRKSegment(int track, long time, const QString &name)
Emitted after reading a segment prefix chunk.
void signalWRKTempo(long time, int tempo)
Emitted after reading a Tempo Change message.
void signalWRKExpression(int track, long time, int code, const QString &text)
Emitted after reading an expression indication (notation) chunk.
void signalWRKTimeSig(int bar, int num, int den)
Emitted after reading a WRK Time signature.
void signalWRKHairpin(int track, long time, int code, int dur)
Emitted after reading a hairpin symbol (notation) chunk.
void signalWRKPitchBend(int track, long time, int chan, int value)
Emitted after reading a Bender message.
void signalWRKEnd()
Emitted after reading the last chunk of a WRK file.
int getTempoOfs3() const
Fixed-point ratio value of tempo offset 3.
int getThru() const
Thru marker time.
bool getSendCont() const
Send MIDI Continue?
int getTempoOfs2() const
Fixed-point ratio value of tempo offset 2.
void signalWRKNewTrack2(const QByteArray &name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a new track prefix This signal is emitted when getTextCodec() is nullptr.
bool getPatchSearch() const
Patch/controller search-back?
void readFromStream(QDataStream *stream)
Reads a stream.
void signalWRKThru(int mode, int port, int channel, int keyPlus, int velPlus, int localPort)
Emitted after reading an Extended Thru parameters chunk.
int getPunchInTime() const
Punch-in time.
void signalWRKNote(int track, long time, int chan, int pitch, int vol, int dur)
Emitted after reading a Note message.
unsigned int getStopTime() const
Auto-stop time.
void signalWRKUnknownChunk(int type, const QByteArray &data)
Emitted after reading an unknown chunk.
void signalWRKTrackBank(int track, int bank)
Emitted after reading a track bank chunk.
void signalWRKTrackName(int track, const QString &name)
Emitted after reading a track name chunk.
void signalWRKComments2(const QByteArray &data)
Emitted after reading a comments chunk This signal is emitted when getTextCodec() is nullptr.
void signalWRKTimeBase(int timebase)
Emitted after reading the timebase chunk.
QByteArray getLastChunkRawData() const
Gets the last chunk raw data (undecoded)
bool getAutoRewind() const
Auto-rewind?
bool getMetroPlay() const
Metronome on during playback?
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
int getFrom() const
From marker time.
void signalWRKTimeFormat(int frames, int offset)
Emitted after reading a SMPTE time format chunk.
void signalWRKSysex(int bank, const QString &name, bool autosend, int port, const QByteArray &data)
Emitted after reading a System Exclusive Bank.
void readFromFile(const QString &fileName)
Reads a stream from a disk file.
int getCountIn() const
Measures of count-in (0=no count-in)
int getCurTempoOfs() const
Which of the 3 tempo offsets is used: 0..2.
void signalWRKCtlChange(int track, long time, int chan, int ctl, int value)
Emitted after reading a Control Change message.
void signalWRKTrackReps(int track, int reps)
Emitted after reading a track offset chunk.
void signalWRKNewTrack(const QString &name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a new track prefix.
void signalWRKKeySig(int bar, int alt)
Emitted after reading a WRK Key Signature.
bool getAutoRestart() const
Auto-restart?
int getClock() const
Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE)
int getKeySig() const
Key signature (0=C, 1=C#, ...
void signalWRKStringTable2(const QList< QByteArray > &strs)
Emitted after reading a string event types chunk.
bool getMetroAccent() const
Metronome accents primary beats?
int getTempoOfs1() const
Fixed-point ratio value of tempo offset 1.
@ NTRKOFS_CHUNK
Track offset.
@ NTRACK_CHUNK
Track prefix.
@ TRKPATCH_CHUNK
Track patch.
@ STRTAB_CHUNK
Table of text event types.
@ NTEMPO_CHUNK
New Tempo map.
@ VARS_CHUNK
Global variables.
@ TRKBANK_CHUNK
Track bank.
@ COMMENTS_CHUNK
Comments.
@ SGMNT_CHUNK
Segment prefix.
@ SOFTVER_CHUNK
Software version which saved the file.
@ TRKNAME_CHUNK
Track name.
@ TIMEFMT_CHUNK
SMPTE time format.
@ END_CHUNK
Last chunk, end of file.
@ STREAM_CHUNK
Events stream.
@ TRACK_CHUNK
Track prefix.
@ TIMEBASE_CHUNK
Timebase. If present is the first chunk in the file.
@ TRKOFFS_CHUNK
Track offset.
@ NSYSEX_CHUNK
System exclusive bank.
@ THRU_CHUNK
Extended thru parameters.
@ SYSEX2_CHUNK
System exclusive bank.
@ NSTREAM_CHUNK
Events stream.
@ VARIABLE_CHUNK
Variable record chunk.
@ METERKEY_CHUNK
Meter/Key map.
@ TRKREPS_CHUNK
Track repetitions.
@ TRKVOL_CHUNK
Track volume.
@ SYSEX_CHUNK
System exclusive bank.
@ LYRICS_CHUNK
Events stream with lyrics.
Cakewalk WRK Files Input.