2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
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.
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.
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/>.
22 #include "audio_buffers.h"
23 #include "dcpomatic_assert.h"
24 #include "maths_util.h"
25 #include <dcp/scope_guard.h>
31 using std::shared_ptr;
32 using std::make_shared;
35 /** Construct a silent AudioBuffers */
36 AudioBuffers::AudioBuffers (int channels, int frames)
38 allocate (channels, frames);
43 * @param other Other AudioBuffers; data is copied.
45 AudioBuffers::AudioBuffers (AudioBuffers const & other)
47 allocate (other.channels(), other.frames());
48 copy_from (&other, other.frames(), 0, 0);
52 AudioBuffers::AudioBuffers (std::shared_ptr<const AudioBuffers> other)
54 allocate (other->channels(), other->frames());
55 copy_from (other.get(), other->frames(), 0, 0);
59 AudioBuffers::AudioBuffers (std::shared_ptr<const AudioBuffers> other, int frames_to_copy, int read_offset)
61 allocate (other->channels(), frames_to_copy);
62 copy_from (other.get(), frames_to_copy, read_offset, 0);
67 AudioBuffers::operator= (AudioBuffers const & other)
73 allocate (other.channels(), other.frames());
74 copy_from (&other, other.frames(), 0, 0);
81 AudioBuffers::allocate (int channels, int frames)
83 DCPOMATIC_ASSERT (frames >= 0);
84 DCPOMATIC_ASSERT(frames == 0 || channels > 0);
86 dcp::ScopeGuard sg = [this]() { update_data_pointers(); };
88 _data.resize(channels);
89 for (int channel = 0; channel < channels; ++channel) {
90 _data[channel].resize(frames);
95 /** @param channel Channel index.
96 * @return Buffer for this channel.
99 AudioBuffers::data (int channel)
101 DCPOMATIC_ASSERT (channel >= 0 && channel < channels());
102 return _data[channel].data();
106 /** @param channel Channel index.
107 * @return Buffer for this channel.
110 AudioBuffers::data (int channel) const
112 DCPOMATIC_ASSERT (channel >= 0 && channel < channels());
113 return _data[channel].data();
117 /** Set the number of frames in these AudioBuffers */
119 AudioBuffers::set_frames (int frames)
121 allocate(_data.size(), frames);
125 /** Make all frames silent */
127 AudioBuffers::make_silent ()
129 for (int channel = 0; channel < channels(); ++channel) {
130 make_silent (channel);
135 /** Make all samples on a given channel silent */
137 AudioBuffers::make_silent (int channel)
139 DCPOMATIC_ASSERT (channel >= 0 && channel < channels());
141 /* This isn't really allowed, as all-bits-0 is not guaranteed to mean a 0 float,
142 but it seems that we can get away with it.
144 memset (data(channel), 0, frames() * sizeof(float));
148 /** Make some frames silent.
149 * @param from Start frame.
152 AudioBuffers::make_silent (int from, int frames_to_silence)
154 DCPOMATIC_ASSERT ((from + frames_to_silence) <= frames());
156 for (int channel = 0; channel < channels(); ++channel) {
157 /* This isn't really allowed, as all-bits-0 is not guaranteed to mean a 0 float,
158 but it seems that we can get away with it.
160 memset (data(channel) + from, 0, frames_to_silence * sizeof(float));
165 /** Copy data from another AudioBuffers to this one. All channels are copied.
166 * @param from AudioBuffers to copy from; must have the same number of channels as this.
167 * @param frames_to_copy Number of frames to copy.
168 * @param read_offset Offset to read from in `from'.
169 * @param write_offset Offset to write to in `to'.
172 AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset)
174 if (frames_to_copy == 0) {
175 /* Prevent the asserts from firing if there is nothing to do */
179 DCPOMATIC_ASSERT (from);
180 DCPOMATIC_ASSERT (from->channels() == channels());
181 DCPOMATIC_ASSERT (read_offset >= 0 && (read_offset + frames_to_copy) <= from->frames());
182 DCPOMATIC_ASSERT (write_offset >= 0 && (write_offset + frames_to_copy) <= frames());
184 for (int channel = 0; channel < channels(); ++channel) {
185 memcpy (data(channel) + write_offset, from->data(channel) + read_offset, frames_to_copy * sizeof(float));
190 /** Move audio data around.
191 * @param frames_to_move Number of frames to move.
192 * @param from Offset to move from.
193 * @param to Offset to move to.
196 AudioBuffers::move (int frames_to_move, int from, int to)
198 if (frames_to_move == 0) {
202 DCPOMATIC_ASSERT (from >= 0);
203 DCPOMATIC_ASSERT (from < frames());
204 DCPOMATIC_ASSERT (to >= 0);
205 DCPOMATIC_ASSERT (to < frames());
206 DCPOMATIC_ASSERT (frames_to_move > 0);
207 DCPOMATIC_ASSERT (frames_to_move <= frames());
208 DCPOMATIC_ASSERT ((from + frames_to_move) <= frames());
209 DCPOMATIC_ASSERT ((to + frames_to_move) <= frames());
211 for (int channel = 0; channel < channels(); ++channel) {
212 memmove (data(channel) + to, data(channel) + from, frames_to_move * sizeof(float));
217 /** Add data from from `from', `from_channel' to our channel `to_channel'.
218 * @param from Buffers to copy data from.
219 * @param from_channel Channel index to read in \p from.
220 * @param to_channel Channel index to accumulate into.
221 * @param gain Linear gain to apply to the data before it is added.
224 AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel, float gain)
226 int const N = frames ();
227 DCPOMATIC_ASSERT (from->frames() == N);
228 DCPOMATIC_ASSERT (to_channel <= channels());
230 auto s = from->data (from_channel);
231 auto d = data(to_channel);
233 for (int i = 0; i < N; ++i) {
234 *d++ += (*s++) * gain;
239 /** Mix some other buffers with these ones. The AudioBuffers must have the same number of channels.
240 * @param from Audio buffers to get data from.
241 * @param frames Number of frames to mix.
242 * @param read_offset Offset within `from' to read from.
243 * @param write_offset Offset within this to mix into.
246 AudioBuffers::accumulate_frames (AudioBuffers const * from, int frames, int read_offset, int write_offset)
248 DCPOMATIC_ASSERT (channels() == from->channels());
249 DCPOMATIC_ASSERT (read_offset >= 0);
250 DCPOMATIC_ASSERT (write_offset >= 0);
252 auto from_data = from->data ();
253 for (int i = 0; i < channels(); ++i) {
254 for (int j = 0; j < frames; ++j) {
255 _data[i][j + write_offset] += from_data[i][j + read_offset];
261 /** @param dB gain in dB */
263 AudioBuffers::apply_gain (float dB)
265 auto const linear = db_to_linear (dB);
267 for (int i = 0; i < channels(); ++i) {
268 for (int j = 0; j < frames(); ++j) {
269 _data[i][j] *= linear;
275 /** @return AudioBuffers object containing only the given channel from this AudioBuffers */
276 shared_ptr<AudioBuffers>
277 AudioBuffers::channel (int channel) const
279 auto output = make_shared<AudioBuffers>(1, frames());
280 output->copy_channel_from (this, channel, 0);
285 /** Copy all the samples from a channel on another AudioBuffers to a channel on this one.
286 * @param from AudioBuffers to copy from.
287 * @param from_channel Channel index in `from' to copy from.
288 * @param to_channel Channel index in this to copy into, overwriting what's already there.
291 AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel)
293 DCPOMATIC_ASSERT (from->frames() == frames());
294 memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float));
298 /** Make a copy of these AudioBuffers */
299 shared_ptr<AudioBuffers>
300 AudioBuffers::clone () const
302 auto b = make_shared<AudioBuffers>(channels(), frames());
303 b->copy_from (this, frames(), 0, 0);
308 /** Extend these buffers with the data from another. The AudioBuffers must have the same number of channels. */
310 AudioBuffers::append (shared_ptr<const AudioBuffers> other)
312 DCPOMATIC_ASSERT (channels() == other->channels());
313 auto old_frames = frames();
314 set_frames(old_frames + other->frames());
315 copy_from (other.get(), other->frames(), 0, old_frames);
319 /** Remove some frames from the start of these AudioBuffers */
321 AudioBuffers::trim_start (int frames_to_trim)
323 DCPOMATIC_ASSERT (frames_to_trim <= frames());
324 move (frames() - frames_to_trim, frames_to_trim, 0);
325 set_frames (frames() - frames_to_trim);
330 AudioBuffers::update_data_pointers ()
332 _data_pointers.resize (channels());
333 for (int i = 0; i < channels(); ++i) {
334 _data_pointers[i] = _data[i].data();
339 /** Set a new channel count, either discarding data (if new_channels is less than the current
340 * channels()), or filling with silence (if new_channels is more than the current channels()
343 AudioBuffers::set_channels(int new_channels)
345 DCPOMATIC_ASSERT(new_channels > 0);
347 dcp::ScopeGuard sg = [this]() { update_data_pointers(); };
349 int const old_channels = channels();
350 _data.resize(new_channels);
352 for (int channel = old_channels; channel < new_channels; ++channel) {
353 _data[channel].resize(frames());