/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
_frames = f;
}
-/** Make all samples on all channels silent */
+/** Make all frames silent */
void
AudioBuffers::make_silent ()
{
}
}
+/** Make some frames.
+ * @param from Start frame.
+ * @param frames Number of frames to silence.
+ */
void
AudioBuffers::make_silent (int32_t from, int32_t frames)
{
* @param to Offset to move to.
* @param frames Number of frames to move.
*/
-
void
AudioBuffers::move (int32_t frames, int32_t from, int32_t to)
{
_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)
{
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)
{
memcpy (data(to_channel), from->data(from_channel), frames() * sizeof (float));
}
+/** Make a copy of these AudioBuffers */
shared_ptr<AudioBuffers>
AudioBuffers::clone () const
{
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)
{
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
: DecoderPart (parent, log)
{
+ /* Set up _positions so that we have one for each stream */
BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
_positions[i] = 0;
}
}
if (_positions[stream] == 0) {
+ /* This is the first data we have received since initialisation or seek. Set
+ the position based on the ContentTime that was given. After this first time
+ we just count samples, as it seems that ContentTimes are unreliable from
+ FFmpegDecoder (not quite continuous; perhaps due to some rounding error).
+ */
_positions[stream] = time.frames_round (stream->frame_rate ());
}
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
boost::signals2::signal<void (AudioStreamPtr, ContentAudio)> Data;
private:
+ /** Frame after the last one that was emitted from Data for each AudioStream */
std::map<AudioStreamPtr, Frame> _positions;
};
*/
+/** @file src/audio_merger.cc
+ * @brief AudioMerger class.
+ */
+
#include "audio_merger.h"
#include "dcpomatic_time.h"
#include <iostream>
using boost::optional;
AudioMerger::AudioMerger (int frame_rate)
- : _last_pull (0)
- , _frame_rate (frame_rate)
+ : _frame_rate (frame_rate)
{
}
+Frame
+AudioMerger::frames (DCPTime t) const
+{
+ return t.frames_floor (_frame_rate);
+}
+
/** Pull audio up to a given time; after this call, no more data can be pushed
* before the specified time.
+ * @param time Time to pull up to.
+ * @return Blocks of merged audio up to `time'.
*/
list<pair<shared_ptr<AudioBuffers>, DCPTime> >
AudioMerger::pull (DCPTime time)
out.push_back (make_pair (i.audio, i.time));
} else if (i.time < time) {
/* Overlaps the end of the pull period */
- shared_ptr<AudioBuffers> audio (new AudioBuffers (i.audio->channels(), DCPTime(time - i.time).frames_floor(_frame_rate)));
+ shared_ptr<AudioBuffers> audio (new AudioBuffers (i.audio->channels(), frames(DCPTime(time - i.time))));
audio->copy_from (i.audio.get(), audio->frames(), 0, 0);
out.push_back (make_pair (audio, i.time));
i.audio->trim_start (audio->frames ());
return out;
}
+/** Push some data into the merger at a given time */
void
AudioMerger::push (boost::shared_ptr<const AudioBuffers> audio, DCPTime time)
{
DCPTimePeriod period (time, time + DCPTime::from_frames (audio->frames(), _frame_rate));
- /* Mix any parts of this new block with existing ones */
+ /* Mix any overlapping parts of this new block with existing ones */
BOOST_FOREACH (Buffer i, _buffers) {
optional<DCPTimePeriod> overlap = i.period().overlap (period);
if (overlap) {
- int32_t const offset = DCPTime(overlap->from - i.time).frames_floor(_frame_rate);
- int32_t const frames = overlap->duration().frames_floor(_frame_rate);
+ int32_t const offset = frames(DCPTime(overlap->from - i.time));
+ int32_t const frames_to_mix = frames(overlap->duration());
if (i.time < time) {
- i.audio->accumulate_frames(audio.get(), frames, 0, offset);
+ i.audio->accumulate_frames(audio.get(), frames_to_mix, 0, offset);
} else {
- i.audio->accumulate_frames(audio.get(), frames, offset, 0);
+ i.audio->accumulate_frames(audio.get(), frames_to_mix, offset, 0);
}
}
}
}
/* Get the part of audio that we want to use */
- shared_ptr<AudioBuffers> part (new AudioBuffers (audio->channels(), i.to.frames_floor(_frame_rate) - i.from.frames_floor(_frame_rate)));
- part->copy_from (audio.get(), part->frames(), DCPTime(i.from - time).frames_floor(_frame_rate), 0);
+ shared_ptr<AudioBuffers> part (new AudioBuffers (audio->channels(), frames(i.to) - frames(i.from)));
+ part->copy_from (audio.get(), part->frames(), frames(DCPTime(i.from - time)), 0);
if (before == _buffers.end() && after == _buffers.end()) {
/* New buffer */
*/
+/** @file src/audio_merger.h
+ * @brief AudioMerger class.
+ */
+
#include "audio_buffers.h"
#include "dcpomatic_time.h"
#include "util.h"
+/** @class AudioMerger.
+ * @brief A class that can merge audio data from many sources.
+ */
class AudioMerger
{
public:
AudioMerger (int frame_rate);
- /** Pull audio up to a given time; after this call, no more data can be pushed
- * before the specified time.
- */
std::list<std::pair<boost::shared_ptr<AudioBuffers>, DCPTime> > pull (DCPTime time);
void push (boost::shared_ptr<const AudioBuffers> audio, DCPTime time);
private:
+ Frame frames (DCPTime t) const;
+
class Buffer
{
public: