player->set_ignore_video ();
player->set_fast ();
- int64_t const len = _playlist->length().frames_round (_film->audio_frame_rate());
+ DCPTime const start = _playlist->start().get_value_or (DCPTime ());
+ DCPTime const length = _playlist->length ();
+
+ Frame const len = DCPTime (length - start).frames_round (_film->audio_frame_rate());
_samples_per_point = max (int64_t (1), len / _num_points);
delete[] _current;
if (has_any_audio) {
_done = 0;
DCPTime const block = DCPTime::from_seconds (1.0 / 8);
- for (DCPTime t; t < _film->length(); t += block) {
+ for (DCPTime t = start; t < length; t += block) {
analyse (player->get_audio (t, block, false));
- set_progress (t.seconds() / _film->length().seconds());
+ set_progress ((t.seconds() - start.seconds()) / (length.seconds() - start.seconds()));
}
}
* @param channels Number of channels.
* @param frames Number of frames to reserve space for.
*/
-AudioBuffers::AudioBuffers (int channels, int frames)
+AudioBuffers::AudioBuffers (int channels, int32_t frames)
{
allocate (channels, frames);
}
}
void
-AudioBuffers::allocate (int channels, int frames)
+AudioBuffers::allocate (int channels, int32_t frames)
{
DCPOMATIC_ASSERT (frames >= 0);
DCPOMATIC_ASSERT (channels >= 0);
* @param f Frames; must be less than or equal to the number of allocated frames.
*/
void
-AudioBuffers::set_frames (int f)
+AudioBuffers::set_frames (int32_t f)
{
DCPOMATIC_ASSERT (f <= _allocated_frames);
}
void
-AudioBuffers::make_silent (int from, int frames)
+AudioBuffers::make_silent (int32_t from, int32_t frames)
{
DCPOMATIC_ASSERT ((from + frames) <= _allocated_frames);
* @param write_offset Offset to write to in `to'.
*/
void
-AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset)
+AudioBuffers::copy_from (AudioBuffers const * from, int32_t frames_to_copy, int32_t read_offset, int32_t write_offset)
{
if (frames_to_copy == 0) {
/* Prevent the asserts from firing if there is nothing to do */
*/
void
-AudioBuffers::move (int from, int to, int frames)
+AudioBuffers::move (int32_t from, int32_t to, int32_t frames)
{
if (frames == 0) {
return;
* the buffers, fill the new space with silence.
*/
void
-AudioBuffers::ensure_size (int frames)
+AudioBuffers::ensure_size (int32_t frames)
{
if (_allocated_frames >= frames) {
return;
}
+ /* Round up frames to the next power of 2 to reduce the number
+ of realloc()s that are necessary.
+ */
+ frames--;
+ frames |= frames >> 1;
+ frames |= frames >> 2;
+ frames |= frames >> 4;
+ frames |= frames >> 8;
+ frames |= frames >> 16;
+ frames++;
+
for (int i = 0; i < _channels; ++i) {
_data[i] = static_cast<float*> (realloc (_data[i], frames * sizeof (float)));
if (!_data[i]) {
}
void
-AudioBuffers::accumulate_frames (AudioBuffers const * from, int read_offset, int write_offset, int frames)
+AudioBuffers::accumulate_frames (AudioBuffers const * from, int32_t read_offset, int32_t write_offset, int32_t frames)
{
DCPOMATIC_ASSERT (_channels == from->channels ());
DCPOMATIC_ASSERT (read_offset >= 0);
/** @class AudioBuffers
* @brief A class to hold multi-channel audio data in float format.
+ *
+ * The use of int32_t for frame counts in this class is due to the
+ * round-up to the next power-of-2 code in ::ensure_size; if that
+ * were changed the frame count could use any integer type.
*/
class AudioBuffers
{
public:
- AudioBuffers (int channels, int frames);
+ AudioBuffers (int channels, int32_t frames);
AudioBuffers (AudioBuffers const &);
AudioBuffers (boost::shared_ptr<const AudioBuffers>);
~AudioBuffers ();
boost::shared_ptr<AudioBuffers> clone () const;
boost::shared_ptr<AudioBuffers> channel (int) const;
- void ensure_size (int);
+ void ensure_size (int32_t);
float** data () const {
return _data;
return _frames;
}
- void set_frames (int f);
+ void set_frames (int32_t f);
void make_silent ();
void make_silent (int c);
- void make_silent (int from, int frames);
+ void make_silent (int32_t from, int32_t frames);
void apply_gain (float);
- void copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset);
+ void copy_from (AudioBuffers const * from, int32_t frames_to_copy, int32_t read_offset, int32_t write_offset);
void copy_channel_from (AudioBuffers const * from, int from_channel, int to_channel);
- void move (int from, int to, int frames);
+ void move (int32_t from, int32_t to, int32_t frames);
void accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel, float gain = 1);
- void accumulate_frames (AudioBuffers const *, int read_offset, int write_offset, int frames);
+ void accumulate_frames (AudioBuffers const *, int32_t read_offset, int32_t write_offset, int32_t frames);
private:
- void allocate (int, int);
+ void allocate (int channels, int32_t frames);
void deallocate ();
/** Number of channels */
int _channels;
/** Number of frames (where a frame is one sample across all channels) */
- int _frames;
+ int32_t _frames;
/** Number of frames that _data can hold */
- int _allocated_frames;
+ int32_t _allocated_frames;
/** Audio data (so that, e.g. _data[2][6] is channel 2, sample 6) */
float** _data;
};
_playlist->move_later (c);
}
+/** @return length of the film from time 0 to the last thing on the playlist */
DCPTime
Film::length () const
{
return best->dcp;
}
+/** @return length of the playlist from time 0 to the last thing on the playlist */
DCPTime
Playlist::length () const
{
return len;
}
+/** @return position of the first thing on the playlist, if it's not empty */
+optional<DCPTime>
+Playlist::start () const
+{
+ if (_content.empty ()) {
+ return optional<DCPTime> ();
+ }
+
+ DCPTime start = DCPTime::max ();
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ start = min (start, i->position ());
+ }
+
+ return start;
+}
+
void
Playlist::reconnect ()
{
std::string video_identifier () const;
DCPTime length () const;
+ boost::optional<DCPTime> start () const;
int best_dcp_frame_rate () const;
DCPTime video_end () const;