Chris@301: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@301: Chris@301: /* Chris@301: Sonic Visualiser Chris@301: An audio file viewer and annotation editor. Chris@301: Centre for Digital Music, Queen Mary, University of London. Chris@301: Chris@301: This program is free software; you can redistribute it and/or Chris@301: modify it under the terms of the GNU General Public License as Chris@301: published by the Free Software Foundation; either version 2 of the Chris@301: License, or (at your option) any later version. See the file Chris@301: COPYING included with this distribution for more information. Chris@301: */ Chris@301: Chris@301: Chris@301: /* Chris@301: This is a modified version of a source file from the Chris@301: Rosegarden MIDI and audio sequencer and notation editor. Chris@301: This file copyright 2000-2006 Richard Bown and Chris Cannam. Chris@301: */ Chris@301: Chris@1581: #ifndef SV_MIDI_EVENT_H Chris@1581: #define SV_MIDI_EVENT_H Chris@301: Chris@301: #include Chris@301: #include Chris@301: #include Chris@1038: #include Chris@1038: Chris@687: #include "base/Debug.h" Chris@301: Chris@301: typedef unsigned char MIDIByte; Chris@301: Chris@301: namespace MIDIConstants Chris@301: { Chris@301: static const char *const MIDI_FILE_HEADER = "MThd"; Chris@301: static const char *const MIDI_TRACK_HEADER = "MTrk"; Chris@301: Chris@301: static const MIDIByte MIDI_STATUS_BYTE_MASK = 0x80; Chris@301: static const MIDIByte MIDI_MESSAGE_TYPE_MASK = 0xF0; Chris@301: static const MIDIByte MIDI_CHANNEL_NUM_MASK = 0x0F; Chris@301: Chris@301: static const MIDIByte MIDI_NOTE_OFF = 0x80; Chris@301: static const MIDIByte MIDI_NOTE_ON = 0x90; Chris@301: static const MIDIByte MIDI_POLY_AFTERTOUCH = 0xA0; Chris@301: static const MIDIByte MIDI_CTRL_CHANGE = 0xB0; Chris@301: static const MIDIByte MIDI_PROG_CHANGE = 0xC0; Chris@301: static const MIDIByte MIDI_CHNL_AFTERTOUCH = 0xD0; Chris@301: static const MIDIByte MIDI_PITCH_BEND = 0xE0; Chris@301: static const MIDIByte MIDI_SELECT_CHNL_MODE = 0xB0; Chris@301: static const MIDIByte MIDI_SYSTEM_EXCLUSIVE = 0xF0; Chris@301: static const MIDIByte MIDI_TC_QUARTER_FRAME = 0xF1; Chris@301: static const MIDIByte MIDI_SONG_POSITION_PTR = 0xF2; Chris@301: static const MIDIByte MIDI_SONG_SELECT = 0xF3; Chris@301: static const MIDIByte MIDI_TUNE_REQUEST = 0xF6; Chris@301: static const MIDIByte MIDI_END_OF_EXCLUSIVE = 0xF7; Chris@301: static const MIDIByte MIDI_TIMING_CLOCK = 0xF8; Chris@301: static const MIDIByte MIDI_START = 0xFA; Chris@301: static const MIDIByte MIDI_CONTINUE = 0xFB; Chris@301: static const MIDIByte MIDI_STOP = 0xFC; Chris@301: static const MIDIByte MIDI_ACTIVE_SENSING = 0xFE; Chris@301: static const MIDIByte MIDI_SYSTEM_RESET = 0xFF; Chris@301: static const MIDIByte MIDI_SYSEX_NONCOMMERCIAL = 0x7D; Chris@301: static const MIDIByte MIDI_SYSEX_NON_RT = 0x7E; Chris@301: static const MIDIByte MIDI_SYSEX_RT = 0x7F; Chris@301: static const MIDIByte MIDI_SYSEX_RT_COMMAND = 0x06; Chris@301: static const MIDIByte MIDI_SYSEX_RT_RESPONSE = 0x07; Chris@301: static const MIDIByte MIDI_MMC_STOP = 0x01; Chris@301: static const MIDIByte MIDI_MMC_PLAY = 0x02; Chris@301: static const MIDIByte MIDI_MMC_DEFERRED_PLAY = 0x03; Chris@301: static const MIDIByte MIDI_MMC_FAST_FORWARD = 0x04; Chris@301: static const MIDIByte MIDI_MMC_REWIND = 0x05; Chris@301: static const MIDIByte MIDI_MMC_RECORD_STROBE = 0x06; Chris@301: static const MIDIByte MIDI_MMC_RECORD_EXIT = 0x07; Chris@301: static const MIDIByte MIDI_MMC_RECORD_PAUSE = 0x08; Chris@301: static const MIDIByte MIDI_MMC_PAUSE = 0x08; Chris@301: static const MIDIByte MIDI_MMC_EJECT = 0x0A; Chris@301: static const MIDIByte MIDI_MMC_LOCATE = 0x44; Chris@301: static const MIDIByte MIDI_FILE_META_EVENT = 0xFF; Chris@301: static const MIDIByte MIDI_SEQUENCE_NUMBER = 0x00; Chris@301: static const MIDIByte MIDI_TEXT_EVENT = 0x01; Chris@301: static const MIDIByte MIDI_COPYRIGHT_NOTICE = 0x02; Chris@301: static const MIDIByte MIDI_TRACK_NAME = 0x03; Chris@301: static const MIDIByte MIDI_INSTRUMENT_NAME = 0x04; Chris@301: static const MIDIByte MIDI_LYRIC = 0x05; Chris@301: static const MIDIByte MIDI_TEXT_MARKER = 0x06; Chris@301: static const MIDIByte MIDI_CUE_POINT = 0x07; Chris@301: static const MIDIByte MIDI_CHANNEL_PREFIX = 0x20; Chris@301: static const MIDIByte MIDI_CHANNEL_PREFIX_OR_PORT = 0x21; Chris@301: static const MIDIByte MIDI_END_OF_TRACK = 0x2F; Chris@301: static const MIDIByte MIDI_SET_TEMPO = 0x51; Chris@301: static const MIDIByte MIDI_SMPTE_OFFSET = 0x54; Chris@301: static const MIDIByte MIDI_TIME_SIGNATURE = 0x58; Chris@301: static const MIDIByte MIDI_KEY_SIGNATURE = 0x59; Chris@301: static const MIDIByte MIDI_SEQUENCER_SPECIFIC = 0x7F; Chris@301: static const MIDIByte MIDI_CONTROLLER_BANK_MSB = 0x00; Chris@301: static const MIDIByte MIDI_CONTROLLER_VOLUME = 0x07; Chris@301: static const MIDIByte MIDI_CONTROLLER_BANK_LSB = 0x20; Chris@301: static const MIDIByte MIDI_CONTROLLER_MODULATION = 0x01; Chris@301: static const MIDIByte MIDI_CONTROLLER_PAN = 0x0A; Chris@301: static const MIDIByte MIDI_CONTROLLER_SUSTAIN = 0x40; Chris@301: static const MIDIByte MIDI_CONTROLLER_RESONANCE = 0x47; Chris@301: static const MIDIByte MIDI_CONTROLLER_RELEASE = 0x48; Chris@301: static const MIDIByte MIDI_CONTROLLER_ATTACK = 0x49; Chris@301: static const MIDIByte MIDI_CONTROLLER_FILTER = 0x4A; Chris@301: static const MIDIByte MIDI_CONTROLLER_REVERB = 0x5B; Chris@301: static const MIDIByte MIDI_CONTROLLER_CHORUS = 0x5D; Chris@301: static const MIDIByte MIDI_CONTROLLER_NRPN_1 = 0x62; Chris@301: static const MIDIByte MIDI_CONTROLLER_NRPN_2 = 0x63; Chris@301: static const MIDIByte MIDI_CONTROLLER_RPN_1 = 0x64; Chris@301: static const MIDIByte MIDI_CONTROLLER_RPN_2 = 0x65; Chris@301: static const MIDIByte MIDI_CONTROLLER_SOUNDS_OFF = 0x78; Chris@301: static const MIDIByte MIDI_CONTROLLER_RESET = 0x79; Chris@301: static const MIDIByte MIDI_CONTROLLER_LOCAL = 0x7A; Chris@301: static const MIDIByte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B; Chris@301: static const MIDIByte MIDI_PERCUSSION_CHANNEL = 9; Chris@301: } Chris@301: Chris@301: class MIDIEvent Chris@301: { Chris@301: public: Chris@301: MIDIEvent(unsigned long deltaTime, Chris@1038: int eventCode, Chris@1038: int data1 = 0, Chris@1038: int data2 = 0) : Chris@1429: m_deltaTime(deltaTime), Chris@1429: m_duration(0), Chris@1429: m_metaEventCode(0) Chris@1038: { Chris@1038: if (eventCode < 0 || eventCode > 0xff || Chris@1038: data1 < 0 || data1 > 0xff || Chris@1038: data2 < 0 || data2 > 0xff) { Chris@1038: throw std::domain_error("not all args within byte range"); Chris@1038: } Chris@1038: m_eventCode = MIDIByte(eventCode); Chris@1038: m_data1 = MIDIByte(data1); Chris@1038: m_data2 = MIDIByte(data2); Chris@1038: } Chris@301: Chris@301: MIDIEvent(unsigned long deltaTime, Chris@301: MIDIByte eventCode, Chris@301: MIDIByte metaEventCode, Chris@301: const std::string &metaMessage) : Chris@1429: m_deltaTime(deltaTime), Chris@1429: m_duration(0), Chris@1429: m_eventCode(eventCode), Chris@1429: m_data1(0), Chris@1429: m_data2(0), Chris@1429: m_metaEventCode(metaEventCode), Chris@1429: m_metaMessage(metaMessage) Chris@301: { } Chris@301: Chris@301: MIDIEvent(unsigned long deltaTime, Chris@301: MIDIByte eventCode, Chris@301: const std::string &sysEx) : Chris@1429: m_deltaTime(deltaTime), Chris@1429: m_duration(0), Chris@1429: m_eventCode(eventCode), Chris@1429: m_data1(0), Chris@1429: m_data2(0), Chris@1429: m_metaEventCode(0), Chris@1429: m_metaMessage(sysEx) Chris@301: { } Chris@301: Chris@1733: MIDIEvent(const MIDIEvent &) =default; Chris@1733: MIDIEvent& operator=(const MIDIEvent &) =default; Chris@1733: Chris@301: ~MIDIEvent() { } Chris@301: Chris@301: void setTime(const unsigned long &time) { m_deltaTime = time; } Chris@301: void setDuration(const unsigned long& duration) { m_duration = duration;} Chris@301: unsigned long addTime(const unsigned long &time) { Chris@1429: m_deltaTime += time; Chris@1429: return m_deltaTime; Chris@301: } Chris@301: Chris@301: MIDIByte getMessageType() const Chris@301: { return (m_eventCode & MIDIConstants::MIDI_MESSAGE_TYPE_MASK); } Chris@301: Chris@301: MIDIByte getChannelNumber() const Chris@301: { return (m_eventCode & MIDIConstants::MIDI_CHANNEL_NUM_MASK); } Chris@301: Chris@301: unsigned long getTime() const { return m_deltaTime; } Chris@301: unsigned long getDuration() const { return m_duration; } Chris@301: Chris@301: MIDIByte getPitch() const { return m_data1; } Chris@301: MIDIByte getVelocity() const { return m_data2; } Chris@301: MIDIByte getData1() const { return m_data1; } Chris@301: MIDIByte getData2() const { return m_data2; } Chris@301: MIDIByte getEventCode() const { return m_eventCode; } Chris@301: Chris@301: bool isMeta() const { return (m_eventCode == MIDIConstants::MIDI_FILE_META_EVENT); } Chris@301: Chris@301: MIDIByte getMetaEventCode() const { return m_metaEventCode; } Chris@301: std::string getMetaMessage() const { return m_metaMessage; } Chris@301: void setMetaMessage(const std::string &meta) { m_metaMessage = meta; } Chris@301: Chris@301: friend bool operator<(const MIDIEvent &a, const MIDIEvent &b); Chris@301: Chris@301: private: Chris@301: unsigned long m_deltaTime; Chris@301: unsigned long m_duration; Chris@301: MIDIByte m_eventCode; Chris@301: MIDIByte m_data1; // or Note Chris@301: MIDIByte m_data2; // or Velocity Chris@301: MIDIByte m_metaEventCode; Chris@301: std::string m_metaMessage; Chris@301: }; Chris@301: Chris@301: // Comparator for sorting Chris@301: // Chris@301: struct MIDIEventCmp Chris@301: { Chris@301: bool operator()(const MIDIEvent &mE1, const MIDIEvent &mE2) const Chris@301: { return mE1.getTime() < mE2.getTime(); } Chris@301: Chris@301: bool operator()(const MIDIEvent *mE1, const MIDIEvent *mE2) const Chris@301: { return mE1->getTime() < mE2->getTime(); } Chris@301: }; Chris@301: Chris@301: class MIDIException : virtual public std::exception Chris@301: { Chris@301: public: Chris@301: MIDIException(QString message) throw() : m_message(message) { Chris@301: std::cerr << "WARNING: MIDI exception: " Chris@1429: << message.toLocal8Bit().data() << std::endl; Chris@301: } Chris@301: virtual ~MIDIException() throw() { } Chris@301: Chris@1580: const char *what() const throw() override { Chris@1848: static QByteArray msg; Chris@1848: msg = m_message.toLocal8Bit(); Chris@1848: return msg.data(); Chris@301: } Chris@301: Chris@301: protected: Chris@301: QString m_message; Chris@301: }; Chris@301: Chris@301: #endif