Merge branch 'master' into cairocanvas
[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 LIBARDOUR_API 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
38         /** Read @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
39         void read_from (const Sample* src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
40                 assert(src != 0);
41                 assert(_capacity > 0);
42                 assert(len <= _capacity);
43                 memcpy(_data + dst_offset, src + src_offset, sizeof(Sample) * len);
44                 _silent = false;
45                 _written = true;
46         }
47
48         void read_from_with_gain (const Sample* src, framecnt_t len, gain_t gain, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
49                 assert(src != 0);
50                 assert(_capacity > 0);
51                 assert(len <= _capacity);
52                 src += src_offset;
53                 for (framecnt_t n = 0; n < len; ++n) {
54                         _data[dst_offset+n] = src[n] * gain;
55                 }
56                 _silent = false;
57                 _written = true;
58         }
59
60         /** Read @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
61         void read_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
62                 assert(&src != this);
63                 assert(_capacity > 0);
64                 assert(src.type() == DataType::AUDIO);
65                 assert(dst_offset + len <= _capacity);
66                 assert( src_offset <= ((framecnt_t) src.capacity()-len));
67                 memcpy(_data + dst_offset, ((const AudioBuffer&)src).data() + src_offset, sizeof(Sample) * len);
68                 if (dst_offset == 0 && src_offset == 0 && len == _capacity) {
69                         _silent = src.silent();
70                 } else {
71                         _silent = _silent && src.silent();
72                 }
73                 _written = true;
74         }
75
76         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
77         void merge_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
78                 const AudioBuffer* ab = dynamic_cast<const AudioBuffer*>(&src);
79                 assert (ab);
80                 accumulate_from (*ab, len, dst_offset, src_offset);
81         }
82
83         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
84         void accumulate_from (const AudioBuffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
85                 assert(_capacity > 0);
86                 assert(len <= _capacity);
87
88                 Sample*       const dst_raw = _data + dst_offset;
89                 const Sample* const src_raw = src.data() + src_offset;
90
91                 mix_buffers_no_gain(dst_raw, src_raw, len);
92
93                 _silent = (src.silent() && _silent);
94                 _written = true;
95         }
96
97         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
98         void accumulate_from (const Sample* src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
99                 assert(_capacity > 0);
100                 assert(len <= _capacity);
101
102                 Sample*       const dst_raw = _data + dst_offset;
103                 const Sample* const src_raw = src + src_offset;
104
105                 mix_buffers_no_gain(dst_raw, src_raw, len);
106                 
107                 _silent = false;
108                 _written = true;
109         }
110
111         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @dst_offset
112          * scaling by @a gain_coeff */
113         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) {
114
115                 assert(_capacity > 0);
116                 assert(len <= _capacity);
117
118                 if (src.silent()) {
119                         return;
120                 }
121
122                 Sample*       const dst_raw = _data + dst_offset;
123                 const Sample* const src_raw = src.data() + src_offset;
124
125                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
126
127                 _silent = ( (src.silent() && _silent) || (_silent && gain_coeff == 0) );
128                 _written = true;
129         }
130
131         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
132          * scaling by @a gain_coeff */
133         void accumulate_with_gain_from (const Sample* src_raw, framecnt_t len, gain_t gain_coeff, framecnt_t dst_offset = 0) {
134
135                 assert(_capacity > 0);
136                 assert(len <= _capacity);
137
138                 Sample*       const dst_raw = _data + dst_offset;
139
140                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
141
142                 _silent = (_silent && gain_coeff == 0);
143                 _written = true;
144         }
145
146         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
147          * scaling by @a gain_coeff */
148         void accumulate_with_ramped_gain_from (const Sample* src, framecnt_t len, gain_t initial, gain_t target, framecnt_t dst_offset = 0) {
149
150                 assert(_capacity > 0);
151                 assert(len <= _capacity);
152
153                 Sample* dst = _data + dst_offset;
154                 gain_t  gain_delta = (target - initial)/len;
155
156                 for (framecnt_t n = 0; n < len; ++n) {
157                         *dst++ += (*src++ * initial);
158                         initial += gain_delta;
159                 }
160
161                 _silent = (_silent && initial == 0 && target == 0);
162                 _written = true;
163         }
164
165         void apply_gain (gain_t gain, framecnt_t len) {
166                 apply_gain_to_buffer (_data, len, gain);
167         }
168
169         /** Set the data contained by this buffer manually (for setting directly to jack buffer).
170          *
171          * Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
172          */
173         void set_data (Sample* data, size_t size) {
174                 assert(!_owns_data); // prevent leaks
175                 _capacity = size;
176                 _data = data;
177                 _silent = false;
178                 _written = false;
179         }
180
181         /** Reallocate the buffer used internally to handle at least @nframes of data
182          *
183          * Constructor MUST have been passed capacity!=0 or this will die (to prevent mem leaks).
184          */
185         void resize (size_t nframes);
186
187         const Sample* data (framecnt_t offset = 0) const {
188                 assert(offset <= _capacity);
189                 return _data + offset;
190         }
191
192         Sample* data (framecnt_t offset = 0) {
193                 assert(offset <= _capacity);
194                 _silent = false;
195                 return _data + offset;
196         }
197
198         bool check_silence (pframes_t, pframes_t&) const;
199
200         void prepare () { _written = false; _silent = false; }
201         bool written() const { return _written; }
202         void set_written(bool w) { _written = w; }
203
204   private:
205         bool    _owns_data;
206         bool    _written;
207         Sample* _data; ///< Actual buffer contents
208 };
209
210
211 } // namespace ARDOUR
212
213 #endif // __ardour_audio_audio_buffer_h__