ardour
midi_buffer.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006-2009 Paul Davis
3  Author: David Robillard
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the Free
7  Software Foundation; either version 2 of the License, or (at your option)
8  any later version.
9 
10  This program is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13  for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #ifndef __ardour_midi_buffer_h__
21 #define __ardour_midi_buffer_h__
22 
23 #include "evoral/midi_util.h"
24 #include "evoral/EventSink.hpp"
25 
26 #include "midi++/event.h"
27 
28 #include "ardour/buffer.h"
29 #include "ardour/parameter_types.h"
30 
31 namespace ARDOUR {
32 
33 
35 class LIBARDOUR_API MidiBuffer : public Buffer, public Evoral::EventSink<framepos_t>
36 {
37 public:
39 
40  MidiBuffer(size_t capacity);
41  ~MidiBuffer();
42 
43  void silence (framecnt_t nframes, framecnt_t offset = 0);
44  void read_from (const Buffer& src, framecnt_t nframes, framecnt_t dst_offset = 0, framecnt_t src_offset = 0);
45  void merge_from (const Buffer& src, framecnt_t nframes, framecnt_t dst_offset = 0, framecnt_t src_offset = 0);
46 
47  void copy(const MidiBuffer& copy);
48 
49  bool push_back(const Evoral::MIDIEvent<TimeType>& event);
50  bool push_back(TimeType time, size_t size, const uint8_t* data);
51 
52  uint8_t* reserve(TimeType time, size_t size);
53 
54  void resize(size_t);
55  size_t size() const { return _size; }
56  bool empty() const { return _size == 0; }
57 
58  bool insert_event(const Evoral::MIDIEvent<TimeType>& event);
59  bool merge_in_place(const MidiBuffer &other);
60 
62  uint32_t write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf);
63 
64  template<typename BufferType, typename EventType>
66  {
67  public:
69  : buffer(&b), offset(o) {}
70 
72  : buffer (o.buffer), offset(o.offset) {}
73 
75  if (&o != this) {
76  buffer = o.buffer;
77  offset = o.offset;
78  }
79  return *this;
80  }
81 
82  inline EventType operator*() const {
83  uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType);
84  int event_size = Evoral::midi_event_size(ev_start);
85  assert(event_size >= 0);
86  return EventType(midi_parameter_type(*ev_start),
87  *((TimeType*)(buffer->_data + offset)),
88  event_size, ev_start);
89  }
90 
91  inline EventType operator*() {
92  uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType);
93  int event_size = Evoral::midi_event_size(ev_start);
94  assert(event_size >= 0);
95  return EventType(midi_parameter_type(*ev_start),
96  *(reinterpret_cast<TimeType*>((uintptr_t)(buffer->_data + offset))),
97  event_size, ev_start);
98  }
99 
100  inline TimeType * timeptr() {
101  return reinterpret_cast<TimeType*>((uintptr_t)(buffer->_data + offset));
102  }
103 
105  uint8_t* ev_start = buffer->_data + offset + sizeof(TimeType);
106  int event_size = Evoral::midi_event_size(ev_start);
107  assert(event_size >= 0);
108  offset += sizeof(TimeType) + event_size;
109  return *this;
110  }
111 
112  inline bool operator!=(const iterator_base<BufferType, EventType>& other) const {
113  return (buffer != other.buffer) || (offset != other.offset);
114  }
115 
116  inline bool operator==(const iterator_base<BufferType, EventType>& other) const {
117  return (buffer == other.buffer) && (offset == other.offset);
118  }
119 
120  BufferType* buffer;
121  size_t offset;
122  };
123 
126 
127  iterator begin() { return iterator(*this, 0); }
128  iterator end() { return iterator(*this, _size); }
129 
130  const_iterator begin() const { return const_iterator(*this, 0); }
131  const_iterator end() const { return const_iterator(*this, _size); }
132 
133  iterator erase(const iterator& i) {
134  assert (i.buffer == this);
135  uint8_t* ev_start = _data + i.offset + sizeof (TimeType);
136  int event_size = Evoral::midi_event_size (ev_start);
137 
138  if (event_size < 0) {
139  /* unknown size, sysex: return end() */
140  return end();
141  }
142 
143  size_t total_data_deleted = sizeof(TimeType) + event_size;
144 
145  if (i.offset + total_data_deleted > _size) {
146  _size = 0;
147  return end();
148  }
149 
150  /* we need to avoid the temporary malloc that memmove would do,
151  so copy by hand. remember: this is small amounts of data ...
152  */
153  size_t a, b;
154  for (a = i.offset, b = i.offset + total_data_deleted; b < _size; ++b, ++a) {
155  _data[a] = _data[b];
156  }
157 
158  _size -= total_data_deleted;
159 
160  /* all subsequent iterators are now invalid, and the one we
161  * return should refer to the event we copied, which was after
162  * the one we just erased.
163  */
164 
165  return iterator (*this, i.offset);
166  }
167 
168  uint8_t* data() const { return _data; }
169 
175  static bool second_simultaneous_midi_byte_is_first (uint8_t, uint8_t);
176 
177 private:
178  friend class iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >;
179  friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
180 
181  uint8_t* _data;
182  pframes_t _size;
183 };
184 
185 } // namespace ARDOUR
186 
187 #endif // __ardour_midi_buffer_h__
size_t size() const
Definition: midi_buffer.h:55
static int midi_event_size(uint8_t status)
Definition: midi_util.h:39
bool empty() const
Definition: midi_buffer.h:56
const_iterator begin() const
Definition: midi_buffer.h:130
uint32_t pframes_t
Definition: types.h:61
framepos_t TimeType
Definition: midi_buffer.h:38
uint8_t * data() const
Definition: midi_buffer.h:168
int64_t framecnt_t
Definition: types.h:76
Definition: amp.h:29
iterator erase(const iterator &i)
Definition: midi_buffer.h:133
int64_t framepos_t
Definition: types.h:66
iterator_base< const MidiBuffer, const Evoral::MIDIEvent< TimeType > > const_iterator
Definition: midi_buffer.h:125
uint32_t EventType
Definition: types.hpp:43
#define LIBARDOUR_API
EventType operator*() const
Definition: midi_buffer.h:82
bool operator==(const iterator_base< BufferType, EventType > &other) const
Definition: midi_buffer.h:116
iterator_base< MidiBuffer, Evoral::MIDIEvent< TimeType > > iterator
Definition: midi_buffer.h:124
iterator_base< BufferType, EventType > & operator++()
Definition: midi_buffer.h:104
iterator begin()
Definition: midi_buffer.h:127
AutomationType midi_parameter_type(uint8_t status)
const_iterator end() const
Definition: midi_buffer.h:131
bool operator!=(const iterator_base< BufferType, EventType > &other) const
Definition: midi_buffer.h:112