view midiFileReader/MIDIEvent.h @ 0:b299a65a3ad0

start project
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 16 Aug 2011 11:29:59 +0100
parents
children
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*
    This is a modified version of a source file from the 
    Rosegarden MIDI and audio sequencer and notation editor.
    This file copyright 2000-2010 Richard Bown and Chris Cannam.
  
    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy,
    modify, merge, publish, distribute, sublicense, and/or sell copies
    of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    Except as contained in this notice, the names of the authors
    shall not be used in advertising or otherwise to promote the sale,
    use or other dealings in this Software without prior written
    authorization.
*/

#ifndef _MIDI_EVENT_H_
#define _MIDI_EVENT_H_

#include <string>
#include <iostream>

typedef unsigned char MIDIByte;

namespace MIDIConstants
{
    static const char *const MIDI_FILE_HEADER         = "MThd";
    static const char *const MIDI_TRACK_HEADER        = "MTrk";

    static const MIDIByte MIDI_STATUS_BYTE_MASK       = 0x80;
    static const MIDIByte MIDI_MESSAGE_TYPE_MASK      = 0xF0;
    static const MIDIByte MIDI_CHANNEL_NUM_MASK       = 0x0F;

    static const MIDIByte MIDI_NOTE_OFF               = 0x80;
    static const MIDIByte MIDI_NOTE_ON                = 0x90;
    static const MIDIByte MIDI_POLY_AFTERTOUCH        = 0xA0;
    static const MIDIByte MIDI_CTRL_CHANGE            = 0xB0;
    static const MIDIByte MIDI_PROG_CHANGE            = 0xC0;
    static const MIDIByte MIDI_CHNL_AFTERTOUCH        = 0xD0;
    static const MIDIByte MIDI_PITCH_BEND             = 0xE0;
    static const MIDIByte MIDI_SELECT_CHNL_MODE       = 0xB0;
    static const MIDIByte MIDI_SYSTEM_EXCLUSIVE       = 0xF0;
    static const MIDIByte MIDI_TC_QUARTER_FRAME       = 0xF1;
    static const MIDIByte MIDI_SONG_POSITION_PTR      = 0xF2;
    static const MIDIByte MIDI_SONG_SELECT            = 0xF3;
    static const MIDIByte MIDI_TUNE_REQUEST           = 0xF6;
    static const MIDIByte MIDI_END_OF_EXCLUSIVE       = 0xF7;
    static const MIDIByte MIDI_TIMING_CLOCK           = 0xF8;
    static const MIDIByte MIDI_START                  = 0xFA;
    static const MIDIByte MIDI_CONTINUE               = 0xFB;
    static const MIDIByte MIDI_STOP                   = 0xFC;
    static const MIDIByte MIDI_ACTIVE_SENSING         = 0xFE;
    static const MIDIByte MIDI_SYSTEM_RESET           = 0xFF;
    static const MIDIByte MIDI_SYSEX_NONCOMMERCIAL    = 0x7D;
    static const MIDIByte MIDI_SYSEX_NON_RT           = 0x7E;
    static const MIDIByte MIDI_SYSEX_RT               = 0x7F;
    static const MIDIByte MIDI_SYSEX_RT_COMMAND       = 0x06;
    static const MIDIByte MIDI_SYSEX_RT_RESPONSE      = 0x07;
    static const MIDIByte MIDI_MMC_STOP               = 0x01;
    static const MIDIByte MIDI_MMC_PLAY               = 0x02;
    static const MIDIByte MIDI_MMC_DEFERRED_PLAY      = 0x03;
    static const MIDIByte MIDI_MMC_FAST_FORWARD       = 0x04;
    static const MIDIByte MIDI_MMC_REWIND             = 0x05;
    static const MIDIByte MIDI_MMC_RECORD_STROBE      = 0x06;
    static const MIDIByte MIDI_MMC_RECORD_EXIT        = 0x07;
    static const MIDIByte MIDI_MMC_RECORD_PAUSE       = 0x08;
    static const MIDIByte MIDI_MMC_PAUSE              = 0x08;
    static const MIDIByte MIDI_MMC_EJECT              = 0x0A;
    static const MIDIByte MIDI_MMC_LOCATE             = 0x44;
    static const MIDIByte MIDI_FILE_META_EVENT        = 0xFF;
    static const MIDIByte MIDI_SEQUENCE_NUMBER        = 0x00;
    static const MIDIByte MIDI_TEXT_EVENT             = 0x01;
    static const MIDIByte MIDI_COPYRIGHT_NOTICE       = 0x02;
    static const MIDIByte MIDI_TRACK_NAME             = 0x03;
    static const MIDIByte MIDI_INSTRUMENT_NAME        = 0x04;
    static const MIDIByte MIDI_LYRIC                  = 0x05;
    static const MIDIByte MIDI_TEXT_MARKER            = 0x06;
    static const MIDIByte MIDI_CUE_POINT              = 0x07;
    static const MIDIByte MIDI_CHANNEL_PREFIX         = 0x20;
    static const MIDIByte MIDI_CHANNEL_PREFIX_OR_PORT = 0x21;
    static const MIDIByte MIDI_END_OF_TRACK           = 0x2F;
    static const MIDIByte MIDI_SET_TEMPO              = 0x51;
    static const MIDIByte MIDI_SMPTE_OFFSET           = 0x54;
    static const MIDIByte MIDI_TIME_SIGNATURE         = 0x58;
    static const MIDIByte MIDI_KEY_SIGNATURE          = 0x59;
    static const MIDIByte MIDI_SEQUENCER_SPECIFIC     = 0x7F;
    static const MIDIByte MIDI_CONTROLLER_BANK_MSB      = 0x00;
    static const MIDIByte MIDI_CONTROLLER_VOLUME        = 0x07;
    static const MIDIByte MIDI_CONTROLLER_BANK_LSB      = 0x20;
    static const MIDIByte MIDI_CONTROLLER_MODULATION    = 0x01;
    static const MIDIByte MIDI_CONTROLLER_PAN           = 0x0A;
    static const MIDIByte MIDI_CONTROLLER_SUSTAIN       = 0x40;
    static const MIDIByte MIDI_CONTROLLER_RESONANCE     = 0x47;
    static const MIDIByte MIDI_CONTROLLER_RELEASE       = 0x48;
    static const MIDIByte MIDI_CONTROLLER_ATTACK        = 0x49;
    static const MIDIByte MIDI_CONTROLLER_FILTER        = 0x4A;
    static const MIDIByte MIDI_CONTROLLER_REVERB        = 0x5B;
    static const MIDIByte MIDI_CONTROLLER_CHORUS        = 0x5D;
    static const MIDIByte MIDI_CONTROLLER_NRPN_1        = 0x62;
    static const MIDIByte MIDI_CONTROLLER_NRPN_2        = 0x63;
    static const MIDIByte MIDI_CONTROLLER_RPN_1         = 0x64;
    static const MIDIByte MIDI_CONTROLLER_RPN_2         = 0x65;
    static const MIDIByte MIDI_CONTROLLER_SOUNDS_OFF    = 0x78;
    static const MIDIByte MIDI_CONTROLLER_RESET         = 0x79;
    static const MIDIByte MIDI_CONTROLLER_LOCAL         = 0x7A;
    static const MIDIByte MIDI_CONTROLLER_ALL_NOTES_OFF = 0x7B;
    static const MIDIByte MIDI_PERCUSSION_CHANNEL       = 9;

    typedef enum {
	MIDI_SINGLE_TRACK_FILE          = 0x00,
	MIDI_SIMULTANEOUS_TRACK_FILE    = 0x01,
	MIDI_SEQUENTIAL_TRACK_FILE      = 0x02,
	MIDI_FILE_BAD_FORMAT            = 0xFF
    } MIDIFileFormatType;
}

class MIDIEvent
{
public:
    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 std::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 std::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;
    }

    int getMessageType() const
        { return (m_eventCode & MIDIConstants::MIDI_MESSAGE_TYPE_MASK); }

    int getChannelNumber() const
        { return (m_eventCode & MIDIConstants::MIDI_CHANNEL_NUM_MASK); }

    unsigned long getTime() const { return m_deltaTime; }
    unsigned long getDuration() const { return m_duration; }

    int getPitch() const { return m_data1; }
    int getVelocity() const { return m_data2; }
    int getData1() const { return m_data1; }
    int getData2() const { return m_data2; }
    int getEventCode() const { return m_eventCode; }

    bool isMeta() const { return (m_eventCode == MIDIConstants::MIDI_FILE_META_EVENT); }

    int getMetaEventCode() const { return m_metaEventCode; }
    std::string getMetaMessage() const { return m_metaMessage; }
    void setMetaMessage(const std::string &meta) { m_metaMessage = meta; }

    friend bool operator<(const MIDIEvent &a, const MIDIEvent &b);

private:
    unsigned long  m_deltaTime;
    unsigned long  m_duration;
    MIDIByte       m_eventCode;
    MIDIByte       m_data1;         // or Note
    MIDIByte       m_data2;         // or Velocity
    MIDIByte       m_metaEventCode;
    std::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(std::string message) throw() : m_message(message) {
        std::cerr << "WARNING: MIDI exception: " << message.c_str() << std::endl;
    }
    virtual ~MIDIException() throw() { }

    virtual const char *what() const throw() {
	return m_message.c_str();
    }

protected:
    std::string m_message;
};

#endif