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