19 #include <QDataStream>
22 #include <QStringList>
24 #include <QTextStream>
47 class QWrk::QWrkPrivate {
62 m_StopTime(4294967295U),
75 m_PunchEnabled(false),
105 quint8 m_CurTempoOfs;
110 quint32 m_PunchInTime;
111 quint32 m_PunchOutTime;
112 quint32 m_EndAllTime;
116 QDataStream *m_IOStream;
117 QByteArray m_lastChunkData;
118 QList<RecTempo> m_tempos;
163 return d->m_lastChunkData;
169 void QWrk::readRawData(
int size)
171 d->m_lastChunkData = d->m_IOStream->device()->read(size);
225 return d->m_AutoSave;
234 return d->m_PlayDelay;
243 return d->m_ZeroCtrls;
261 return d->m_SendCont;
270 return d->m_PatchSearch;
279 return d->m_AutoStop;
288 return d->m_StopTime;
297 return d->m_AutoRewind;
306 return d->m_RewindTime;
315 return d->m_MetroPlay;
324 return d->m_MetroRecord;
333 return d->m_MetroAccent;
360 return d->m_AutoRestart;
369 return d->m_CurTempoOfs;
388 return d->m_TempoOfs1;
407 return d->m_TempoOfs2;
426 return d->m_TempoOfs3;
435 return d->m_PunchEnabled;
444 return d->m_PunchInTime;
453 return d->m_PunchOutTime;
462 return d->m_EndAllTime;
469 quint8 QWrk::readByte()
472 if (!d->m_IOStream->atEnd())
483 quint16 QWrk::to16bit(quint8 c1, quint8 c2)
485 quint16 value = (c1 << 8);
498 quint32 QWrk::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
500 quint32 value = (c1 << 24);
511 quint16 QWrk::read16bit()
516 return to16bit(c2, c1);
523 quint32 QWrk::read24bit()
529 return to32bit(0, c3, c2, c1);
536 quint32 QWrk::read32bit()
538 quint8 c1, c2, c3, c4;
543 return to32bit(c4, c3, c2, c1);
550 QString QWrk::readString(
int len)
556 for (
int i = 0; i < len && c != 0 && !atEnd(); ++i ) {
561 if (d->m_codec ==
nullptr)
564 s = d->m_codec->toUnicode(data);
573 QString QWrk::readVarString()
582 }
while (b != 0 && !atEnd());
583 if (d->m_codec ==
nullptr)
586 s = d->m_codec->toUnicode(data);
596 return d->m_IOStream->device()->pos();
603 void QWrk::seek(qint64 pos)
605 d->m_IOStream->device()->seek(pos);
614 return d->m_IOStream->atEnd();
621 void QWrk::readGap(
int size)
633 d->m_IOStream = stream;
643 QFile file(fileName);
644 file.open(QIODevice::ReadOnly);
645 QDataStream ds(&file);
650 void QWrk::processTrackChunk()
663 trackno = read16bit();
664 for(
int i=0; i<2; ++i) {
665 namelen = readByte();
666 name[i] = readString(namelen);
668 channel = readByte() & 0x0f;
670 velocity = readByte();
672 quint8 flags = readByte();
673 selected = ((flags & 1) != 0);
674 muted = ((flags & 2) != 0);
675 loop = ((flags & 4) != 0);
677 trackno, channel, pitch,
678 velocity, port, selected,
682 void QWrk::processVarsChunk()
684 d->m_Now = read32bit();
685 d->m_From = read32bit();
686 d->m_Thru = read32bit();
687 d->m_KeySig = readByte();
688 d->m_Clock = readByte();
689 d->m_AutoSave = readByte();
690 d->m_PlayDelay = readByte();
692 d->m_ZeroCtrls = (readByte() != 0);
693 d->m_SendSPP = (readByte() != 0);
694 d->m_SendCont = (readByte() != 0);
695 d->m_PatchSearch = (readByte() != 0);
696 d->m_AutoStop = (readByte() != 0);
697 d->m_StopTime = read32bit();
698 d->m_AutoRewind = (readByte() != 0);
699 d->m_RewindTime = read32bit();
700 d->m_MetroPlay = (readByte() != 0);
701 d->m_MetroRecord = (readByte() != 0);
702 d->m_MetroAccent = (readByte() != 0);
703 d->m_CountIn = readByte();
705 d->m_ThruOn = (readByte() != 0);
707 d->m_AutoRestart = (readByte() != 0);
708 d->m_CurTempoOfs = readByte();
709 d->m_TempoOfs1 = readByte();
710 d->m_TempoOfs2 = readByte();
711 d->m_TempoOfs3 = readByte();
713 d->m_PunchEnabled = (readByte() != 0);
714 d->m_PunchInTime = read32bit();
715 d->m_PunchOutTime = read32bit();
716 d->m_EndAllTime = read32bit();
721 void QWrk::processTimebaseChunk()
723 quint16 timebase = read16bit();
724 d->m_division = timebase;
728 void QWrk::processNoteArray(
int track,
int events)
731 quint8 status = 0, data1 = 0, data2 = 0, i = 0;
733 int value = 0, type = 0, channel = 0, len = 0;
736 for ( i = 0; (i < events) && !atEnd(); ++i ) {
740 if (status >= 0x90) {
741 type = status & 0xf0;
742 channel = status & 0x0f;
744 if (type == 0x90 || type == 0xA0 || type == 0xB0 || type == 0xE0)
750 Q_EMIT
signalWRKNote(track, time, channel, data1, data2, dur);
765 value = (data2 << 7) + data1 - 8192;
772 }
else if (status == 5) {
773 int code = read16bit();
775 text = readString(len);
777 }
else if (status == 6) {
778 int code = read16bit();
782 }
else if (status == 7) {
784 text = readString(len);
786 for(
int j=0; j<13; ++j) {
787 int byte = readByte();
791 }
else if (status == 8) {
794 for(
int j=0; j<len; ++j) {
795 int byte = readByte();
801 text = readString(len);
805 if ((i < events) && atEnd()) {
811 void QWrk::processStreamChunk()
814 int dur = 0, value = 0, type = 0, channel = 0, i = 0;
815 quint8 status = 0, data1 = 0, data2 = 0;
816 quint16 track = read16bit();
817 int events = read16bit();
818 for ( i = 0; (i < events) && !atEnd(); ++i ) {
824 type = status & 0xf0;
825 channel = status & 0x0f;
828 Q_EMIT
signalWRKNote(track, time, channel, data1, data2, dur);
843 value = (data2 << 7) + data1 - 8192;
851 if ((i < events) && atEnd()) {
857 void QWrk::processMeterChunk()
859 int count = read16bit();
860 for (
int i = 0; i < count; ++i) {
862 int measure = read16bit();
863 int num = readByte();
864 int den = pow(2.0, readByte());
870 void QWrk::processMeterKeyChunk()
872 int count = read16bit();
873 for (
int i = 0; i < count; ++i) {
874 int measure = read16bit();
875 int num = readByte();
876 int den = pow(2.0, readByte());
877 qint8 alt = readByte();
883 double QWrk::getRealTime(
long ticks)
const
885 double division = 1.0 * d->m_division;
890 if (!d->m_tempos.isEmpty()) {
891 foreach(
const RecTempo& rec, d->m_tempos) {
892 if (rec.time >= ticks)
897 return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo));
900 void QWrk::processTempoChunk(
int factor)
902 double division = 1.0 * d->m_division;
903 int count = read16bit();
905 for (
int i = 0; i < count; ++i) {
907 long time = read32bit();
909 long tempo = read16bit() * factor;
913 next.tempo = tempo / 100.0;
916 last.tempo = next.tempo;
918 if (! d->m_tempos.isEmpty()) {
919 foreach(
const RecTempo& rec, d->m_tempos) {
920 if (rec.time >= time)
924 next.seconds = last.seconds +
925 (((time - last.time) / division) * (60.0 / last.tempo));
927 d->m_tempos.append(next);
933 void QWrk::processSysexChunk()
938 int bank = readByte();
939 int length = read16bit();
940 bool autosend = (readByte() != 0);
941 int namelen = readByte();
942 name = readString(namelen);
943 for(j=0; j<length; ++j) {
944 int byte = readByte();
950 void QWrk::processSysex2Chunk()
955 int bank = read16bit();
956 int length = read32bit();
957 quint8 b = readByte();
958 int port = ( b & 0xf0 ) >> 4;
959 bool autosend = ( (b & 0x0f) != 0);
960 int namelen = readByte();
961 name = readString(namelen);
962 for(j=0; j<length; ++j) {
963 int byte = readByte();
969 void QWrk::processNewSysexChunk()
974 int bank = read16bit();
975 int length = read32bit();
976 int port = read16bit();
977 bool autosend = (readByte() != 0);
978 int namelen = readByte();
979 name = readString(namelen);
980 for(j=0; j<length; ++j) {
981 int byte = readByte();
987 void QWrk::processThruChunk()
990 qint8 port = readByte();
991 qint8 channel = readByte();
992 qint8 keyPlus = readByte();
993 qint8 velPlus = readByte();
994 qint8 localPort = readByte();
995 qint8 mode = readByte();
996 Q_EMIT
signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort);
999 void QWrk::processTrackOffset()
1001 quint16 track = read16bit();
1002 qint16 offset = read16bit();
1006 void QWrk::processTrackReps()
1008 quint16 track = read16bit();
1009 quint16 reps = read16bit();
1013 void QWrk::processTrackPatch()
1015 quint16 track = read16bit();
1016 qint8 patch = readByte();
1020 void QWrk::processTimeFormat()
1022 quint16 fmt = read16bit();
1023 quint16 ofs = read16bit();
1027 void QWrk::processComments()
1029 int len = read16bit();
1030 QString text = readString(len);
1034 void QWrk::processVariableRecord(
int max)
1036 int datalen = max - 32;
1038 QString name = readVarString();
1039 readGap(31 - name.length());
1040 for (
int i = 0; i < datalen; ++i )
1045 void QWrk::processUnknown(
int id)
1050 void QWrk::processNewTrack()
1060 bool selected =
false;
1063 quint16 track = read16bit();
1064 quint8 len = readByte();
1065 QString name = readString(len);
1067 patch = read16bit();
1074 channel = readByte();
1075 muted = (readByte() != 0);
1076 Q_EMIT
signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop);
1087 void QWrk::processSoftVer()
1089 int len = readByte();
1090 QString vers = readString(len);
1094 void QWrk::processTrackName()
1096 int track = read16bit();
1097 int len = readByte();
1098 QString name = readString(len);
1102 void QWrk::processStringTable()
1105 int rows = read16bit();
1106 for (
int i = 0; i < rows; ++i) {
1107 int len = readByte();
1108 QString name = readString(len);
1109 int idx = readByte();
1110 table.insert(idx, name);
1115 void QWrk::processLyricsStream()
1117 quint16 track = read16bit();
1118 int events = read32bit();
1119 processNoteArray(track, events);
1122 void QWrk::processTrackVol()
1124 quint16 track = read16bit();
1125 int vol = read16bit();
1129 void QWrk::processNewTrackOffset()
1131 quint16 track = read16bit();
1132 int offset = read32bit();
1136 void QWrk::processTrackBank()
1138 quint16 track = read16bit();
1139 int bank = read16bit();
1143 void QWrk::processSegmentChunk()
1146 int track = read16bit();
1147 int offset = read32bit();
1149 int len = readByte();
1150 name = readString(len);
1153 int events = read32bit();
1154 processNoteArray(track, events);
1157 void QWrk::processNewStream()
1160 int track = read16bit();
1161 int len = readByte();
1162 name = readString(len);
1164 int events = read32bit();
1165 processNoteArray(track, events);
1168 void QWrk::processEndChunk()
1173 int QWrk::readChunk()
1175 long start_pos, final_pos;
1176 int ck_len, ck = readByte();
1178 ck_len = read32bit();
1180 final_pos = start_pos + ck_len;
1181 readRawData(ck_len);
1185 processTrackChunk();
1191 processTimebaseChunk();
1194 processStreamChunk();
1197 processMeterChunk();
1200 processTempoChunk(100);
1203 processTempoChunk();
1206 processSysexChunk();
1212 processTrackOffset();
1218 processTrackPatch();
1221 processTimeFormat();
1227 processVariableRecord(ck_len);
1239 processStringTable();
1242 processLyricsStream();
1248 processNewTrackOffset();
1254 processMeterKeyChunk();
1257 processSysex2Chunk();
1260 processNewSysexChunk();
1263 processSegmentChunk();
1276 void QWrk::wrkRead()
1278 QByteArray hdr(
HEADER.length(),
' ');
1279 d->m_tempos.clear();
1280 d->m_IOStream->device()->read(hdr.data(),
HEADER.length());
1289 ck_id = readChunk();
1299 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.
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.
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 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 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.
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 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#, ...
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.