Remove out-of-date comment.
[dcpomatic.git] / src / lib / audio_buffers.cc
1 /*
2     Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cassert>
21 #include <cstring>
22 #include <stdexcept>
23 #include "audio_buffers.h"
24
25 using std::bad_alloc;
26 using boost::shared_ptr;
27
28 /** Construct an AudioBuffers.  Audio data is undefined after this constructor.
29  *  @param channels Number of channels.
30  *  @param frames Number of frames to reserve space for.
31  */
32 AudioBuffers::AudioBuffers (int channels, int frames)
33 {
34         allocate (channels, frames);
35 }
36
37 /** Copy constructor.
38  *  @param other Other AudioBuffers; data is copied.
39  */
40 AudioBuffers::AudioBuffers (AudioBuffers const & other)
41 {
42         allocate (other._channels, other._frames);
43         copy_from (&other, other._frames, 0, 0);
44 }
45
46 AudioBuffers::AudioBuffers (boost::shared_ptr<const AudioBuffers> other)
47 {
48         allocate (other->_channels, other->_frames);
49         copy_from (other.get(), other->_frames, 0, 0);
50 }
51
52 AudioBuffers &
53 AudioBuffers::operator= (AudioBuffers const & other)
54 {
55         if (this == &other) {
56                 return *this;
57         }
58                 
59         deallocate ();
60         allocate (other._channels, other._frames);
61         copy_from (&other, other._frames, 0, 0);
62
63         return *this;
64 }
65
66 /** AudioBuffers destructor */
67 AudioBuffers::~AudioBuffers ()
68 {
69         deallocate ();
70 }
71
72 void
73 AudioBuffers::allocate (int channels, int frames)
74 {
75         _channels = channels;
76         _frames = frames;
77         _allocated_frames = frames;
78         
79         _data = static_cast<float**> (malloc (_channels * sizeof (float *)));
80         if (!_data) {
81                 throw bad_alloc ();
82         }
83         
84         for (int i = 0; i < _channels; ++i) {
85                 _data[i] = static_cast<float*> (malloc (frames * sizeof (float)));
86                 if (!_data[i]) {
87                         throw bad_alloc ();
88                 }
89         }
90 }
91
92 void
93 AudioBuffers::deallocate ()
94 {
95         for (int i = 0; i < _channels; ++i) {
96                 free (_data[i]);
97         }
98
99         free (_data);
100 }
101
102 /** @param c Channel index.
103  *  @return Buffer for this channel.
104  */
105 float*
106 AudioBuffers::data (int c) const
107 {
108         assert (c >= 0 && c < _channels);
109         return _data[c];
110 }
111
112 /** Set the number of frames that these AudioBuffers will report themselves
113  *  as having.
114  *  @param f Frames; must be less than or equal to the number of allocated frames.
115  */
116 void
117 AudioBuffers::set_frames (int f)
118 {
119         assert (f <= _allocated_frames);
120         _frames = f;
121 }
122
123 /** Make all samples on all channels silent */
124 void
125 AudioBuffers::make_silent ()
126 {
127         for (int i = 0; i < _channels; ++i) {
128                 make_silent (i);
129         }
130 }
131
132 /** Make all samples on a given channel silent.
133  *  @param c Channel.
134  */
135 void
136 AudioBuffers::make_silent (int c)
137 {
138         assert (c >= 0 && c < _channels);
139         
140         for (int i = 0; i < _frames; ++i) {
141                 _data[c][i] = 0;
142         }
143 }
144
145 void
146 AudioBuffers::make_silent (int from, int frames)
147 {
148         assert ((from + frames) <= _allocated_frames);
149
150         for (int c = 0; c < _channels; ++c) {
151                 for (int i = from; i < (from + frames); ++i) {
152                         _data[c][i] = 0;
153                 }
154         }
155 }
156
157 /** Copy data from another AudioBuffers to this one.  All channels are copied.
158  *  @param from AudioBuffers to copy from; must have the same number of channels as this.
159  *  @param frames_to_copy Number of frames to copy.
160  *  @param read_offset Offset to read from in `from'.
161  *  @param write_offset Offset to write to in `to'.
162  */
163 void
164 AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset)
165 {
166         assert (from->channels() == channels());
167
168         assert (from);
169         assert (read_offset >= 0 && (read_offset + frames_to_copy) <= from->_allocated_frames);
170         assert (write_offset >= 0 && (write_offset + frames_to_copy) <= _allocated_frames);
171
172         for (int i = 0; i < _channels; ++i) {
173                 memcpy (_data[i] + write_offset, from->_data[i] + read_offset, frames_to_copy * sizeof(float));
174         }
175 }
176
177 /** Move audio data around.
178  *  @param from Offset to move from.
179  *  @param to Offset to move to.
180  *  @param frames Number of frames to move.
181  */
182     
183 void
184 AudioBuffers::move (int from, int to, int frames)
185 {
186         if (frames == 0) {
187                 return;
188         }
189         
190         assert (from >= 0);
191         assert (from < _frames);
192         assert (to >= 0);
193         assert (to < _frames);
194         assert (frames > 0);
195         assert (frames <= _frames);
196         assert ((from + frames) <= _frames);
197         assert ((to + frames) <= _allocated_frames);
198         
199         for (int i = 0; i < _channels; ++i) {
200                 memmove (_data[i] + to, _data[i] + from, frames * sizeof(float));
201         }
202 }
203
204 /** Add data from from `from', `from_channel' to our channel `to_channel' */
205 void
206 AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel)
207 {
208         int const N = frames ();
209         assert (from->frames() == N);
210         assert (to_channel <= _channels);
211
212         float* s = from->data (from_channel);
213         float* d = _data[to_channel];
214
215         for (int i = 0; i < N; ++i) {
216                 *d++ += *s++;
217         }
218 }
219
220 /** Ensure we have space for at least a certain number of frames.  If we extend
221  *  the buffers, fill the new space with silence.
222  */
223 void
224 AudioBuffers::ensure_size (int frames)
225 {
226         if (_allocated_frames >= frames) {
227                 return;
228         }
229
230         for (int i = 0; i < _channels; ++i) {
231                 _data[i] = static_cast<float*> (realloc (_data[i], frames * sizeof (float)));
232                 if (!_data[i]) {
233                         throw bad_alloc ();
234                 }
235                 for (int j = _allocated_frames; j < frames; ++j) {
236                         _data[i][j] = 0;
237                 }
238         }
239
240         _allocated_frames = frames;
241 }
242
243 void
244 AudioBuffers::accumulate_frames (AudioBuffers const * from, int read_offset, int write_offset, int frames)
245 {
246         assert (_channels == from->channels ());
247
248         for (int i = 0; i < _channels; ++i) {
249                 for (int j = 0; j < frames; ++j) {
250                         _data[i][j + write_offset] += from->data()[i][j + read_offset];
251                 }
252         }
253 }
254