2 Copyright (C) 2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 675 Mass Ave, Cambridge, MA 02139, USA.
21 using std::cerr; using std::endl;
23 #include <ardour/buffer.h>
26 static const int CPU_CACHE_ALIGN = 64;
28 static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
35 Buffer::create(DataType type, size_t capacity)
37 if (type == DataType::AUDIO)
38 return new AudioBuffer(capacity);
39 else if (type == DataType::MIDI)
40 return new MidiBuffer(capacity);
46 AudioBuffer::AudioBuffer(size_t capacity)
47 : Buffer(DataType::AUDIO, capacity)
51 _size = capacity; // For audio buffers, size = capacity (always)
53 #ifdef NO_POSIX_MEMALIGN
54 _data = (Sample *) malloc(sizeof(Sample) * capacity);
56 posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * capacity);
64 AudioBuffer::~AudioBuffer()
70 // FIXME: mirroring for MIDI buffers?
71 MidiBuffer::MidiBuffer(size_t capacity)
72 : Buffer(DataType::MIDI, capacity)
81 #ifdef NO_POSIX_MEMALIGN
82 _events = (MidiEvent *) malloc(sizeof(MidiEvent) * capacity);
83 _data = (Byte *) malloc(sizeof(Byte) * capacity * MAX_EVENT_SIZE);
85 posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MidiEvent) * capacity);
86 posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Byte) * capacity * MAX_EVENT_SIZE);
93 MidiBuffer::~MidiBuffer()
100 /** Read events from @a src starting at time @a offset into the START of this buffer, for
101 * time direction @a nframes. Relative time, where 0 = start of buffer.
103 * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts.
106 MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
108 assert(src.type() == DataType::MIDI);
109 const MidiBuffer& msrc = (MidiBuffer&)src;
111 assert(_capacity >= src.size());
117 for (size_t i=0; i < src.size(); ++i) {
118 const MidiEvent& ev = msrc[i];
119 if (ev.time >= offset && ev.time < offset+nframes) {
124 _silent = src.silent();
128 /** Push an event into the buffer.
130 * Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
131 * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
133 * @return false if operation failed (not enough room)
136 MidiBuffer::push_back(const MidiEvent& ev)
138 if (_size == _capacity)
141 Byte* const write_loc = _data + (_size * MAX_EVENT_SIZE);
143 memcpy(write_loc, ev.buffer, ev.size);
145 _events[_size].buffer = write_loc;
148 //cerr << "MidiBuffer: pushed, size = " << _size << endl;
156 /** Push an event into the buffer.
158 * Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
159 * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
161 * @return false if operation failed (not enough room)
164 MidiBuffer::push_back(const jack_midi_event_t& ev)
166 if (_size == _capacity)
169 Byte* const write_loc = _data + (_size * MAX_EVENT_SIZE);
171 memcpy(write_loc, ev.buffer, ev.size);
172 _events[_size].time = (double)ev.time;
173 _events[_size].size = ev.size;
174 _events[_size].buffer = write_loc;
177 //cerr << "MidiBuffer: pushed, size = " << _size << endl;
185 /** Reserve space for a new event in the buffer.
187 * This call is for copying MIDI directly into the buffer, the data location
188 * (of sufficient size to write \a size bytes) is returned, or NULL on failure.
189 * This call MUST be immediately followed by a write to the returned data
190 * location, or the buffer will be corrupted and very nasty things will happen.
193 MidiBuffer::reserve(double time, size_t size)
195 assert(size < MAX_EVENT_SIZE);
197 if (_size == _capacity)
200 Byte* const write_loc = _data + (_size * MAX_EVENT_SIZE);
202 _events[_size].time = time;
203 _events[_size].size = size;
204 _events[_size].buffer = write_loc;
207 //cerr << "MidiBuffer: reserved, size = " << _size << endl;
216 MidiBuffer::silence(nframes_t dur, nframes_t offset)
218 // FIXME use parameters
220 //assert(dur == _capacity);
222 memset(_events, 0, sizeof(MidiEvent) * _capacity);
223 memset(_data, 0, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
229 } // namespace ARDOUR