diff data/fileio/MIDIFileReader.cpp @ 301:73537d900d4b

* Add MIDI file export (closes FR#1643721)
author Chris Cannam
date Thu, 04 Oct 2007 11:52:38 +0000
parents 4b2ea82fd0ed
children 14e0f60435b8
line wrap: on
line diff
--- a/data/fileio/MIDIFileReader.cpp	Mon Oct 01 13:48:38 2007 +0000
+++ b/data/fileio/MIDIFileReader.cpp	Thu Oct 04 11:52:38 2007 +0000
@@ -28,6 +28,8 @@
 
 #include "MIDIFileReader.h"
 
+#include "MIDIEvent.h"
+
 #include "model/Model.h"
 #include "base/Pitch.h"
 #include "base/RealTime.h"
@@ -50,203 +52,10 @@
 using std::map;
 using std::set;
 
+using namespace MIDIConstants;
+
 //#define MIDI_DEBUG 1
 
-static const char *const MIDI_FILE_HEADER         = "MThd";
-static const char *const MIDI_TRACK_HEADER        = "MTrk";
-
-static const MIDIFileReader::MIDIByte MIDI_STATUS_BYTE_MASK       = 0x80;
-static const MIDIFileReader::MIDIByte MIDI_MESSAGE_TYPE_MASK      = 0xF0;
-static const MIDIFileReader::MIDIByte MIDI_CHANNEL_NUM_MASK       = 0x0F;
-static const MIDIFileReader::MIDIByte MIDI_NOTE_OFF               = 0x80;
-static const MIDIFileReader::MIDIByte MIDI_NOTE_ON                = 0x90;
-static const MIDIFileReader::MIDIByte MIDI_POLY_AFTERTOUCH        = 0xA0;
-static const MIDIFileReader::MIDIByte MIDI_CTRL_CHANGE            = 0xB0;
-static const MIDIFileReader::MIDIByte MIDI_PROG_CHANGE            = 0xC0;
-static const MIDIFileReader::MIDIByte MIDI_CHNL_AFTERTOUCH        = 0xD0;
-static const MIDIFileReader::MIDIByte MIDI_PITCH_BEND             = 0xE0;
-static const MIDIFileReader::MIDIByte MIDI_SELECT_CHNL_MODE       = 0xB0;
-static const MIDIFileReader::MIDIByte MIDI_SYSTEM_EXCLUSIVE       = 0xF0;
-static const MIDIFileReader::MIDIByte MIDI_TC_QUARTER_FRAME       = 0xF1;
-static const MIDIFileReader::MIDIByte MIDI_SONG_POSITION_PTR      = 0xF2;
-static const MIDIFileReader::MIDIByte MIDI_SONG_SELECT            = 0xF3;
-static const MIDIFileReader::MIDIByte MIDI_TUNE_REQUEST           = 0xF6;
-static const MIDIFileReader::MIDIByte MIDI_END_OF_EXCLUSIVE       = 0xF7;
-static const MIDIFileReader::MIDIByte MIDI_TIMING_CLOCK           = 0xF8;
-static const MIDIFileReader::MIDIByte MIDI_START                  = 0xFA;
-static const MIDIFileReader::MIDIByte MIDI_CONTINUE               = 0xFB;
-static const MIDIFileReader::MIDIByte MIDI_STOP                   = 0xFC;
-static const MIDIFileReader::MIDIByte MIDI_ACTIVE_SENSING         = 0xFE;
-static const MIDIFileReader::MIDIByte MIDI_SYSTEM_RESET           = 0xFF;
-static const MIDIFileReader::MIDIByte MIDI_SYSEX_NONCOMMERCIAL    = 0x7D;
-static const MIDIFileReader::MIDIByte MIDI_SYSEX_NON_RT           = 0x7E;
-static const MIDIFileReader::MIDIByte MIDI_SYSEX_RT               = 0x7F;
-static const MIDIFileReader::MIDIByte MIDI_SYSEX_RT_COMMAND       = 0x06;
-static const MIDIFileReader::MIDIByte MIDI_SYSEX_RT_RESPONSE      = 0x07;
-static const MIDIFileReader::MIDIByte MIDI_MMC_STOP               = 0x01;
-static const MIDIFileReader::MIDIByte MIDI_MMC_PLAY               = 0x02;
-static const MIDIFileReader::MIDIByte MIDI_MMC_DEFERRED_PLAY      = 0x03;
-static const MIDIFileReader::MIDIByte MIDI_MMC_FAST_FORWARD       = 0x04;
-static const MIDIFileReader::MIDIByte MIDI_MMC_REWIND             = 0x05;
-static const MIDIFileReader::MIDIByte MIDI_MMC_RECORD_STROBE      = 0x06;
-static const MIDIFileReader::MIDIByte MIDI_MMC_RECORD_EXIT        = 0x07;
-static const MIDIFileReader::MIDIByte MIDI_MMC_RECORD_PAUSE       = 0x08;
-static const MIDIFileReader::MIDIByte MIDI_MMC_PAUSE              = 0x08;
-static const MIDIFileReader::MIDIByte MIDI_MMC_EJECT              = 0x0A;
-static const MIDIFileReader::MIDIByte MIDI_MMC_LOCATE             = 0x44;
-static const MIDIFileReader::MIDIByte MIDI_FILE_META_EVENT        = 0xFF;
-static const MIDIFileReader::MIDIByte MIDI_SEQUENCE_NUMBER        = 0x00;
-static const MIDIFileReader::MIDIByte MIDI_TEXT_EVENT             = 0x01;
-static const MIDIFileReader::MIDIByte MIDI_COPYRIGHT_NOTICE       = 0x02;
-static const MIDIFileReader::MIDIByte MIDI_TRACK_NAME             = 0x03;
-static const MIDIFileReader::MIDIByte MIDI_INSTRUMENT_NAME        = 0x04;
-static const MIDIFileReader::MIDIByte MIDI_LYRIC                  = 0x05;
-static const MIDIFileReader::MIDIByte MIDI_TEXT_MARKER            = 0x06;
-static const MIDIFileReader::MIDIByte MIDI_CUE_POINT              = 0x07;
-static const MIDIFileReader::MIDIByte MIDI_CHANNEL_PREFIX         = 0x20;
-static const MIDIFileReader::MIDIByte MIDI_CHANNEL_PREFIX_OR_PORT = 0x21;
-static const MIDIFileReader::MIDIByte MIDI_END_OF_TRACK           = 0x2F;
-static const MIDIFileReader::MIDIByte MIDI_SET_TEMPO              = 0x51;
-static const MIDIFileReader::MIDIByte MIDI_SMPTE_OFFSET           = 0x54;
-static const MIDIFileReader::MIDIByte MIDI_TIME_SIGNATURE         = 0x58;
-static const MIDIFileReader::MIDIByte MIDI_KEY_SIGNATURE          = 0x59;
-static const MIDIFileReader::MIDIByte MIDI_SEQUENCER_SPECIFIC     = 0x7F;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_BANK_MSB      = 0x00;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_VOLUME        = 0x07;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_BANK_LSB      = 0x20;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_MODULATION    = 0x01;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_PAN           = 0x0A;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_SUSTAIN       = 0x40;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_RESONANCE     = 0x47;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_RELEASE       = 0x48;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_ATTACK        = 0x49;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_FILTER        = 0x4A;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_REVERB        = 0x5B;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_CHORUS        = 0x5D;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_NRPN_1        = 0x62;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_NRPN_2        = 0x63;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_RPN_1         = 0x64;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_RPN_2         = 0x65;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_SOUNDS_OFF    = 0x78;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_RESET         = 0x79;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_LOCAL         = 0x7A;
-static const MIDIFileReader::MIDIByte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B;
-static const MIDIFileReader::MIDIByte MIDI_PERCUSSION_CHANNEL       = 9;
-
-class MIDIEvent
-{
-public:
-    typedef MIDIFileReader::MIDIByte MIDIByte;
-
-    MIDIEvent(unsigned long deltaTime,
-              MIDIByte eventCode,
-              MIDIByte data1 = 0,
-              MIDIByte data2 = 0) :
-	m_deltaTime(deltaTime),
-	m_duration(0),
-	m_eventCode(eventCode),
-	m_data1(data1),
-	m_data2(data2),
-	m_metaEventCode(0)
-    { }
-
-    MIDIEvent(unsigned long deltaTime,
-              MIDIByte eventCode,
-              MIDIByte metaEventCode,
-              const string &metaMessage) :
-	m_deltaTime(deltaTime),
-	m_duration(0),
-	m_eventCode(eventCode),
-	m_data1(0),
-	m_data2(0),
-	m_metaEventCode(metaEventCode),
-	m_metaMessage(metaMessage)
-    { }
-
-    MIDIEvent(unsigned long deltaTime,
-              MIDIByte eventCode,
-              const string &sysEx) :
-	m_deltaTime(deltaTime),
-	m_duration(0),
-	m_eventCode(eventCode),
-	m_data1(0),
-	m_data2(0),
-	m_metaEventCode(0),
-	m_metaMessage(sysEx)
-    { }
-
-    ~MIDIEvent() { }
-
-    void setTime(const unsigned long &time) { m_deltaTime = time; }
-    void setDuration(const unsigned long& duration) { m_duration = duration;}
-    unsigned long addTime(const unsigned long &time) {
-	m_deltaTime += time;
-	return m_deltaTime;
-    }
-
-    MIDIByte getMessageType() const
-        { return (m_eventCode & MIDI_MESSAGE_TYPE_MASK); }
-
-    MIDIByte getChannelNumber() const
-        { return (m_eventCode & MIDI_CHANNEL_NUM_MASK); }
-
-    unsigned long getTime() const { return m_deltaTime; }
-    unsigned long getDuration() const { return m_duration; }
-
-    MIDIByte getPitch() const { return m_data1; }
-    MIDIByte getVelocity() const { return m_data2; }
-    MIDIByte getData1() const { return m_data1; }
-    MIDIByte getData2() const { return m_data2; }
-    MIDIByte getEventCode() const { return m_eventCode; }
-
-    bool isMeta() const { return (m_eventCode == MIDI_FILE_META_EVENT); }
-
-    MIDIByte getMetaEventCode() const { return m_metaEventCode; }
-    string getMetaMessage() const { return m_metaMessage; }
-    void setMetaMessage(const string &meta) { m_metaMessage = meta; }
-
-    friend bool operator<(const MIDIEvent &a, const MIDIEvent &b);
-
-private:
-    MIDIEvent& operator=(const MIDIEvent);
-
-    unsigned long  m_deltaTime;
-    unsigned long  m_duration;
-    MIDIByte       m_eventCode;
-    MIDIByte       m_data1;         // or Note
-    MIDIByte       m_data2;         // or Velocity
-    MIDIByte       m_metaEventCode;
-    string         m_metaMessage;
-};
-
-// Comparator for sorting
-//
-struct MIDIEventCmp
-{
-    bool operator()(const MIDIEvent &mE1, const MIDIEvent &mE2) const
-    { return mE1.getTime() < mE2.getTime(); }
-
-    bool operator()(const MIDIEvent *mE1, const MIDIEvent *mE2) const
-    { return mE1->getTime() < mE2->getTime(); }
-};
-
-class MIDIException : virtual public std::exception
-{
-public:
-    MIDIException(QString message) throw() : m_message(message) {
-	cerr << "WARNING: MIDI exception: "
-		  << message.toLocal8Bit().data() << endl;
-    }
-    virtual ~MIDIException() throw() { }
-
-    virtual const char *what() const throw() {
-	return m_message.toLocal8Bit().data();
-    }
-
-protected:
-    QString m_message;
-};
-
 
 MIDIFileReader::MIDIFileReader(QString path,
 			       size_t mainModelSampleRate) :
@@ -325,7 +134,7 @@
 // section we can read only a specified number of bytes held in
 // m_trackByteCount.
 //
-MIDIFileReader::MIDIByte
+MIDIByte
 MIDIFileReader::getMIDIByte()
 {
     if (!m_midiFile) {
@@ -477,6 +286,7 @@
 	m_error = "File not found or not readable.";
 	m_format = MIDI_FILE_BAD_FORMAT;
 	delete m_midiFile;
+        m_midiFile = 0;
 	return false;
     }