1 /*
2  * Copyright (C) 2007-2012 David Robillard <d@drobilla.net>
3  * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2013-2016 Robin Gareus <robin@gareus.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 #ifndef __ardour_audio_buffer_h__
23 #define __ardour_audio_buffer_h__
24 
25 #include <cstring>
26 
27 #include "ardour/buffer.h"
28 #include "ardour/runtime_functions.h"
29 
30 namespace ARDOUR
31 {
32 /** Buffer containing audio data. */
33 class LIBARDOUR_API AudioBuffer : public Buffer
34 {
35 public:
36 	AudioBuffer (size_t capacity);
37 	~AudioBuffer ();
38 
39 	/** silence buffer
40 	 * @param len number of samples to clear
41 	 * @param offset start offset
42 	 */
43 	void silence (samplecnt_t len, samplecnt_t offset = 0);
44 
45 	/** Copy samples from src array starting at src_offset into self starting at dst_offset
46 	 * @param src array to read from
47 	 * @param len number of samples to copy
48 	 * @param dst_offset offset in destination buffer
49 	 * @param src_offset start offset in src buffer
50 	 */
51 	void read_from (const Sample* src, samplecnt_t len, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
52 	{
53 		assert (src != 0);
54 		assert (_capacity > 0);
55 		assert (len <= _capacity);
56 		copy_vector (_data + dst_offset, src + src_offset, len);
57 		_silent  = false;
58 		_written = true;
59 	}
60 
61 	/** Copy samples from src buffer starting at src_offset into self starting at dst_offset
62 	 * @param src buffer to read from
63 	 * @param len number of samples to copy
64 	 * @param dst_offset offset in destination buffer
65 	 * @param src_offset start offset in src buffer
66 	 */
67 	void read_from (const Buffer& src, samplecnt_t len, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
68 	{
69 		assert (&src != this);
70 		assert (_capacity > 0);
71 		assert (src.type () == DataType::AUDIO);
72 		assert (dst_offset + len <= _capacity);
73 		assert (src_offset <= ((samplecnt_t)src.capacity () - len));
74 
75 		if (src.silent ()) {
76 			memset (_data + dst_offset, 0, sizeof (Sample) * len);
77 		} else {
78 			copy_vector (_data + dst_offset, ((const AudioBuffer&)src).data () + src_offset, len);
79 		}
80 
81 		if (dst_offset == 0 && src_offset == 0 && len == _capacity) {
82 			_silent = src.silent ();
83 		} else {
84 			_silent = _silent && src.silent ();
85 		}
86 		_written = true;
87 	}
88 
89 	/** Accumulate (add) \p len samples from \p src starting at \p src_offset into self starting at \p dst_offset */
90 	void merge_from (const Buffer& src, samplecnt_t len, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
91 	{
92 		const AudioBuffer* ab = dynamic_cast<const AudioBuffer*> (&src);
93 		assert (ab);
94 		accumulate_from (*ab, len, dst_offset, src_offset);
95 	}
96 
97 	/** Accumulate (add) \p len samples from \p src starting at \p src_offset into self starting at \p dst_offset */
98 	void accumulate_from (const AudioBuffer& src, samplecnt_t len, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
99 	{
100 		assert (_capacity > 0);
101 		assert (len <= _capacity);
102 		if (src.silent ()) {
103 			return;
104 		}
105 		Sample* const       dst_raw = _data + dst_offset;
106 		const Sample* const src_raw = src.data () + src_offset;
107 
108 		mix_buffers_no_gain (dst_raw, src_raw, len);
109 
110 		_silent  = (src.silent () && _silent);
111 		_written = true;
112 	}
113 
114 	/** Accumulate (add) \p len samples of \p src starting at \p src_offset into self
115 	 * starting at \p dst_offset
116 	 */
117 	void accumulate_from (const Sample* src, samplecnt_t len, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
118 	{
119 		assert (_capacity > 0);
120 		assert (len <= _capacity);
121 
122 		Sample* const       dst_raw = _data + dst_offset;
123 		const Sample* const src_raw = src + src_offset;
124 
125 		mix_buffers_no_gain (dst_raw, src_raw, len);
126 
127 		_silent  = false;
128 		_written = true;
129 	}
130 
131 	/** Accumulate (add) \p len samples if \p src starting at \p src_offset into self
132 	 * starting at \p dst_offset scaling by \p gain_coeff
133 	 */
134 	void accumulate_with_gain_from (const AudioBuffer& src, samplecnt_t len, gain_t gain_coeff, sampleoffset_t dst_offset = 0, sampleoffset_t src_offset = 0)
135 	{
136 		assert (_capacity > 0);
137 		assert (len <= _capacity);
138 
139 		if (src.silent () || gain_coeff == 0) {
140 			return;
141 		}
142 
143 		Sample* const       dst_raw = _data + dst_offset;
144 		const Sample* const src_raw = src.data () + src_offset;
145 
146 		mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
147 
148 		_silent  = ((src.silent () && _silent) || (_silent && gain_coeff == 0));
149 		_written = true;
150 	}
151 
152 	/** Accumulate (add) \p len samples from the start of \p src_raw into self at \p dst_offset
153 	 * scaling by \p gain_coeff
154 	 */
155 	void accumulate_with_gain_from (const Sample* src_raw, samplecnt_t len, gain_t gain_coeff, sampleoffset_t dst_offset = 0)
156 	{
157 		assert (_capacity > 0);
158 		assert (len <= _capacity);
159 
160 		Sample* const dst_raw = _data + dst_offset;
161 
162 		mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
163 
164 		_silent  = (_silent && gain_coeff == 0);
165 		_written = true;
166 	}
167 
168 	/** Accumulate (add) \p len samples from the start of \p src into self at \p dst_offset
169 	 * using a linear gain ramp from \p initial to \p target .
170 	 */
171 	void accumulate_with_ramped_gain_from (const Sample* src, samplecnt_t len, gain_t initial, gain_t target, sampleoffset_t dst_offset = 0)
172 	{
173 		assert (_capacity > 0);
174 		assert (len <= _capacity);
175 
176 		if (initial == 0 && target == 0) {
177 			return;
178 		}
179 
180 		Sample* dst        = _data + dst_offset;
181 		gain_t  gain_delta = (target - initial) / len;
182 
183 		for (samplecnt_t n = 0; n < len; ++n) {
184 			*dst++ += (*src++ * initial);
185 			initial += gain_delta;
186 		}
187 
188 		_silent  = (_silent && initial == 0 && target == 0);
189 		_written = true;
190 	}
191 
192 	/** Apply a fixed gain factor to the audio buffer
193 	 *
194 	 * @param gain gain factor
195 	 * @param len number of samples to amplify
196 	 */
apply_gain(gain_t gain,samplecnt_t len)197 	void apply_gain (gain_t gain, samplecnt_t len)
198 	{
199 		if (gain == 0) {
200 			memset (_data, 0, sizeof (Sample) * len);
201 			if (len == _capacity) {
202 				_silent = true;
203 			}
204 			return;
205 		}
206 		apply_gain_to_buffer (_data, len, gain);
207 	}
208 
209 	/** Set the data contained by this buffer manually (for setting directly to jack buffer).
210 	 *
211 	 * Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
212 	 */
set_data(Sample * data,size_t size)213 	void set_data (Sample* data, size_t size)
214 	{
215 		assert (!_owns_data); // prevent leaks
216 		_capacity = size;
217 		_data     = data;
218 		_silent   = false;
219 		_written  = false;
220 	}
221 
222 	/** Reallocate the buffer used internally to handle at least \p nframes of data
223 	 *
224 	 * Constructor MUST have been passed capacity!=0 or this will die (to prevent mem leaks).
225 	 */
226 	void resize (size_t nframes);
227 
228 	const Sample* data (samplecnt_t offset = 0) const
229 	{
230 		assert (offset <= _capacity);
231 		return _data + offset;
232 	}
233 
234 	Sample* data (samplecnt_t offset = 0)
235 	{
236 		assert (offset <= _capacity);
237 		_silent = false;
238 		return _data + offset;
239 	}
240 
241 	/** Check buffer for silence
242 	 *
243 	 * @param nframes  number of samples to check
244 	 * @param n first non zero sample (if any)
245 	 * @return true if all samples are zero
246 	 */
247 	bool check_silence (pframes_t nframes, pframes_t& n) const;
248 
prepare()249 	void prepare ()
250 	{
251 		if (!_owns_data) {
252 			_data = 0;
253 		}
254 		_written = false;
255 		_silent  = false;
256 	}
257 
written()258 	bool written () const { return _written; }
set_written(bool w)259 	void set_written (bool w) { _written = w; }
260 
261 private:
262 	bool    _owns_data;
263 	bool    _written;
264 	Sample* _data; ///< Actual buffer contents
265 };
266 
267 } // namespace ARDOUR
268 
269 #endif // __ardour_audio_audio_buffer_h__
270