provide semantic ordering of simultaneous MIDI events; add operator== to MidiBuffer...
[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 #include "ardour/buffer.h"
24
25 namespace ARDOUR {
26
27 /** Buffer containing audio data. */
28 class AudioBuffer : public Buffer
29 {
30 public:
31         AudioBuffer(size_t capacity);
32         ~AudioBuffer();
33
34         void silence (framecnt_t len, framecnt_t offset = 0) {
35                 if (!_silent) {
36                         assert(_capacity > 0);
37                         assert(offset + len <= _capacity);
38                         memset(_data + offset, 0, sizeof (Sample) * len);
39                         if (len == _capacity) {
40                                 _silent = true;
41                         }
42                 }
43                 _written = true;
44         }
45
46         /** Read @a len frames @a src starting at @a src_offset into self starting at @ dst_offset*/
47         void read_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
48                 assert(&src != this);
49                 assert(_capacity > 0);
50                 assert(src.type() == DataType::AUDIO);
51                 assert(len <= _capacity);
52                 assert( src_offset <= ((framecnt_t) src.capacity()-len));
53                 memcpy(_data + dst_offset, ((AudioBuffer&)src).data() + src_offset, sizeof(Sample) * len);
54                 if (dst_offset == 0 && src_offset == 0 && len == _capacity) {
55                         _silent = src.silent();
56                 } else {
57                         _silent = _silent && src.silent();
58                 }
59                 _written = true;
60         }
61
62         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
63         void merge_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
64                 const AudioBuffer* ab = dynamic_cast<const AudioBuffer*>(&src);
65                 assert (ab);
66                 accumulate_from (*ab, len, dst_offset, src_offset);
67         }
68
69         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @a dst_offset */
70         void accumulate_from (const AudioBuffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) {
71                 assert(_capacity > 0);
72                 assert(len <= _capacity);
73
74                 Sample*       const dst_raw = _data + dst_offset;
75                 const Sample* const src_raw = src.data() + src_offset;
76
77                 mix_buffers_no_gain(dst_raw, src_raw, len);
78
79                 _silent = (src.silent() && _silent);
80                 _written = true;
81         }
82
83         /** Acumulate (add) @a len frames @a src starting at @a src_offset into self starting at @dst_offset
84          * scaling by @a gain_coeff */
85         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) {
86
87                 assert(_capacity > 0);
88                 assert(len <= _capacity);
89
90                 if (src.silent()) {
91                         return;
92                 }
93
94                 Sample*       const dst_raw = _data + dst_offset;
95                 const Sample* const src_raw = src.data() + src_offset;
96
97                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
98
99                 _silent = ( (src.silent() && _silent) || (_silent && gain_coeff == 0) );
100                 _written = true;
101         }
102
103         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
104          * scaling by @a gain_coeff */
105         void accumulate_with_gain_from (const Sample* src_raw, framecnt_t len, gain_t gain_coeff, framecnt_t dst_offset = 0) {
106
107                 assert(_capacity > 0);
108                 assert(len <= _capacity);
109
110                 Sample*       const dst_raw = _data + dst_offset;
111
112                 mix_buffers_with_gain (dst_raw, src_raw, len, gain_coeff);
113
114                 _silent = (_silent && gain_coeff == 0);
115                 _written = true;
116         }
117
118         /** Accumulate (add) @a len frames FROM THE START OF @a src into self
119          * scaling by @a gain_coeff */
120         void accumulate_with_ramped_gain_from (const Sample* src, framecnt_t len, gain_t initial, gain_t target, framecnt_t dst_offset = 0) {
121
122                 assert(_capacity > 0);
123                 assert(len <= _capacity);
124
125                 Sample* dst = _data + dst_offset;
126                 gain_t  gain_delta = (target - initial)/len;
127
128                 for (framecnt_t n = 0; n < len; ++n) {
129                         *dst++ += (*src++ * initial);
130                         initial += gain_delta;
131                 }
132
133                 _silent = (_silent && initial == 0 && target == 0);
134                 _written = true;
135         }
136
137         void apply_gain (gain_t gain, framecnt_t len) {
138                 apply_gain_to_buffer (_data, len, gain);
139         }
140
141         /** Set the data contained by this buffer manually (for setting directly to jack buffer).
142          *
143          * Constructor MUST have been passed capacity=0 or this will die (to prevent mem leaks).
144          */
145         void set_data (Sample* data, size_t size) {
146                 assert(!_owns_data); // prevent leaks
147                 _capacity = size;
148                 _size = size;
149                 _data = data;
150                 _silent = false;
151                 _written = false;
152         }
153
154         /** Reallocate the buffer used internally to handle at least @nframes of data
155          *
156          * Constructor MUST have been passed capacity!=0 or this will die (to prevent mem leaks).
157          */
158         void resize (size_t nframes);
159
160         bool empty() const { return _size == 0; }
161
162         const Sample* data (framecnt_t offset = 0) const {
163                 assert(offset <= _capacity);
164                 return _data + offset;
165         }
166
167         Sample* data (framecnt_t offset = 0) {
168                 assert(offset <= _capacity);
169                 return _data + offset;
170         }
171
172         void prepare () { _written = false; _silent = false; }
173         bool written() const { return _written; }
174
175   private:
176         bool    _owns_data;
177         bool    _written;
178         Sample* _data; ///< Actual buffer contents
179 };
180
181
182 } // namespace ARDOUR
183
184 #endif // __ardour_audio_audio_buffer_h__