Debug.
[dcpomatic.git] / src / lib / audio_buffers.cc
1 /*
2     Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #include "audio_buffers.h"
22 #include "dcpomatic_assert.h"
23 #include "dcpomatic_log.h"
24 #include <cassert>
25 #include <cstring>
26 #include <cmath>
27 #include <stdexcept>
28
29 using std::bad_alloc;
30 using boost::shared_ptr;
31
32 /** Construct an AudioBuffers.  Audio data is undefined after this constructor.
33  *  @param channels Number of channels.
34  *  @param frames Number of frames to reserve space for.
35  */
36 AudioBuffers::AudioBuffers (int channels, int32_t frames)
37 {
38         allocate (channels, frames);
39 }
40
41 /** Copy constructor.
42  *  @param other Other AudioBuffers; data is copied.
43  */
44 AudioBuffers::AudioBuffers (AudioBuffers const & other)
45 {
46         allocate (other._channels, other._frames);
47         LOG_GENERAL_NC("copy_from #5");
48         copy_from (&other, other._frames, 0, 0);
49 }
50
51 AudioBuffers::AudioBuffers (boost::shared_ptr<const AudioBuffers> other)
52 {
53         allocate (other->_channels, other->_frames);
54         LOG_GENERAL_NC("copy_from #6");
55         copy_from (other.get(), other->_frames, 0, 0);
56 }
57
58 AudioBuffers &
59 AudioBuffers::operator= (AudioBuffers const & other)
60 {
61         if (this == &other) {
62                 return *this;
63         }
64
65         deallocate ();
66         allocate (other._channels, other._frames);
67         LOG_GENERAL_NC("copy_from #7");
68         copy_from (&other, other._frames, 0, 0);
69
70         return *this;
71 }
72
73 /** AudioBuffers destructor */
74 AudioBuffers::~AudioBuffers ()
75 {
76         deallocate ();
77 }
78
79 void
80 AudioBuffers::allocate (int channels, int32_t frames)
81 {
82         DCPOMATIC_ASSERT (frames >= 0);
83         DCPOMATIC_ASSERT (channels >= 0);
84
85         _channels = channels;
86         _frames = frames;
87         _allocated_frames = frames;
88
89         _data = static_cast<float**> (malloc (_channels * sizeof (float *)));
90         if (!_data) {
91                 throw bad_alloc ();
92         }
93
94         for (int i = 0; i < _channels; ++i) {
95                 _data[i] = static_cast<float*> (malloc (frames * sizeof (float)));
96                 if (!_data[i]) {
97                         throw bad_alloc ();
98                 }
99         }
100 }
101
102 void
103 AudioBuffers::deallocate ()
104 {
105         for (int i = 0; i < _channels; ++i) {
106                 free (_data[i]);
107         }
108
109         free (_data);
110 }
111
112 /** @param c Channel index.
113  *  @return Buffer for this channel.
114  */
115 float*
116 AudioBuffers::data (int c) const
117 {
118         DCPOMATIC_ASSERT (c >= 0 && c < _channels);
119         return _data[c];
120 }
121
122 /** Set the number of frames that these AudioBuffers will report themselves
123  *  as having.  If we reduce the number of frames, the `lost' frames will
124  *  be silenced.
125  *  @param f Frames; must be less than or equal to the number of allocated frames.
126  */
127 void
128 AudioBuffers::set_frames (int32_t f)
129 {
130         DCPOMATIC_ASSERT (f <= _allocated_frames);
131
132         for (int c = 0; c < _channels; ++c) {
133                 for (int i = f; i < _frames; ++i) {
134                         _data[c][i] = 0;
135                 }
136         }
137
138         _frames = f;
139 }
140
141 /** Make all frames silent */
142 void
143 AudioBuffers::make_silent ()
144 {
145         for (int i = 0; i < _channels; ++i) {
146                 make_silent (i);
147         }
148 }
149
150 /** Make all samples on a given channel silent.
151  *  @param c Channel.
152  */
153 void
154 AudioBuffers::make_silent (int c)
155 {
156         DCPOMATIC_ASSERT (c >= 0 && c < _channels);
157
158         for (int i = 0; i < _frames; ++i) {
159                 _data[c][i] = 0;
160         }
161 }
162
163 /** Make some frames.
164  *  @param from Start frame.
165  *  @param frames Number of frames to silence.
166  */
167 void
168 AudioBuffers::make_silent (int32_t from, int32_t frames)
169 {
170         DCPOMATIC_ASSERT ((from + frames) <= _allocated_frames);
171
172         for (int c = 0; c < _channels; ++c) {
173                 for (int i = from; i < (from + frames); ++i) {
174                         _data[c][i] = 0;
175                 }
176         }
177 }
178
179 /** Copy data from another AudioBuffers to this one.  All channels are copied.
180  *  @param from AudioBuffers to copy from; must have the same number of channels as this.
181  *  @param frames_to_copy Number of frames to copy.
182  *  @param read_offset Offset to read from in `from'.
183  *  @param write_offset Offset to write to in `to'.
184  */
185 void
186 AudioBuffers::copy_from (AudioBuffers const * from, int32_t frames_to_copy, int32_t read_offset, int32_t write_offset)
187 {
188         if (frames_to_copy == 0) {
189                 /* Prevent the asserts from firing if there is nothing to do */
190                 return;
191         }
192
193         LOG_GENERAL("AudioBuffers::copy_from %1 %2 %3 %4", from->_allocated_frames, frames_to_copy, read_offset, write_offset);
194
195         DCPOMATIC_ASSERT (from->channels() == channels());
196
197         DCPOMATIC_ASSERT (from);
198         DCPOMATIC_ASSERT (read_offset >= 0 && (read_offset + frames_to_copy) <= from->_allocated_frames);
199         DCPOMATIC_ASSERT (write_offset >= 0 && (write_offset + frames_to_copy) <= _allocated_frames);
200
201         for (int i = 0; i < _channels; ++i) {
202                 memcpy (_data[i] + write_offset, from->_data[i] + read_offset, frames_to_copy * sizeof(float));
203         }
204 }
205
206 /** Move audio data around.
207  *  @param from Offset to move from.
208  *  @param to Offset to move to.
209  *  @param frames Number of frames to move.
210  */
211 void
212 AudioBuffers::move (int32_t frames, int32_t from, int32_t to)
213 {
214         if (frames == 0) {
215                 return;
216         }
217
218         DCPOMATIC_ASSERT (from >= 0);
219         DCPOMATIC_ASSERT (from < _frames);
220         DCPOMATIC_ASSERT (to >= 0);
221         DCPOMATIC_ASSERT (to < _frames);
222         DCPOMATIC_ASSERT (frames > 0);
223         DCPOMATIC_ASSERT (frames <= _frames);
224         DCPOMATIC_ASSERT ((from + frames) <= _frames);
225         DCPOMATIC_ASSERT ((to + frames) <= _allocated_frames);
226
227         for (int i = 0; i < _channels; ++i) {
228                 memmove (_data[i] + to, _data[i] + from, frames * sizeof(float));
229         }
230 }
231
232 /** Add data from from `from', `from_channel' to our channel `to_channel'.
233  *  @param from Buffers to copy data from.
234  *  @param from_channel Channel index to read in \p from.
235  *  @param to_channel Channel index to accumulate into.
236  *  @param gain Linear gain to apply to the data before it is added.
237  */
238 void
239 AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel, float gain)
240 {
241         int const N = frames ();
242         DCPOMATIC_ASSERT (from->frames() == N);
243         DCPOMATIC_ASSERT (to_channel <= _channels);
244
245         float* s = from->data (from_channel);
246         float* d = _data[to_channel];
247
248         for (int i = 0; i < N; ++i) {
249                 *d++ += (*s++) * gain;
250         }
251 }
252
253 /** Ensure we have space for at least a certain number of frames.  If we extend
254  *  the buffers, fill the new space with silence.
255  */
256 void
257 AudioBuffers::ensure_size (int32_t frames)
258 {
259         if (_allocated_frames >= frames) {
260                 return;
261         }
262
263         /* Round up frames to the next power of 2 to reduce the number
264            of realloc()s that are necessary.
265         */
266         frames--;
267         frames |= frames >> 1;
268         frames |= frames >> 2;
269         frames |= frames >> 4;
270         frames |= frames >> 8;
271         frames |= frames >> 16;
272         frames++;
273
274         for (int i = 0; i < _channels; ++i) {
275                 _data[i] = static_cast<float*> (realloc (_data[i], frames * sizeof (float)));
276                 if (!_data[i]) {
277                         throw bad_alloc ();
278                 }
279                 for (int j = _allocated_frames; j < frames; ++j) {
280                         _data[i][j] = 0;
281                 }
282         }
283
284         _allocated_frames = frames;
285 }
286
287 /** Mix some other buffers with these ones.  The AudioBuffers must have the same number of channels.
288  *  @param from Audio buffers to get data from.
289  *  @param frames Number of frames to mix.
290  *  @param read_offset Offset within `from' to read from.
291  *  @param write_offset Offset within this to mix into.
292  */
293 void
294 AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t frames, int32_t read_offset, int32_t write_offset)
295 {
296         DCPOMATIC_ASSERT (_channels == from->channels ());
297         DCPOMATIC_ASSERT (read_offset >= 0);
298         DCPOMATIC_ASSERT (write_offset >= 0);
299
300         float** from_data = from->data ();
301         for (int i = 0; i < _channels; ++i) {
302                 for (int j = 0; j < frames; ++j) {
303                         _data[i][j + write_offset] += from_data[i][j + read_offset];
304                 }
305         }
306 }
307
308 /** @param dB gain in dB */
309 void
310 AudioBuffers::apply_gain (float dB)
311 {
312         float const linear = pow (10, dB / 20);
313
314         for (int i = 0; i < _channels; ++i) {
315                 for (int j = 0; j < _frames; ++j) {
316                         _data[i][j] *= linear;
317                 }
318         }
319 }
320
321 /** @param c Channel index.
322  *  @return AudioBuffers object containing only channel `c' from this AudioBuffers.
323  */
324 shared_ptr<AudioBuffers>
325 AudioBuffers::channel (int c) const
326 {
327         shared_ptr<AudioBuffers> o (new AudioBuffers (1, frames ()));
328         o->copy_channel_from (this, c, 0);
329         return o;
330 }
331
332 /** Copy all the samples from a channel on another AudioBuffers to a channel on this one.
333  *  @param from AudioBuffers to copy from.
334  *  @param from_channel Channel index in `from' to copy from.
335  *  @param to_channel Channel index in this to copy into, overwriting what's already there.
336  */
337 void
338 AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel)
339 {
340         DCPOMATIC_ASSERT (from->frames() == frames());
341         memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float));
342 }
343
344 /** Make a copy of these AudioBuffers */
345 shared_ptr<AudioBuffers>
346 AudioBuffers::clone () const
347 {
348         shared_ptr<AudioBuffers> b (new AudioBuffers (channels (), frames ()));
349         LOG_GENERAL_NC("copy_from #3");
350         b->copy_from (this, frames (), 0, 0);
351         return b;
352 }
353
354 /** Extend these buffers with the data from another.  The AudioBuffers must have the same number of channels. */
355 void
356 AudioBuffers::append (shared_ptr<const AudioBuffers> other)
357 {
358         DCPOMATIC_ASSERT (channels() == other->channels());
359         ensure_size (_frames + other->frames());
360         LOG_GENERAL_NC("copy_from #4");
361         copy_from (other.get(), other->frames(), 0, _frames);
362         _frames += other->frames();
363 }
364
365 /** Remove some frames from the start of these AudioBuffers */
366 void
367 AudioBuffers::trim_start (int32_t frames)
368 {
369         DCPOMATIC_ASSERT (frames <= _frames);
370         move (_frames - frames, frames, 0);
371         set_frames (_frames - frames);
372 }