merge and resolve conflict with master
[ardour.git] / libs / ardour / ardour / audio_buffer.h
1 /*
2     Copyright (C) 2006 Paul Davis
3
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)
7     any later version.
8
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
12     for more details.
13
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.
17 */
18
19 #ifndef __ardour_audio_buffer_h__
20 #define __ardour_audio_buffer_h__
21
22 #include <cstring>
23
24 #include "ardour/buffer.h"
25 #include "ardour/runtime_functions.h"
26
27 namespace ARDOUR {
28
29 /** Buffer containing audio data. */
30 class AudioBuffer : public Buffer
31 {
32 public:
33         AudioBuffer(size_t capacity);
34         ~AudioBuffer();
35
36         void silence (framecnt_t len, framecnt_t offset = 0) {
37                 if (!_silent) {
38                         assert(_capacity > 0);
39                         assert(offset + len <= _capacity);
40                         memset(_data + offset, 0, sizeof (Sample) * len);
41                         if (len == _capacity) {
42                                 _silent = true;
43                         }
44                 }
45                 _written = true;
46         }
47
48         /** Read @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
49         void read_from (const Sample* src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
50                 assert(src != 0);
51                 assert(_capacity > 0);
52                 assert(len <= _capacity);
53                 memcpy(_data + dst_offset, src + src_offset, sizeof(Sample) * len);
54                 _silent = false;
55                 _written = true;
56         }
57
58         void read_from_with_gain (const Sample* src, framecnt_t len, gain_t gain, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
59                 assert(src != 0);
60                 assert(_capacity > 0);
61                 assert(len <= _capacity);
62                 src += src_offset;
63                 for (framecnt_t n = 0; n < len; ++n) {
64                         _data[dst_offset+n] = src[n] * gain;
65                 }
66                 _silent = false;
67                 _written = true;
68         }
69
70         /** Read @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
71         void read_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
72                 assert(&src != this);
73                 assert(_capacity > 0);
74                 assert(src.type() == DataType::AUDIO);
75                 assert(len <= _capacity);
76                 assert( src_offset <= ((framecnt_t) src.capacity()-len));
77                 memcpy(_data + dst_offset, ((const AudioBuffer&)src).data() + src_offset, sizeof(Sample) * len);
78                 if (dst_offset == 0 && src_offset == 0 && len == _capacity) {
79                         _silent = src.silent();
80                 } else {
81                         _silent = _silent && src.silent();
82                 }
83                 _written = true;
84         }
85
86         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
87         void merge_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
88                 const AudioBuffer* ab = dynamic_cast<const AudioBuffer*>(&src);
89                 assert (ab);
90                 accumulate_from (*ab, len, dst_offset, src_offset);
91         }
92
93         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
94         void accumulate_from (const AudioBuffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
95                 assert(_capacity > 0);
96                 assert(len <= _capacity);
97
98                 Sample*       const dst_raw = _data + dst_offset;
99                 const Sample* const src_raw = src.data() + src_offset;
100
101                 mix_buffers_no_gain(dst_raw, src_raw, len);
102
103                 _silent = (src.silent() && _silent);
104                 _written = true;
105         }
106
107         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
108         void accumulate_from (const Sample* src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
109                 assert(_capacity > 0);
110                 assert(len <= _capacity);
111
112                 Sample*       const dst_raw = _data + dst_offset;
113                 const Sample* const src_raw = src + src_offset;
114
115                 mix_buffers_no_gain(dst_raw, src_raw, len);
116                 
117                 _silent = false;
118                 _written = true;
119         }
120
121         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @dst_offset
122          * scaling by @a gain_coeff */
123         void accumulate_with_gain_from (const AudioBuffer& src, framecnt_t len, gain_t gain_coeff, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
124
125                 assert(_capacity > 0);
126                 assert(len <= _capacity);
127
128                 if (src.silent()) {
129                         return;
130                 }
131
132                 Sample*       const dst_raw = _data + dst_offset;
133                 const Sample* const src_raw = src.data() + src_offset;
134
135                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
136
137                 _silent = ( (src.silent() && _silent) || (_silent && gain_coeff == 0) );
138                 _written = true;
139         }
140
141         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
142          * scaling by @a gain_coeff */
143         void accumulate_with_gain_from (const Sample* src_raw, framecnt_t len, gain_t gain_coeff, framecnt_t dst_offset = 0) {
144
145                 assert(_capacity > 0);
146                 assert(len <= _capacity);
147
148                 Sample*       const dst_raw = _data + dst_offset;
149
150                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
151
152                 _silent = (_silent && gain_coeff == 0);
153                 _written = true;
154         }
155
156         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
157          * scaling by @a gain_coeff */
158         void accumulate_with_ramped_gain_from (const Sample* src, framecnt_t len, gain_t initial, gain_t target, framecnt_t dst_offset = 0) {
159
160                 assert(_capacity > 0);
161                 assert(len <= _capacity);
162
163                 Sample* dst = _data + dst_offset;
164                 gain_t  gain_delta = (target - initial)/len;
165
166                 for (framecnt_t n = 0; n < len; ++n) {
167                         *dst++ += (*src++ * initial);
168                         initial += gain_delta;
169                 }
170
171                 _silent = (_silent && initial == 0 && target == 0);
172                 _written = true;
173         }
174
175         void apply_gain (gain_t gain, framecnt_t len) {
176                 apply_gain_to_buffer (_data, len, gain);
177         }
178
179         /** Set the data contained by this buffer manually (for setting directly to jack buffer).
180          *
181          * Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
182          */
183         void set_data (Sample* data, size_t size) {
184                 assert(!_owns_data); // prevent leaks
185                 _capacity = size;
186                 _size = size;
187                 _data = data;
188                 _silent = false;
189                 _written = false;
190         }
191
192         /** Reallocate the buffer used internally to handle at least @nframes of data
193          *
194          * Constructor MUST have been passed capacity!=0 or this will die (to prevent mem leaks).
195          */
196         void resize (size_t nframes);
197
198         bool empty() const { return _size == 0; }
199
200         const Sample* data (framecnt_t offset = 0) const {
201                 assert(offset <= _capacity);
202                 return _data + offset;
203         }
204
205         Sample* data (framecnt_t offset = 0) {
206                 assert(offset <= _capacity);
207                 return _data + offset;
208         }
209
210         bool check_silence (pframes_t, pframes_t&) const;
211
212         void prepare () { _written = false; _silent = false; }
213         bool written() const { return _written; }
214         void set_written(bool w) { _written = w; }
215
216   private:
217         bool    _owns_data;
218         bool    _written;
219         Sample* _data; ///< Actual buffer contents
220 };
221
222
223 } // namespace ARDOUR
224
225 #endif // __ardour_audio_audio_buffer_h__