X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Faudio_buffers.cc;h=9f91810e0c4ab14387b55eef574a1362bf1c6fdf;hb=cfbe9d2f44e380efed7a61b5b5c7a2fec7794915;hp=8d3a897c42d76eb7ecd7f0474afdba63ba014a27;hpb=4162285358cb4611e9faa7de576d57b47dbf2ec4;p=dcpomatic.git diff --git a/src/lib/audio_buffers.cc b/src/lib/audio_buffers.cc index 8d3a897c4..9f91810e0 100644 --- a/src/lib/audio_buffers.cc +++ b/src/lib/audio_buffers.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,6 +18,8 @@ */ + +#include "util.h" #include "audio_buffers.h" #include "dcpomatic_assert.h" #include @@ -25,8 +27,11 @@ #include #include + using std::bad_alloc; -using boost::shared_ptr; +using std::shared_ptr; +using std::make_shared; + /** Construct an AudioBuffers. Audio data is undefined after this constructor. * @param channels Number of channels. @@ -37,6 +42,7 @@ AudioBuffers::AudioBuffers (int channels, int32_t frames) allocate (channels, frames); } + /** Copy constructor. * @param other Other AudioBuffers; data is copied. */ @@ -46,12 +52,21 @@ AudioBuffers::AudioBuffers (AudioBuffers const & other) copy_from (&other, other._frames, 0, 0); } -AudioBuffers::AudioBuffers (boost::shared_ptr other) + +AudioBuffers::AudioBuffers (std::shared_ptr other) { allocate (other->_channels, other->_frames); copy_from (other.get(), other->_frames, 0, 0); } + +AudioBuffers::AudioBuffers (std::shared_ptr other, int32_t frames_to_copy, int32_t read_offset) +{ + allocate (other->_channels, frames_to_copy); + copy_from (other.get(), frames_to_copy, read_offset, 0); +} + + AudioBuffers & AudioBuffers::operator= (AudioBuffers const & other) { @@ -66,12 +81,14 @@ AudioBuffers::operator= (AudioBuffers const & other) return *this; } + /** AudioBuffers destructor */ AudioBuffers::~AudioBuffers () { deallocate (); } + void AudioBuffers::allocate (int channels, int32_t frames) { @@ -82,19 +99,20 @@ AudioBuffers::allocate (int channels, int32_t frames) _frames = frames; _allocated_frames = frames; - _data = static_cast (malloc (_channels * sizeof (float *))); + _data = static_cast (malloc(_channels * sizeof(float *))); if (!_data) { throw bad_alloc (); } for (int i = 0; i < _channels; ++i) { - _data[i] = static_cast (malloc (frames * sizeof (float))); + _data[i] = static_cast (malloc(frames * sizeof(float))); if (!_data[i]) { throw bad_alloc (); } } } + void AudioBuffers::deallocate () { @@ -105,6 +123,7 @@ AudioBuffers::deallocate () free (_data); } + /** @param c Channel index. * @return Buffer for this channel. */ @@ -115,6 +134,7 @@ AudioBuffers::data (int c) const return _data[c]; } + /** Set the number of frames that these AudioBuffers will report themselves * as having. If we reduce the number of frames, the `lost' frames will * be silenced. @@ -125,10 +145,13 @@ AudioBuffers::set_frames (int32_t f) { DCPOMATIC_ASSERT (f <= _allocated_frames); - make_silent (f, _frames - f); + if (f < _frames) { + make_silent (f, _frames - f); + } _frames = f; } + /** Make all frames silent */ void AudioBuffers::make_silent () @@ -138,6 +161,7 @@ AudioBuffers::make_silent () } } + /** Make all samples on a given channel silent. * @param c Channel. */ @@ -152,6 +176,7 @@ AudioBuffers::make_silent (int c) memset (_data[c], 0, _frames * sizeof(float)); } + /** Make some frames. * @param from Start frame. * @param frames Number of frames to silence. @@ -169,6 +194,7 @@ AudioBuffers::make_silent (int32_t from, int32_t frames) } } + /** Copy data from another AudioBuffers to this one. All channels are copied. * @param from AudioBuffers to copy from; must have the same number of channels as this. * @param frames_to_copy Number of frames to copy. @@ -183,9 +209,8 @@ AudioBuffers::copy_from (AudioBuffers const * from, int32_t frames_to_copy, int3 return; } - DCPOMATIC_ASSERT (from->channels() == channels()); - DCPOMATIC_ASSERT (from); + DCPOMATIC_ASSERT (from->channels() == channels()); DCPOMATIC_ASSERT (read_offset >= 0 && (read_offset + frames_to_copy) <= from->_allocated_frames); DCPOMATIC_ASSERT (write_offset >= 0 && (write_offset + frames_to_copy) <= _allocated_frames); @@ -194,6 +219,7 @@ AudioBuffers::copy_from (AudioBuffers const * from, int32_t frames_to_copy, int3 } } + /** Move audio data around. * @param from Offset to move from. * @param to Offset to move to. @@ -220,6 +246,7 @@ AudioBuffers::move (int32_t frames, int32_t from, int32_t to) } } + /** Add data from from `from', `from_channel' to our channel `to_channel'. * @param from Buffers to copy data from. * @param from_channel Channel index to read in \p from. @@ -233,14 +260,15 @@ AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, i DCPOMATIC_ASSERT (from->frames() == N); DCPOMATIC_ASSERT (to_channel <= _channels); - float* s = from->data (from_channel); - float* d = _data[to_channel]; + auto s = from->data (from_channel); + auto d = _data[to_channel]; for (int i = 0; i < N; ++i) { *d++ += (*s++) * gain; } } + /** Ensure we have space for at least a certain number of frames. If we extend * the buffers, fill the new space with silence. */ @@ -263,16 +291,20 @@ AudioBuffers::ensure_size (int32_t frames) frames++; for (int i = 0; i < _channels; ++i) { - _data[i] = static_cast (realloc (_data[i], frames * sizeof (float))); + _data[i] = static_cast (realloc(_data[i], frames * sizeof(float))); if (!_data[i]) { throw bad_alloc (); } } - make_silent (_allocated_frames, frames - _allocated_frames); + auto const old_allocated = _allocated_frames; _allocated_frames = frames; + if (old_allocated < _allocated_frames) { + make_silent (old_allocated, _allocated_frames - old_allocated); + } } + /** 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. @@ -286,7 +318,7 @@ AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t frames, int3 DCPOMATIC_ASSERT (read_offset >= 0); DCPOMATIC_ASSERT (write_offset >= 0); - float** from_data = from->data (); + auto 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]; @@ -294,11 +326,12 @@ AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t frames, int3 } } + /** @param dB gain in dB */ void AudioBuffers::apply_gain (float dB) { - float const linear = pow (10, dB / 20); + auto const linear = db_to_linear (dB); for (int i = 0; i < _channels; ++i) { for (int j = 0; j < _frames; ++j) { @@ -307,17 +340,19 @@ AudioBuffers::apply_gain (float dB) } } + /** @param c Channel index. * @return AudioBuffers object containing only channel `c' from this AudioBuffers. */ shared_ptr AudioBuffers::channel (int c) const { - shared_ptr o (new AudioBuffers (1, frames ())); + auto o = make_shared(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. @@ -330,15 +365,17 @@ AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, in memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float)); } + /** Make a copy of these AudioBuffers */ shared_ptr AudioBuffers::clone () const { - shared_ptr b (new AudioBuffers (channels (), frames ())); - b->copy_from (this, frames (), 0, 0); + auto b = make_shared(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 other) @@ -349,6 +386,7 @@ AudioBuffers::append (shared_ptr other) _frames += other->frames(); } + /** Remove some frames from the start of these AudioBuffers */ void AudioBuffers::trim_start (int32_t frames)