RMI read, print and extract.
#include "riff.h"
{
Q_OBJECT
public:
DumpRmid();
void run(QString fileName);
void dump(const QString& chan, const QString& event, const QString& data);
void dumpStr(const QString& event, const QString& data);
int numErrors();
void setExtract(bool enable);
void extractFileData(const QString& fileSuffix, const QByteArray& data);
public Q_SLOTS:
void headerEvent(int format, int ntrks, int division);
void trackStartEvent();
void trackEndEvent();
void endOfTrackEvent();
void noteOnEvent(int chan, int pitch, int vol);
void noteOffEvent(int chan, int pitch, int vol);
void keyPressEvent(int chan, int pitch, int press);
void ctlChangeEvent(int chan, int ctl, int value);
void pitchBendEvent(int chan, int value);
void programEvent(int chan, int patch);
void chanPressEvent(int chan, int press);
void sysexEvent(const QByteArray& data);
void seqSpecificEvent(const QByteArray& data);
void metaMiscEvent(int typ, const QByteArray& data);
void seqNum(int seq);
void forcedChannel(int channel);
void forcedPort(int port);
void textEvent(int typ, const QString& data);
void smpteEvent(int b0, int b1, int b2, int b3, int b4);
void timeSigEvent(int b0, int b1, int b2, int b3);
void keySigEvent(int b0, int b1);
void tempoEvent(int tempo);
void errorHandler(const QString& errorStr);
void infoHandler(const QString& infoType, const QByteArray& data);
void dataHandler(const QString& dataType, const QByteArray& data);
void processDLS(QString name, QString version, QString copyright);
void processInstrument(int bank, int pc, QString name);
void processPercussion(int bank, int pc, QString name);
private:
int m_currentTrack;
Riff *m_riff;
int m_rc;
bool m_extract;
QString m_fileName;
};
The QObject class is the base class of all Qt objects.
Standard MIDI Files input/output.
RIFF MIDI file format (input only)
Standard MIDI Files Input/Output.
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QFileInfo>
#include <QDir>
#include <QObject>
#include <QString>
#include <QTextCodec>
#include <QTextStream>
#include <cstdlib>
#include "dumprmi.h"
DISABLE_WARNING_PUSH
DISABLE_WARNING_DEPRECATED_DECLARATIONS
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
#define right Qt::right
#define left Qt::left
#define endl Qt::endl
#endif
QTextStream cout(stdout, QIODevice::WriteOnly);
QTextStream cerr(stderr, QIODevice::WriteOnly);
DumpRmid::DumpRmid():
m_currentTrack(0), m_engine(nullptr), m_rc(0)
{
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
m_engine =
new Rmidi(
this);
m_riff = new Riff(this); m_smf->setTextCodec(codec);
connect(m_riff, &Riff::signalDLS, this, &DumpRmid::processDLS);
connect(m_riff, &Riff::signalInstrument, this, &DumpRmid::processInstrument);
connect(m_riff, &Riff::signalPercussion, this, &DumpRmid::processPercussion);
cout.setRealNumberNotation(QTextStream::FixedNotation);
cout.setRealNumberPrecision(4);
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
cout.setCodec(codec);
#else
cout.setEncoding(QStringConverter::Utf8);
#endif
}
void DumpRmid::dump(const QString& chan, const QString& event,
const QString& data)
{
cout << right << qSetFieldWidth(7) << m_smf->getCurrentTime();
cout << right << qSetFieldWidth(10) << m_smf->getRealTime() / 1600.0;
cout << qSetFieldWidth(3) << chan;
cout << qSetFieldWidth(0) << left << " ";
cout << qSetFieldWidth(15) << event;
cout << qSetFieldWidth(0) << " " << data << endl;
}
void DumpRmid::dumpStr(const QString& event, const QString& data)
{
cout << right << qSetFieldWidth(7) << m_smf->getCurrentTime();
cout << right << qSetFieldWidth(10) << m_smf->getRealTime() / 1600.0;
cout << qSetFieldWidth(3) << "--";
cout << qSetFieldWidth(0) << left << " ";
cout << qSetFieldWidth(15) << event;
cout << qSetFieldWidth(0) << " " << data << endl;
}
void DumpRmid::headerEvent(int format, int ntrks, int division)
{
dumpStr("SMF Header", QString("Format=%1, Tracks=%2, Division=%3")
.arg(format).arg(ntrks).arg(division));
}
void DumpRmid::trackStartEvent()
{
m_currentTrack++;
dumpStr("Track", QString("Start: %1").arg(m_currentTrack));
}
void DumpRmid::trackEndEvent()
{
dumpStr("Track", QString("End: %1").arg(m_currentTrack));
}
void DumpRmid::endOfTrackEvent()
{
dumpStr("Meta Event", "End Of Track");
}
void DumpRmid::noteOnEvent(int chan, int pitch, int vol)
{
dump(QString("%1").arg(chan, 2), "Note On", QString("%1, %2").arg(pitch).arg(vol));
}
void DumpRmid::noteOffEvent(int chan, int pitch, int vol)
{
dump(QString("%1").arg(chan, 2), "Note Off", QString("%1, %2").arg(pitch).arg(vol));
}
void DumpRmid::keyPressEvent(int chan, int pitch, int press)
{
dump(QString("%1").arg(chan, 2), "Key Pressure", QString("%1, %2").arg(pitch).arg(press));
}
void DumpRmid::ctlChangeEvent(int chan, int ctl, int value)
{
dump(QString("%1").arg(chan, 2), "Control Change", QString("%1, %2").arg(ctl).arg(value));
}
void DumpRmid::pitchBendEvent(int chan, int value)
{
dump(QString("%1").arg(chan, 2), "Pitch Bend", QString::number(value));
}
void DumpRmid::programEvent(int chan, int patch)
{
dump(QString("%1").arg(chan, 2), "Program Change", QString::number(patch));
}
void DumpRmid::chanPressEvent(int chan, int press)
{
dump(QString("%1").arg(chan, 2), "Chan.Pressure", QString::number(press));
}
void DumpRmid::sysexEvent(const QByteArray& data)
{
int j;
QString s;
for (j = 0; j < data.count(); ++j)
s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16));
dumpStr("SysEx", s);
}
void DumpRmid::seqSpecificEvent(const QByteArray& data)
{
int j;
QString s;
for (j = 0; j < data.count(); ++j)
s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16));
dumpStr("Seq. specific", s);
}
void DumpRmid::metaMiscEvent(int typ, const QByteArray& data)
{
int j;
QString s = QString("type=%1 ").arg(typ);
for (j = 0; j < data.count(); ++j)
s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16));
dumpStr("Meta (unreg.)", s);
}
void DumpRmid::seqNum(int seq)
{
dump("--", "Sequence num.", QString::number(seq));
}
void DumpRmid::forcedChannel(int channel)
{
dump("--", "Forced channel", QString::number(channel));
}
void DumpRmid::forcedPort(int port)
{
dump("--", "Forced port", QString::number(port));
}
void DumpRmid::textEvent(int typ, const QString& data)
{
dumpStr(QString("Text (%1)").arg(typ), data);
}
void DumpRmid::smpteEvent(int b0, int b1, int b2, int b3, int b4)
{
dump("--", "SMPTE", QString("%1, %2, %3, %4, %5").arg(b0).arg(b1).arg(b2).arg(b3).arg(b4));
}
void DumpRmid::timeSigEvent(int b0, int b1, int b2, int b3)
{
dump("--", "Time Signature", QString("%1, %2, %3, %4").arg(b0).arg(b1).arg(b2).arg(b3));
}
void DumpRmid::keySigEvent(int b0, int b1)
{
dump("--", "Key Signature", QString("%1, %2").arg(b0).arg(b1));
}
void DumpRmid::tempoEvent(int tempo)
{
dump("--", "Tempo", QString::number(tempo));
}
void DumpRmid::errorHandler(const QString& errorStr)
{
m_rc++;
cerr << "*** Warning! " << errorStr
<< " at file offset " << m_smf->getFilePos()
<< endl;
}
void DumpRmid::infoHandler(const QString &infoType, const QByteArray &data)
{
QString info = QString::fromLatin1(data);
if (m_extract) {
cout << infoType << ": " << info << endl;
} else {
dump("--", "Info", QString("%1: %2").arg(infoType, info));
}
}
void DumpRmid::extractFileData(const QString &fileSuffix, const QByteArray &data)
{
QFileInfo finfo(m_fileName);
QString outfile = QDir::current().absoluteFilePath(finfo.baseName() + fileSuffix);
QFile file(outfile);
file.open(QFile::WriteOnly);
file.write(data);
file.close();
}
void DumpRmid::dataHandler(const QString &dataType, const QByteArray &data)
{
if (m_extract) {
if (dataType == "RMID") {
extractFileData(QLatin1String(".mid"), data);
} else if (dataType == "DLS") {
extractFileData(QLatin1String(".dls"), data);
}
} else {
if (dataType == "RMID") {
QDataStream ds(data);
m_smf->readFromStream(&ds);
} else if (dataType == "DLS") {
cout << " __bank ____PC name_____________________" << endl;
QDataStream ds(data);
m_riff->readFromStream(&ds);
}
}
}
void DumpRmid::processDLS(QString name, QString version, QString copyright)
{
cout << "DLS: " << name;
if (!version.isEmpty()) {
cout << " version: " << version;
}
if (!copyright.isNull()) {
cout << " copyright: " << copyright;
}
cout << endl;
}
void DumpRmid::processInstrument(int bank, int pc, QString name)
{
cout << right << qSetFieldWidth(7) << bank;
cout << right << qSetFieldWidth(7) << pc;
cout << left << qSetFieldWidth(0) << " " << name << endl;
}
void DumpRmid::processPercussion(int bank, int pc, QString name)
{
cout << right << qSetFieldWidth(7) << bank;
cout << right << qSetFieldWidth(7) << pc;
cout << left << qSetFieldWidth(0) << " " << name << endl;
}
void DumpRmid::run(QString fileName)
{
m_fileName = fileName;
m_currentTrack = 0;
if (!m_extract) {
cout << "__ticks __seconds ch event__________ data____" << endl;
}
m_engine->readFromFile(fileName);
}
int DumpRmid::numErrors()
{
return m_rc;
}
void DumpRmid::setExtract(bool enable)
{
m_extract = enable;
}
DISABLE_WARNING_POP
void signalSMFKeyPress(int chan, int pitch, int press)
Emitted after reading a Polyphonic Aftertouch message.
void signalSMFforcedChannel(int channel)
Emitted after reading a Forced channel message.
void signalSMFforcedPort(int port)
Emitted after reading a Forced port message.
void signalSMFTimeSig(int b0, int b1, int b2, int b3)
Emitted after reading a SMF Time signature message.
void signalSMFKeySig(int b0, int b1)
Emitted after reading a SMF Key Signature smessage.
void signalSMFChanPress(int chan, int press)
Emitted after reading a Channel Aftertouch message.
void signalSMFTrackEnd()
Emitted after a track has finished.
void signalSMFNoteOn(int chan, int pitch, int vol)
Emitted after reading a Note On message.
void signalSMFTempo(int tempo)
Emitted after reading a Tempo Change message.
Q_DECL_DEPRECATED void signalSMFText(int typ, const QString &data)
Emitted after reading a SMF text message.
void signalSMFTrackStart()
Emitted after reading a track prefix.
void signalSMFError(const QString &errorStr)
Emitted for a SMF read or write error.
void signalSMFSeqSpecific(const QByteArray &data)
Emitted after reading a Sequencer specific message.
void signalSMFendOfTrack()
Emitted after reading a End-Of-Track message.
void signalSMFHeader(int format, int ntrks, int division)
Emitted after reading a SMF header.
void signalSMFProgram(int chan, int patch)
Emitted after reading a Program change message.
void signalSMFNoteOff(int chan, int pitch, int vol)
Emitted after reading a Note Off message.
void signalSMFSequenceNum(int seq)
Emitted after reading a Sequence number message.
void signalSMFSysex(const QByteArray &data)
Emitted after reading a System Exclusive message.
void signalSMFCtlChange(int chan, int ctl, int value)
Emitted after reading a Control Change message.
void signalSMFPitchBend(int chan, int value)
Emitted after reading a Bender message.
void signalSMFMetaUnregistered(int typ, const QByteArray &data)
Emitted after reading an unregistered SMF Meta message.
void signalSMFSmpte(int b0, int b1, int b2, int b3, int b4)
Emitted after reading a SMPT offset message.
void signalRiffData(const QString &dataType, const QByteArray &data)
signalRiffData is emitted for each RMID data element
void signalRiffInfo(const QString &infoType, const QByteArray &info)
signalRMidInfo is emitted for each RIFF INFO element