1 //========================================================= 2 // MusE 3 // Linux Music Editor 4 // $Id: mpevent.h,v 1.8.2.5 2009/11/25 09:09:43 terminator356 Exp $ 5 // 6 // (C) Copyright 1999-2002 Werner Schweer (ws@seh.de) 7 // (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) 8 // 9 // This program is free software; you can redistribute it and/or 10 // modify it under the terms of the GNU General Public License 11 // as published by the Free Software Foundation; version 2 of 12 // the License, or (at your option) any later version. 13 // 14 // This program is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with this program; if not, write to the Free Software 21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 // 23 //========================================================= 24 25 #ifndef __MPEVENT_H__ 26 #define __MPEVENT_H__ 27 28 #include <set> 29 #include "evdata.h" 30 #include "memory.h" 31 #include <cstddef> 32 33 // Play events ring buffer size 34 #define MIDI_FIFO_SIZE 4096 35 36 // Record events ring buffer size 37 #define MIDI_REC_FIFO_SIZE 256 38 39 namespace MusECore { 40 41 //--------------------------------------------------------- 42 // MEvent 43 // baseclass for MidiPlayEvent and MidiRecordEvent 44 //--------------------------------------------------------- 45 46 //--------------------------------------------------------- 47 // MEvent 48 //--------------------------------------------------------- 49 50 class MEvent { 51 unsigned _time; 52 EvData edata; 53 unsigned char _port, _channel, _type; 54 int _a, _b; 55 int _loopNum; // The loop count when the note was recorded. 56 57 public: MEvent()58 MEvent() : _time(0), _port(0), _channel(0), _type(0), _a(0), _b(0), _loopNum(0) { } MEvent(const MEvent & e)59 MEvent(const MEvent& e) : _time(e._time), edata(e.edata), _port(e._port), _channel(e._channel), 60 _type(e._type), _a(e._a), _b(e._b), _loopNum(e._loopNum) { } MEvent(unsigned tm,int p,int c,int t,int a,int b)61 MEvent(unsigned tm, int p, int c, int t, int a, int b) 62 : _time(tm), _port(p), _channel(c & 0xf), _type(t), _a(a), _b(b), _loopNum(0) { } 63 MEvent(unsigned t, int p, int type, const unsigned char* data, int len); MEvent(unsigned t,int p,int tpe,EvData d)64 MEvent(unsigned t, int p, int tpe, EvData d) : _time(t), edata(d), _port(p), _type(tpe), _loopNum(0) { } 65 ~MEvent()66 virtual ~MEvent() {} 67 68 MEvent& operator=(const MEvent& ed) { 69 _time = ed._time; 70 edata = ed.edata; 71 _port = ed._port; 72 _channel = ed._channel; 73 _type = ed._type; 74 _a = ed._a; 75 _b = ed._b; 76 _loopNum = ed._loopNum; 77 return *this; 78 } 79 80 int sortingWeight() const; 81 port()82 int port() const { return _port; } channel()83 int channel() const { return _channel; } type()84 int type() const { return _type; } dataA()85 int dataA() const { return _a; } dataB()86 int dataB() const { return _b; } time()87 unsigned time() const { return _time; } loopNum()88 int loopNum() const { return _loopNum; } 89 setPort(int val)90 void setPort(int val) { _port = val; } setChannel(int val)91 void setChannel(int val) { _channel = val; } setType(int val)92 void setType(int val) { _type = val; } setA(int val)93 void setA(int val) { _a = val; } setB(int val)94 void setB(int val) { _b = val; } setTime(unsigned val)95 void setTime(unsigned val) { _time = val; } setLoopNum(int n)96 void setLoopNum(int n) { _loopNum = n; } 97 eventData()98 const EvData& eventData() const { return edata; } data()99 unsigned char* data() { return edata.data(); } constData()100 const unsigned char* constData() const { return edata.constData(); } len()101 int len() const { return edata.dataLen(); } setData(const EvData & e)102 void setData(const EvData& e) { edata = e; } setData(const unsigned char * p,int len)103 void setData(const unsigned char* p, int len) { edata.setData(p, len); } 104 isNote()105 bool isNote() const { return _type == 0x90; } isNoteOff()106 bool isNoteOff() const { return (_type == 0x80)||(_type == 0x90 && _b == 0); } 107 bool operator<(const MEvent&) const; isValid()108 bool isValid() const { return _type != 0; } 109 110 // Returns a valid source controller number (above zero), 111 // translated from the event to proper internal control type. 112 // For example 113 // ME_CONTROLLER + Data(A = CTRL_HBANK) = CTRL_PROGRAM 114 // ME_CONTROLLER + Data(A = CTRL_LBANK) = CTRL_PROGRAM 115 // ME_PROGRAM = CTRL_PROGRAM 116 // ME_PITCHBEND = CTRL_PITCH 117 // ME_CONTROLLER + Data(A = ctrl) = ctrl 118 // Otherwise returns -1 if the event is not translatable to a controller, 119 // or an error occurred. 120 int translateCtrlNum() const; 121 }; 122 123 //--------------------------------------------------------- 124 // MidiRecordEvent 125 // allocated and deleted in midiseq thread context 126 //--------------------------------------------------------- 127 128 class MidiRecordEvent : public MEvent { 129 private: 130 unsigned int _tick; // To store tick when external sync is on, required besides frame. 131 public: MidiRecordEvent()132 MidiRecordEvent() : MEvent() {} MidiRecordEvent(const MidiRecordEvent & e)133 MidiRecordEvent(const MidiRecordEvent& e) : MEvent(e), _tick(e._tick) {} MidiRecordEvent(const MEvent & e)134 MidiRecordEvent(const MEvent& e) : MEvent(e), _tick(0) {} MidiRecordEvent(unsigned tm,int p,int c,int t,int a,int b)135 MidiRecordEvent(unsigned tm, int p, int c, int t, int a, int b) 136 : MEvent(tm, p, c, t, a, b) {} MidiRecordEvent(unsigned t,int p,int tpe,const unsigned char * data,int len)137 MidiRecordEvent(unsigned t, int p, int tpe, const unsigned char* data, int len) 138 : MEvent(t, p, tpe, data, len) {} MidiRecordEvent(unsigned t,int p,int type,EvData data)139 MidiRecordEvent(unsigned t, int p, int type, EvData data) 140 : MEvent(t, p, type, data) {} ~MidiRecordEvent()141 virtual ~MidiRecordEvent() {} 142 143 MidiRecordEvent& operator=(const MidiRecordEvent& e) { MEvent::operator=(e); _tick = e._tick; return *this; } 144 tick()145 unsigned int tick() {return _tick;} setTick(unsigned int tick)146 void setTick(unsigned int tick) {_tick = tick;} 147 }; 148 149 //--------------------------------------------------------- 150 // MidiPlayEvent 151 // allocated and deleted in audio thread context 152 //--------------------------------------------------------- 153 154 class MidiPlayEvent : public MEvent { 155 public: MidiPlayEvent()156 MidiPlayEvent() : MEvent() {} MidiPlayEvent(const MidiPlayEvent & e)157 MidiPlayEvent(const MidiPlayEvent& e) : MEvent(e) {} MidiPlayEvent(const MEvent & e)158 MidiPlayEvent(const MEvent& e) : MEvent(e) {} MidiPlayEvent(unsigned tm,int p,int c,int t,int a,int b)159 MidiPlayEvent(unsigned tm, int p, int c, int t, int a, int b) 160 : MEvent(tm, p, c, t, a, b) {} MidiPlayEvent(unsigned t,int p,int type,const unsigned char * data,int len)161 MidiPlayEvent(unsigned t, int p, int type, const unsigned char* data, int len) 162 : MEvent(t, p, type, data, len) {} MidiPlayEvent(unsigned t,int p,int type,EvData data)163 MidiPlayEvent(unsigned t, int p, int type, EvData data) 164 : MEvent(t, p, type, data) {} ~MidiPlayEvent()165 virtual ~MidiPlayEvent() {} 166 167 MidiPlayEvent& operator=(const MidiPlayEvent& e) { MEvent::operator=(e); return *this; } 168 }; 169 170 //--------------------------------------------------------- 171 // MidiRecFifo 172 //--------------------------------------------------------- 173 174 class MidiRecFifo { 175 MidiRecordEvent fifo[MIDI_REC_FIFO_SIZE]; 176 volatile int size; 177 int wIndex; 178 int rIndex; 179 180 public: MidiRecFifo()181 MidiRecFifo() { clear(); } 182 bool put(const MidiRecordEvent& event); // returns true on fifo overflow 183 MidiRecordEvent get(); 184 const MidiRecordEvent& peek(int = 0); 185 void remove(); isEmpty()186 bool isEmpty() const { return size == 0; } clear()187 void clear() { size = 0, wIndex = 0, rIndex = 0; } getSize()188 int getSize() const { return size; } 189 }; 190 191 //--------------------------------------------------------- 192 // audioMPEventRTalloc 193 //--------------------------------------------------------- 194 195 template <typename T> class audioMPEventRTalloc 196 { 197 private: 198 static TypedMemoryPool<T, 2048> pool; 199 200 public: 201 typedef T value_type; 202 typedef size_t size_type; 203 typedef ptrdiff_t difference_type; 204 205 typedef T* pointer; 206 typedef const T* const_pointer; 207 208 typedef T& reference; 209 typedef const T& const_reference; 210 address(reference x)211 pointer address(reference x) const { return &x; } address(const_reference x)212 const_pointer address(const_reference x) const { return &x; } 213 audioMPEventRTalloc()214 audioMPEventRTalloc() { } audioMPEventRTalloc(const audioMPEventRTalloc<U> &)215 template <typename U> audioMPEventRTalloc(const audioMPEventRTalloc<U>&) {} ~audioMPEventRTalloc()216 ~audioMPEventRTalloc() {} 217 218 pointer allocate(size_type n, void * = 0) { return static_cast<T*>(pool.alloc(n)); } deallocate(pointer p,size_type n)219 void deallocate(pointer p, size_type n) { pool.free(p, n); } 220 221 audioMPEventRTalloc<T>& operator=(const audioMPEventRTalloc&) { return *this; } construct(pointer p,const T & val)222 void construct(pointer p, const T& val) { new ((T*) p) T(val); } destroy(pointer p)223 void destroy(pointer p) { p->~T(); } max_size()224 size_type max_size() const { return size_t(-1); } 225 226 template <typename U> struct rebind { typedef audioMPEventRTalloc<U> other; }; 227 template <typename U> audioMPEventRTalloc& operator=(const audioMPEventRTalloc<U>&) { return *this; } 228 }; 229 230 //--------------------------------------------------------- 231 // seqMPEventRTalloc 232 //--------------------------------------------------------- 233 234 template <typename T> class seqMPEventRTalloc 235 { 236 private: 237 static TypedMemoryPool<T, 2048> pool; 238 239 public: 240 typedef T value_type; 241 typedef size_t size_type; 242 typedef ptrdiff_t difference_type; 243 244 typedef T* pointer; 245 typedef const T* const_pointer; 246 247 typedef T& reference; 248 typedef const T& const_reference; 249 address(reference x)250 pointer address(reference x) const { return &x; } address(const_reference x)251 const_pointer address(const_reference x) const { return &x; } 252 seqMPEventRTalloc()253 seqMPEventRTalloc() { } seqMPEventRTalloc(const seqMPEventRTalloc<U> &)254 template <typename U> seqMPEventRTalloc(const seqMPEventRTalloc<U>&) {} ~seqMPEventRTalloc()255 ~seqMPEventRTalloc() {} 256 257 pointer allocate(size_type n, void * = 0) { return static_cast<T*>(pool.alloc(n)); } deallocate(pointer p,size_type n)258 void deallocate(pointer p, size_type n) { pool.free(p, n); } 259 260 seqMPEventRTalloc<T>& operator=(const seqMPEventRTalloc&) { return *this; } construct(pointer p,const T & val)261 void construct(pointer p, const T& val) { new ((T*) p) T(val); } destroy(pointer p)262 void destroy(pointer p) { p->~T(); } max_size()263 size_type max_size() const { return size_t(-1); } 264 265 template <typename U> struct rebind { typedef seqMPEventRTalloc<U> other; }; 266 template <typename U> seqMPEventRTalloc& operator=(const seqMPEventRTalloc<U>&) { return *this; } 267 }; 268 269 //--------------------------------------------------------- 270 // MPEventList 271 // memory allocation in audio thread domain 272 //--------------------------------------------------------- 273 274 typedef std::multiset<MidiPlayEvent, std::less<MidiPlayEvent>, audioMPEventRTalloc<MidiPlayEvent> > MPEL; 275 276 class MPEventList : public MPEL { 277 public: 278 // Optimize to eliminate duplicate events at the SAME time. 279 // It will not handle duplicate events at DIFFERENT times. 280 // Replaces event if it already exists. 281 void add(const MidiPlayEvent& ev); 282 }; 283 284 typedef MPEventList::iterator iMPEvent; 285 typedef MPEventList::const_iterator ciMPEvent; 286 typedef std::pair<iMPEvent, iMPEvent> MPEventListRangePair_t; 287 288 //--------------------------------------------------------- 289 // SeqMPEventList 290 // memory allocation in sequencer thread domain 291 //--------------------------------------------------------- 292 293 typedef std::multiset<MidiPlayEvent, std::less<MidiPlayEvent>, seqMPEventRTalloc<MidiPlayEvent> > SMPEL; 294 295 class SeqMPEventList : public SMPEL { 296 public: 297 // Optimize to eliminate duplicate events at the SAME time. 298 // It will not handle duplicate events at DIFFERENT times. 299 // Replaces event if it already exists. 300 void add(const MidiPlayEvent& ev); 301 }; 302 303 typedef SeqMPEventList::iterator iSeqMPEvent; 304 typedef SeqMPEventList::const_iterator ciSeqMPEvent; 305 typedef std::pair<iSeqMPEvent, iSeqMPEvent> SeqMPEventListRangePair_t; 306 307 308 } // namespace MusECore 309 310 #endif 311 312