2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
|
|
|
// Copyright (C) 2002-2011 Werner Schweer
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2
|
|
|
|
// as published by the Free Software Foundation and appearing in
|
|
|
|
// the file LICENCE.GPL
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#ifndef __EVENT_H__
|
|
|
|
#define __EVENT_H__
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
#include <map>
|
|
|
|
|
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
class Note;
|
2016-11-19 11:51:21 +01:00
|
|
|
class XmlWriter;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-08-08 17:46:56 +02:00
|
|
|
enum class BeatType : char;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
2013-04-15 10:38:16 +02:00
|
|
|
// Event types
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ME_INVALID = 0,
|
|
|
|
ME_NOTEOFF = 0x80,
|
|
|
|
ME_NOTEON = 0x90,
|
|
|
|
ME_POLYAFTER = 0xa0,
|
|
|
|
ME_CONTROLLER = 0xb0,
|
|
|
|
ME_PROGRAM = 0xc0,
|
|
|
|
ME_AFTERTOUCH = 0xd0,
|
|
|
|
ME_PITCHBEND = 0xe0,
|
|
|
|
ME_SYSEX = 0xf0,
|
|
|
|
ME_META = 0xff,
|
|
|
|
ME_SONGPOS = 0xf2,
|
|
|
|
ME_ENDSYSEX = 0xf7,
|
|
|
|
ME_CLOCK = 0xf8,
|
|
|
|
ME_START = 0xfa,
|
|
|
|
ME_CONTINUE = 0xfb,
|
|
|
|
ME_STOP = 0xfc,
|
|
|
|
ME_SENSE = 0xfe, // active sense (used by yamaha)
|
|
|
|
|
2013-04-08 10:31:17 +02:00
|
|
|
ME_NOTE = 0x1,
|
|
|
|
ME_CHORD = 0x2,
|
|
|
|
ME_TICK1 = 0x3, // metronome tick akzent
|
2013-08-13 05:01:38 +02:00
|
|
|
ME_TICK2 = 0x4, // metronome tick
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Midi Meta Events
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
enum {
|
|
|
|
META_SEQUENCE_NUMBER = 0,
|
|
|
|
META_TEXT = 1,
|
|
|
|
META_COPYRIGHT = 2,
|
|
|
|
META_TRACK_NAME = 3,
|
|
|
|
META_INSTRUMENT_NAME = 4,
|
|
|
|
META_LYRIC = 5,
|
|
|
|
META_MARKER = 6,
|
|
|
|
META_CUE_POINT = 7,
|
2013-07-17 11:58:27 +02:00
|
|
|
META_PROGRAM_NAME = 8, // MIDI Meta Events 8 and 9 were defined as above by the MMA in 1998
|
|
|
|
META_DEVICE_NAME = 9, // It is therefore necessary to redefine MuseScore's private meta events
|
|
|
|
META_TRACK_COMMENT = 0xf, // Using the block starting 0x10 seems sensible as that is currently clear
|
|
|
|
META_TITLE = 0x10, // mscore extension
|
|
|
|
META_SUBTITLE = 0x11, // mscore extension
|
|
|
|
META_COMPOSER = 0x12, // mscore extension
|
|
|
|
META_TRANSLATOR = 0x13, // mscore extension
|
|
|
|
META_POET = 0x14, // mscore extension
|
2012-05-26 14:26:10 +02:00
|
|
|
META_PORT_CHANGE = 0x21,
|
|
|
|
META_CHANNEL_PREFIX = 0x22,
|
|
|
|
META_EOT = 0x2f, // end of track
|
|
|
|
META_TEMPO = 0x51,
|
|
|
|
META_TIME_SIGNATURE = 0x58,
|
2015-01-30 14:09:49 +01:00
|
|
|
META_KEY_SIGNATURE = 0x59,
|
|
|
|
META_SPECIFIC = 0x7F // sequencer specific
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Midi Controller
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
enum {
|
|
|
|
CTRL_HBANK = 0x00,
|
|
|
|
CTRL_LBANK = 0x20,
|
|
|
|
|
|
|
|
CTRL_HDATA = 0x06,
|
|
|
|
CTRL_LDATA = 0x26,
|
|
|
|
|
|
|
|
CTRL_HNRPN = 0x63,
|
|
|
|
CTRL_LNRPN = 0x62,
|
|
|
|
|
|
|
|
CTRL_HRPN = 0x65,
|
|
|
|
CTRL_LRPN = 0x64,
|
|
|
|
|
|
|
|
CTRL_MODULATION = 0x01,
|
2018-12-22 11:43:23 +01:00
|
|
|
CTRL_BREATH = 0x02,
|
|
|
|
CTRL_FOOT = 0x04,
|
2012-05-26 14:26:10 +02:00
|
|
|
CTRL_PORTAMENTO_TIME = 0x05,
|
|
|
|
CTRL_VOLUME = 0x07,
|
|
|
|
CTRL_PANPOT = 0x0a,
|
|
|
|
CTRL_EXPRESSION = 0x0b,
|
|
|
|
CTRL_SUSTAIN = 0x40,
|
|
|
|
CTRL_PORTAMENTO = 0x41,
|
|
|
|
CTRL_SOSTENUTO = 0x42,
|
|
|
|
CTRL_SOFT_PEDAL = 0x43,
|
|
|
|
CTRL_HARMONIC_CONTENT = 0x47,
|
|
|
|
CTRL_RELEASE_TIME = 0x48,
|
|
|
|
CTRL_ATTACK_TIME = 0x49,
|
|
|
|
|
|
|
|
CTRL_BRIGHTNESS = 0x4a,
|
|
|
|
CTRL_PORTAMENTO_CONTROL = 0x54,
|
|
|
|
CTRL_REVERB_SEND = 0x5b,
|
|
|
|
CTRL_CHORUS_SEND = 0x5d,
|
|
|
|
CTRL_VARIATION_SEND = 0x5e,
|
|
|
|
|
|
|
|
CTRL_ALL_SOUNDS_OFF = 0x78, // 120
|
|
|
|
CTRL_RESET_ALL_CTRL = 0x79, // 121
|
|
|
|
CTRL_LOCAL_OFF = 0x7a, // 122
|
2013-03-26 19:59:51 +01:00
|
|
|
CTRL_ALL_NOTES_OFF = 0x7b, // 123
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
// special midi events are mapped to internal
|
|
|
|
// controller
|
|
|
|
//
|
2013-03-27 20:10:14 +01:00
|
|
|
CTRL_PROGRAM = 0x81,
|
2015-06-02 20:05:44 +02:00
|
|
|
/* = 0x82,*/
|
2013-03-27 20:10:14 +01:00
|
|
|
CTRL_PRESS = 0x83,
|
2013-05-11 01:35:40 +02:00
|
|
|
CTRL_POLYAFTER = 0x84
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-04-15 10:38:16 +02:00
|
|
|
// MidiCoreEvent
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-04-15 10:38:16 +02:00
|
|
|
class MidiCoreEvent {
|
2013-04-08 10:31:17 +02:00
|
|
|
protected:
|
2013-04-25 10:52:02 +02:00
|
|
|
uchar _type = 0;
|
|
|
|
uchar _channel = 0;
|
|
|
|
uchar _a = 0;
|
|
|
|
uchar _b = 0;
|
2013-04-08 10:31:17 +02:00
|
|
|
|
|
|
|
public:
|
2013-04-15 10:38:16 +02:00
|
|
|
MidiCoreEvent() {}
|
|
|
|
MidiCoreEvent(uchar t, uchar c, uchar a, uchar b)
|
2013-05-11 01:35:40 +02:00
|
|
|
: _type(t), _channel(c), _a(a), _b(b) {}
|
2013-04-08 10:31:17 +02:00
|
|
|
|
|
|
|
void set(uchar t, uchar c, uchar a, uchar b) {
|
|
|
|
_type = t;
|
|
|
|
_channel = c;
|
|
|
|
_a = a;
|
|
|
|
_b = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
uchar type() const { return _type; }
|
|
|
|
void setType(uchar t) { _type = t; }
|
|
|
|
uchar channel() const { return _channel; }
|
|
|
|
void setChannel(uchar c) { _channel = c; }
|
|
|
|
|
|
|
|
int dataA() const { return _a; }
|
|
|
|
int pitch() const { return _a; }
|
|
|
|
int controller() const { return _a; }
|
|
|
|
|
|
|
|
void setDataA(int v) { _a = v; }
|
|
|
|
void setPitch(int v) { _a = v; }
|
|
|
|
void setController(int v) { _a = v; }
|
|
|
|
|
|
|
|
int dataB() const { return _b; }
|
|
|
|
int velo() const { return _b; }
|
|
|
|
int value() const { return _b; }
|
|
|
|
|
|
|
|
void setDataB(int v) { _b = v; }
|
|
|
|
void setVelo(int v) { _b = v; }
|
|
|
|
void setValue(int v) { _b = v; }
|
|
|
|
|
|
|
|
void setData(int a, int b) { _a = a; _b = b; }
|
|
|
|
void setData(int t, int a, int b) { _type = t; _a = a; _b = b; }
|
|
|
|
|
2013-04-15 10:38:16 +02:00
|
|
|
bool isChannelEvent() const;
|
2016-11-19 11:51:21 +01:00
|
|
|
void write(XmlWriter&) const;
|
2013-04-25 10:52:02 +02:00
|
|
|
bool operator==(const MidiCoreEvent& e) const {
|
|
|
|
return e._type == _type && e._channel == _channel && e._a == _a && e._b == _b;
|
|
|
|
}
|
2013-04-15 10:38:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// MidiEvent
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class MidiEvent : public MidiCoreEvent {
|
|
|
|
|
|
|
|
protected:
|
|
|
|
uchar* _edata; // always zero terminated (_data[_len] == 0; )
|
|
|
|
int _len;
|
|
|
|
int _metaType;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MidiEvent() {}
|
|
|
|
MidiEvent(uchar t, uchar c, uchar a, uchar b)
|
2013-05-11 01:35:40 +02:00
|
|
|
: MidiCoreEvent(t, c, a, b), _edata(0), _len(0) {}
|
2013-04-15 10:38:16 +02:00
|
|
|
|
|
|
|
const uchar* edata() const { return _edata; }
|
|
|
|
void setEData(uchar* d) { _edata = d; }
|
|
|
|
int len() const { return _len; }
|
|
|
|
void setLen(int l) { _len = l; }
|
|
|
|
int metaType() const { return _metaType; }
|
|
|
|
void setMetaType(int v) { _metaType = v; }
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// PlayEvent
|
2013-04-25 09:50:55 +02:00
|
|
|
// interface to Synthesizer
|
2013-04-15 10:38:16 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class PlayEvent : public MidiCoreEvent {
|
|
|
|
|
|
|
|
protected:
|
|
|
|
float _tuning = .0f;
|
|
|
|
|
|
|
|
public:
|
2013-04-25 09:50:55 +02:00
|
|
|
PlayEvent() : MidiCoreEvent() {}
|
|
|
|
PlayEvent(const MidiCoreEvent& e) : MidiCoreEvent(e) {}
|
|
|
|
PlayEvent(uchar t, uchar c, uchar a, uchar b)
|
2013-05-11 01:35:40 +02:00
|
|
|
: MidiCoreEvent(t, c, a, b) {}
|
2013-04-08 10:31:17 +02:00
|
|
|
float tuning() const { return _tuning; }
|
|
|
|
void setTuning(float v) { _tuning = v; }
|
|
|
|
};
|
|
|
|
|
2013-04-25 09:50:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// NPlayEvent
|
|
|
|
// used for Sequencer interface
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class NPlayEvent : public PlayEvent {
|
2018-03-30 21:43:00 +02:00
|
|
|
const Note* _note = 0;
|
2018-10-15 18:23:38 +02:00
|
|
|
int _origin = -1;
|
2018-03-30 21:43:00 +02:00
|
|
|
int _discard = 0;
|
2013-04-25 09:50:55 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
NPlayEvent() : PlayEvent() {}
|
|
|
|
NPlayEvent(uchar t, uchar c, uchar a, uchar b)
|
2013-05-11 01:35:40 +02:00
|
|
|
: PlayEvent(t, c, a, b) {}
|
2013-04-25 09:50:55 +02:00
|
|
|
NPlayEvent(const MidiCoreEvent& e) : PlayEvent(e) {}
|
2016-08-08 17:46:56 +02:00
|
|
|
NPlayEvent(BeatType beatType);
|
2018-10-15 18:23:38 +02:00
|
|
|
|
2018-03-30 21:43:00 +02:00
|
|
|
const Note* note() const { return _note; }
|
|
|
|
void setNote(const Note* v) { _note = v; }
|
2018-10-15 18:23:38 +02:00
|
|
|
|
|
|
|
int getOriginatingStaff() const { return _origin; }
|
|
|
|
void setOriginatingStaff(int i) { _origin = i; }
|
2018-03-30 21:43:00 +02:00
|
|
|
void setDiscard(int d) { _discard = d; }
|
|
|
|
int discard() const { return _discard; }
|
2019-07-25 15:54:21 +02:00
|
|
|
bool isMuted() const;
|
2013-04-25 09:50:55 +02:00
|
|
|
};
|
|
|
|
|
2013-04-08 10:31:17 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Event
|
|
|
|
//---------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-04-08 10:31:17 +02:00
|
|
|
class Event : public PlayEvent {
|
|
|
|
int _ontime;
|
|
|
|
int _noquantOntime;
|
|
|
|
int _noquantDuration;
|
|
|
|
int _duration;
|
|
|
|
int _tpc; // tonal pitch class
|
|
|
|
int _voice;
|
|
|
|
QList<Event> _notes;
|
|
|
|
uchar* _edata; // always zero terminated (_data[_len] == 0; )
|
|
|
|
int _len;
|
|
|
|
int _metaType;
|
|
|
|
const Note* _note;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
Event();
|
|
|
|
Event(const Event&);
|
|
|
|
Event(int t);
|
|
|
|
~Event();
|
|
|
|
bool operator==(const Event&) const;
|
|
|
|
|
2016-11-19 11:51:21 +01:00
|
|
|
void write(XmlWriter&) const;
|
2012-05-26 14:26:10 +02:00
|
|
|
void dump() const;
|
|
|
|
|
|
|
|
|
2013-04-08 10:31:17 +02:00
|
|
|
int noquantOntime() const { return _noquantOntime; }
|
|
|
|
void setNoquantOntime(int v) { _noquantOntime = v; }
|
|
|
|
int noquantDuration() const { return _noquantDuration; }
|
|
|
|
void setNoquantDuration(int v) { _noquantDuration = v; }
|
|
|
|
|
|
|
|
int ontime() const { return _ontime; }
|
|
|
|
void setOntime(int v) { _ontime = v; }
|
|
|
|
|
|
|
|
int duration() const { return _duration; }
|
|
|
|
void setDuration(int v) { _duration = v; }
|
|
|
|
int voice() const { return _voice; }
|
|
|
|
void setVoice(int val) { _voice = val; }
|
|
|
|
int offtime() const { return _ontime + _duration; }
|
|
|
|
QList<Event>& notes() { return _notes; }
|
|
|
|
const uchar* edata() const { return _edata; }
|
|
|
|
void setEData(uchar* d) { _edata = d; }
|
|
|
|
int len() const { return _len; }
|
|
|
|
void setLen(int l) { _len = l; }
|
|
|
|
int metaType() const { return _metaType; }
|
|
|
|
void setMetaType(int v) { _metaType = v; }
|
|
|
|
int tpc() const { return _tpc; }
|
|
|
|
void setTpc(int v) { _tpc = v; }
|
|
|
|
const Note* note() const { return _note; }
|
|
|
|
void setNote(const Note* v) { _note = v; }
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// EventList
|
|
|
|
// EventMap
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class EventList : public QList<Event> {
|
|
|
|
public:
|
|
|
|
void insert(const Event&);
|
|
|
|
void insertNote(int channel, Note*);
|
|
|
|
};
|
|
|
|
|
2018-10-15 18:23:38 +02:00
|
|
|
class EventMap : public std::multimap<int, NPlayEvent> {
|
|
|
|
int _highestChannel = 15;
|
|
|
|
public:
|
|
|
|
void fixupMIDI();
|
|
|
|
void registerChannel(int c) { if (c > _highestChannel) _highestChannel = c; }
|
|
|
|
};
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
typedef EventList::iterator iEvent;
|
|
|
|
typedef EventList::const_iterator ciEvent;
|
|
|
|
|
|
|
|
extern QString midiMetaName(int meta);
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
#endif
|
|
|
|
|