+
+ _allocated_frames = frames;
+}
+
+/** Mix some other buffers with these ones. The AudioBuffers must have the same number of channels.
+ * @param from Audio buffers to get data from.
+ * @param frames Number of frames to mix.
+ * @param read_offset Offset within `from' to read from.
+ * @param write_offset Offset within this to mix into.
+ */
+void
+AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t frames, int32_t read_offset, int32_t write_offset)
+{
+ DCPOMATIC_ASSERT (_channels == from->channels ());
+ DCPOMATIC_ASSERT (read_offset >= 0);
+ DCPOMATIC_ASSERT (write_offset >= 0);
+
+ float** from_data = from->data ();
+ for (int i = 0; i < _channels; ++i) {
+ for (int j = 0; j < frames; ++j) {
+ _data[i][j + write_offset] += from_data[i][j + read_offset];
+ }
+ }
+}
+
+/** @param dB gain in dB */
+void
+AudioBuffers::apply_gain (float dB)
+{
+ float const linear = pow (10, dB / 20);
+
+ for (int i = 0; i < _channels; ++i) {
+ for (int j = 0; j < _frames; ++j) {
+ _data[i][j] *= linear;
+ }
+ }
+}
+
+/** @param c Channel index.
+ * @return AudioBuffers object containing only channel `c' from this AudioBuffers.
+ */
+shared_ptr<AudioBuffers>
+AudioBuffers::channel (int c) const
+{
+ shared_ptr<AudioBuffers> o (new AudioBuffers (1, frames ()));
+ o->copy_channel_from (this, c, 0);
+ return o;
+}
+
+/** Copy all the samples from a channel on another AudioBuffers to a channel on this one.
+ * @param from AudioBuffers to copy from.
+ * @param from_channel Channel index in `from' to copy from.
+ * @param to_channel Channel index in this to copy into, overwriting what's already there.
+ */
+void
+AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel)
+{
+ DCPOMATIC_ASSERT (from->frames() == frames());
+ memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float));
+}
+
+/** Make a copy of these AudioBuffers */
+shared_ptr<AudioBuffers>
+AudioBuffers::clone () const
+{
+ shared_ptr<AudioBuffers> b (new AudioBuffers (channels (), frames ()));
+ b->copy_from (this, frames (), 0, 0);
+ return b;
+}
+
+/** Extend these buffers with the data from another. The AudioBuffers must have the same number of channels. */
+void
+AudioBuffers::append (shared_ptr<const AudioBuffers> other)
+{
+ DCPOMATIC_ASSERT (channels() == other->channels());
+ ensure_size (_frames + other->frames());
+ copy_from (other.get(), other->frames(), 0, _frames);
+ _frames += other->frames();
+}
+
+/** Remove some frames from the start of these AudioBuffers */
+void
+AudioBuffers::trim_start (int32_t frames)
+{
+ DCPOMATIC_ASSERT (frames <= _frames);
+ move (_frames - frames, frames, 0);
+ set_frames (_frames - frames);