summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/buffer_set.h
blob: 3a4b9c834496a188d49c82a1650fad87d5f696f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
 * Copyright (C) 2006-2016 David Robillard <d@drobilla.net>
 * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
 * Copyright (C) 2013-2016 Robin Gareus <robin@gareus.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __ardour_buffer_set_h__
#define __ardour_buffer_set_h__

#ifdef WAF_BUILD
#include "libardour-config.h"
#endif

#include <cassert>
#include <vector>
#include "ardour/chan_count.h"
#include "ardour/data_type.h"
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"

#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
#include "evoral/Event.h"
struct _VstEvents;
typedef struct _VstEvents VstEvents;
struct _VstMidiEvent;
typedef struct _VstMidiEvent VstMidiEvent;
#endif

#ifdef LV2_SUPPORT
typedef struct LV2_Evbuf_Impl LV2_Evbuf;
#endif

namespace ARDOUR {

class Buffer;
class AudioBuffer;
class MidiBuffer;
class PortSet;

/** A set of buffers of various types.
 *
 * These are mainly accessed from Session and passed around as scratch buffers
 * (eg as parameters to run() methods) to do in-place signal processing.
 *
 * There are two types of counts associated with a BufferSet - available,
 * and the 'use count'.  Available is the actual number of allocated buffers
 * (and so is the maximum acceptable value for the use counts).
 *
 * The use counts are how things determine the form of their input and inform
 * others the form of their output (eg what they did to the BufferSet).
 * Setting the use counts is realtime safe.
 */
class LIBARDOUR_API BufferSet
{
public:
	BufferSet();
	~BufferSet();

	void clear();

	void attach_buffers (PortSet& ports);
	void get_backend_port_addresses (PortSet &, samplecnt_t);

	/* the capacity here is a size_t and has a different interpretation depending
	   on the DataType of the buffers. for audio, its a sample count. for MIDI
	   its a byte count.
	*/

	void ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capacity);
	void ensure_buffers(const ChanCount& chns, size_t buffer_capacity);

	const ChanCount& available() const { return _available; }
	ChanCount&       available()       { return _available; }

	const ChanCount& count() const { return _count; }
	ChanCount&       count()       { return _count; }

	void silence (samplecnt_t nframes, samplecnt_t offset);
	bool is_mirror() const { return _is_mirror; }

	void set_count(const ChanCount& count) { assert(count <= _available); _count = count; }

	size_t buffer_capacity(DataType type) const;

	AudioBuffer& get_audio(size_t i) {
		return (AudioBuffer&)get_available (DataType::AUDIO, i);
	}
	const AudioBuffer& get_audio(size_t i) const {
		return (const AudioBuffer&)get_available(DataType::AUDIO, i);
	}

	MidiBuffer& get_midi(size_t i) {
		return (MidiBuffer&)get_available(DataType::MIDI, i);
	}
	const MidiBuffer& get_midi(size_t i) const {
		return (const MidiBuffer&)get_available(DataType::MIDI, i);
	}

	Buffer&       get_available(DataType type, size_t i);
	const Buffer& get_available(DataType type, size_t i) const;

#ifdef LV2_SUPPORT
	/** Get a MIDI buffer translated into an LV2 MIDI buffer for use with
	 * plugins.  The index here corresponds directly to MIDI buffer numbers
	 * (i.e. the index passed to get_midi), translation back and forth will
	 * happen as needed.  If old_api is true, the returned buffer will be in
	 * old event format.  Otherwise it will be in new atom sequence format.
	 */
	LV2_Evbuf* get_lv2_midi(bool input, size_t i, bool old_api);

	/** ensure minimum size of LV2 Atom port buffer */
	void ensure_lv2_bufsize(bool input, size_t i, size_t buffer_capacity);

	/** Flush modified LV2 event output buffers back to Ardour buffers */
	void flush_lv2_midi(bool input, size_t i);

	/** Forward plugin MIDI output to to Ardour buffers */
	void forward_lv2_midi(LV2_Evbuf*, size_t, bool purge_ardour_buffer = true);
#endif

#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
	VstEvents* get_vst_midi (size_t);
#endif

	void read_from(const BufferSet& in, samplecnt_t nframes);
	void read_from(const BufferSet& in, samplecnt_t nframes, DataType);
	void merge_from(const BufferSet& in, samplecnt_t nframes);

	template <typename BS, typename B>
	class iterator_base {
	public:
		iterator_base(const iterator_base& other)
			: _set(other._set), _type(other._type), _index(other._index) {}
		B& operator*()  { return (B&)_set.get_available(_type, _index); }
		B* operator->() { return &(B&)_set.get_available(_type, _index); }
		iterator_base<BS,B>& operator++() { ++_index; return *this; } // yes, prefix only
		bool operator==(const iterator_base<BS,B>& other) { return (_index == other._index); }
		bool operator!=(const iterator_base<BS,B>& other) { return (_index != other._index); }
		iterator_base<BS,B> operator=(const iterator_base<BS,B>& other) {
			_set = other._set; _type = other._type; _index = other._index; return *this;
		}

	private:
		friend class BufferSet;

		iterator_base(BS& list, DataType type, size_t index)
			: _set(list), _type(type), _index(index) {}

		BS&      _set;
		DataType _type;
		size_t   _index;
	};

	typedef iterator_base<BufferSet, Buffer> iterator;
	iterator begin(DataType type) { return iterator(*this, type, 0); }
	iterator end(DataType type)   { return iterator(*this, type, _count.get(type)); }

	typedef iterator_base<const BufferSet, const Buffer> const_iterator;
	const_iterator begin(DataType type) const { return const_iterator(*this, type, 0); }
	const_iterator end(DataType type)   const { return const_iterator(*this, type, _count.get(type)); }

	typedef iterator_base<BufferSet, AudioBuffer> audio_iterator;
	audio_iterator audio_begin() { return audio_iterator(*this, DataType::AUDIO, 0); }
	audio_iterator audio_end()   { return audio_iterator(*this, DataType::AUDIO, _count.n_audio()); }

	typedef iterator_base<BufferSet, MidiBuffer> midi_iterator;
	midi_iterator midi_begin() { return midi_iterator(*this, DataType::MIDI, 0); }
	midi_iterator midi_end()   { return midi_iterator(*this, DataType::MIDI, _count.n_midi()); }

private:
	typedef std::vector<Buffer*> BufferVec;

	/// Vector of vectors, indexed by DataType
	std::vector<BufferVec> _buffers;

#ifdef LV2_SUPPORT
	/// LV2 MIDI buffers (for conversion to/from MIDI buffers)
	typedef std::vector< std::pair<bool, LV2_Evbuf*> > LV2Buffers;
	LV2Buffers _lv2_buffers;
#endif

#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
	class VSTBuffer {
	public:
		VSTBuffer (size_t);
		~VSTBuffer ();

		void clear ();
		void push_back (Evoral::Event<samplepos_t> const &);
		VstEvents* events () const {
			return _events;
		}

	private:
		/* prevent copy construction */
		VSTBuffer (VSTBuffer const &);

		VstEvents* _events; /// the parent VSTEvents struct
		VstMidiEvent* _midi_events; ///< storage area for VSTMidiEvents
		size_t _capacity;
	};

	typedef std::vector<VSTBuffer*> VSTBuffers;
	VSTBuffers _vst_buffers;
#endif

	/// Use counts (there may be more actual buffers than this)
	ChanCount _count;

	/// Available counts (number of buffers actually allocated)
	ChanCount _available;

	/// False if we 'own' the contained buffers, if true we mirror a PortSet)
	bool _is_mirror;
};


} // namespace ARDOUR

#endif // __ardour_buffer_set_h__