Fix analysis of audio when the subject is later in the playlist than
authorCarl Hetherington <cth@carlh.net>
Tue, 8 Sep 2015 00:10:38 +0000 (01:10 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 14 Sep 2015 09:21:14 +0000 (10:21 +0100)
some other long piece of content.  Small optimisation to AudioBuffers
to extend size logarithmically.

src/lib/analyse_audio_job.cc
src/lib/audio_buffers.cc
src/lib/audio_buffers.h
src/lib/film.cc
src/lib/playlist.cc
src/lib/playlist.h

index c863c6c68529366bb6403b0b2222cf662fc95cff..6c142f5cf773a4e4f7b76752bffe38afb4fb7792 100644 (file)
@@ -74,7 +74,10 @@ AnalyseAudioJob::run ()
        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;
@@ -91,9 +94,9 @@ AnalyseAudioJob::run ()
        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()));
                }
        }
 
index 0130f17b46d1b59562d47aca53956a7c75e56e58..05b3d4a44de9451d92cd641c6c7572bdcdade76c 100644 (file)
@@ -31,7 +31,7 @@ using boost::shared_ptr;
  *  @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);
 }
@@ -72,7 +72,7 @@ AudioBuffers::~AudioBuffers ()
 }
 
 void
-AudioBuffers::allocate (int channels, int frames)
+AudioBuffers::allocate (int channels, int32_t frames)
 {
        DCPOMATIC_ASSERT (frames >= 0);
        DCPOMATIC_ASSERT (channels >= 0);
@@ -120,7 +120,7 @@ AudioBuffers::data (int c) const
  *  @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);
 
@@ -156,7 +156,7 @@ AudioBuffers::make_silent (int c)
 }
 
 void
-AudioBuffers::make_silent (int from, int frames)
+AudioBuffers::make_silent (int32_t from, int32_t frames)
 {
        DCPOMATIC_ASSERT ((from + frames) <= _allocated_frames);
 
@@ -174,7 +174,7 @@ AudioBuffers::make_silent (int from, int 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 */
@@ -199,7 +199,7 @@ AudioBuffers::copy_from (AudioBuffers const * from, int frames_to_copy, int read
  */
 
 void
-AudioBuffers::move (int from, int to, int frames)
+AudioBuffers::move (int32_t from, int32_t to, int32_t frames)
 {
        if (frames == 0) {
                return;
@@ -241,12 +241,23 @@ AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, i
  *  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]) {
@@ -261,7 +272,7 @@ AudioBuffers::ensure_size (int frames)
 }
 
 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);
index bcf5d5928ee1330758573cf4d8a7417f46d76e56..122716d7765aef8b76eaba643ad9440cb74b6332 100644 (file)
 
 /** @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 ();
@@ -42,7 +46,7 @@ public:
        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;
@@ -58,30 +62,30 @@ public:
                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;
 };
index e48b08f3b70b7216b6035c7750b22df3cdbcd942..c89d96584a051c12451b8ead21e069d4929fe016 100644 (file)
@@ -994,6 +994,7 @@ Film::move_content_later (shared_ptr<Content> c)
        _playlist->move_later (c);
 }
 
+/** @return length of the film from time 0 to the last thing on the playlist */
 DCPTime
 Film::length () const
 {
index a1b209a1199cafc94c4fa1544160615f446d7526..4aff1015d53381652d5a15de877f90b7019d1a63 100644 (file)
@@ -263,6 +263,7 @@ Playlist::best_dcp_frame_rate () const
        return best->dcp;
 }
 
+/** @return length of the playlist from time 0 to the last thing on the playlist */
 DCPTime
 Playlist::length () const
 {
@@ -274,6 +275,22 @@ 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 ()
 {
index d9c035ac77b2b628113098c4cf1e9ee32fd22f84..76055bea0341c6ac2c831a11c0cf417de91fce5a 100644 (file)
@@ -58,6 +58,7 @@ public:
        std::string video_identifier () const;
 
        DCPTime length () const;
+       boost::optional<DCPTime> start () const;
 
        int best_dcp_frame_rate () const;
        DCPTime video_end () const;