#include <cassert>
#include <cstring>
+#include <cmath>
#include <stdexcept>
#include "audio_buffers.h"
copy_from (&other, other._frames, 0, 0);
}
-/* XXX: it's a shame that this is a copy-and-paste of the above;
- probably fixable with c++0x.
-*/
AudioBuffers::AudioBuffers (boost::shared_ptr<const AudioBuffers> other)
{
allocate (other->_channels, other->_frames);
void
AudioBuffers::allocate (int channels, int frames)
{
+ assert (frames >= 0);
+ assert (channels >= 0);
+
_channels = channels;
_frames = frames;
_allocated_frames = frames;
}
/** Set the number of frames that these AudioBuffers will report themselves
- * as having.
+ * as having. If we reduce the number of frames, the `lost' frames will
+ * be silenced.
* @param f Frames; must be less than or equal to the number of allocated frames.
*/
void
AudioBuffers::set_frames (int f)
{
assert (f <= _allocated_frames);
+
+ for (int c = 0; c < _channels; ++c) {
+ for (int i = f; i < _frames; ++i) {
+ _data[c][i] = 0;
+ }
+ }
+
_frames = f;
}
void
AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset)
{
+ if (frames_to_copy == 0) {
+ /* Prevent the asserts from firing if there is nothing to do */
+ return;
+ }
+
assert (from->channels() == channels());
assert (from);
assert (frames > 0);
assert (frames <= _frames);
assert ((from + frames) <= _frames);
- assert ((to + frames) <= _frames);
+ assert ((to + frames) <= _allocated_frames);
for (int i = 0; i < _channels; ++i) {
memmove (_data[i] + to, _data[i] + from, frames * sizeof(float));
}
}
-/** Add data from from `from', `from_channel' to our channel `to_channel' */
+/** Add data from from `from', `from_channel' to our channel `to_channel'.
+ * @param gain Linear gain to apply to the data before it is added.
+ */
void
-AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel)
+AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel, float gain)
{
int const N = frames ();
assert (from->frames() == N);
float* d = _data[to_channel];
for (int i = 0; i < N; ++i) {
- *d++ += *s++;
+ *d++ += (*s++) * gain;
}
}
AudioBuffers::accumulate_frames (AudioBuffers const * from, int read_offset, int write_offset, int frames)
{
assert (_channels == from->channels ());
+ assert (read_offset >= 0);
+ assert (write_offset >= 0);
for (int i = 0; i < _channels; ++i) {
for (int j = 0; j < frames; ++j) {
}
}
+/** @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;
+}
+
+void
+AudioBuffers::copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel)
+{
+ assert (from->frames() == frames());
+ memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float));
+}
+
+shared_ptr<AudioBuffers>
+AudioBuffers::clone () const
+{
+ shared_ptr<AudioBuffers> b (new AudioBuffers (channels (), frames ()));
+ b->copy_from (this, frames (), 0, 0);
+ return b;
+}