Use SRC_LINEAR for speed when analysing audio (#685).
authorCarl Hetherington <cth@carlh.net>
Wed, 9 Sep 2015 08:50:48 +0000 (09:50 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 9 Sep 2015 08:50:48 +0000 (09:50 +0100)
22 files changed:
ChangeLog
src/lib/analyse_audio_job.cc
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/audio_decoder_stream.cc
src/lib/dcp_decoder.cc
src/lib/dcp_decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/player.cc
src/lib/player.h
src/lib/resampler.cc
src/lib/resampler.h
src/lib/sndfile_decoder.cc
src/lib/sndfile_decoder.h
test/audio_decoder_test.cc
test/dcp_subtitle_test.cc
test/ffmpeg_decoder_seek_test.cc
test/ffmpeg_decoder_sequential_test.cc
test/ffmpeg_pts_offset_test.cc
test/resampler_test.cc
test/seek_zero_test.cc

index 676cc7bfb763e1f4436d02e207939a2c852a528d..31c35e39253c590eed3a877e394440e8370d4276 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-09-09  c.hetherington  <cth@carlh.net>
+
+       * Use SRC_LINEAR when resampling for
+       audio analysis to speed things up (#685).
+
 2015-09-08  c.hetherington  <cth@carlh.net>
 
        * Missing libsamplerate dylib for OS X.
index b45af646d24f664a371711470157c04ca9c56e95..c863c6c68529366bb6403b0b2222cf662fc95cff 100644 (file)
@@ -72,6 +72,7 @@ AnalyseAudioJob::run ()
 {
        shared_ptr<Player> player (new Player (_film, _playlist));
        player->set_ignore_video ();
+       player->set_fast ();
 
        int64_t const len = _playlist->length().frames_round (_film->audio_frame_rate());
        _samples_per_point = max (int64_t (1), len / _num_points);
index 268a9d29629cfa7b108f3c6853e568fefd1e69ab..2944357bac7fe0f279bb8da163915c1e730f65e9 100644 (file)
@@ -30,9 +30,10 @@ using std::cout;
 using std::map;
 using boost::shared_ptr;
 
-AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content)
+AudioDecoder::AudioDecoder (shared_ptr<const AudioContent> content, bool fast)
        : _audio_content (content)
        , _ignore_audio (false)
+       , _fast (fast)
 {
        BOOST_FOREACH (AudioStreamPtr i, content->audio_streams ()) {
                _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (_audio_content, i, this));
index d5e7c6f551584b7f6547e4318b84c79ea04dc54e..716b37969d87986d5ebf449ea98a4a68900f5849 100644 (file)
@@ -39,7 +39,7 @@ class AudioDecoderStream;
 class AudioDecoder : public virtual Decoder, public boost::enable_shared_from_this<AudioDecoder>
 {
 public:
-       AudioDecoder (boost::shared_ptr<const AudioContent>);
+       AudioDecoder (boost::shared_ptr<const AudioContent>, bool fast);
 
        boost::shared_ptr<const AudioContent> audio_content () const {
                return _audio_content;
@@ -55,6 +55,10 @@ public:
 
        void set_ignore_audio ();
 
+       bool fast () const {
+               return _fast;
+       }
+
 protected:
        void audio (AudioStreamPtr stream, boost::shared_ptr<const AudioBuffers>, ContentTime);
        void flush ();
@@ -65,6 +69,7 @@ private:
        /** An AudioDecoderStream object to manage each stream in _audio_content */
        std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
        bool _ignore_audio;
+       bool _fast;
 };
 
 #endif
index 267c542cdba60d5393361ae965aeed86a4f58558..97db8a93f9ca61d392429144ff6196ba345b4084 100644 (file)
@@ -45,7 +45,7 @@ AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content,
        , _decoder (decoder)
 {
        if (content->resampled_audio_frame_rate() != _stream->frame_rate() && _stream->channels() > 0) {
-               _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_audio_frame_rate(), _stream->channels ()));
+               _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_audio_frame_rate(), _stream->channels (), decoder->fast ()));
        }
 
        reset_decoded ();
index ec1f02d3d12bbe3de540e0ca48698b5c39282857..2bdf6a8e98547840c268a6ff748fdb81ae3e24c8 100644 (file)
@@ -41,9 +41,9 @@ using std::cout;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
-DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c)
+DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, bool fast)
        : VideoDecoder (c)
-       , AudioDecoder (c)
+       , AudioDecoder (c, fast)
        , SubtitleDecoder (c)
        , _dcp_content (c)
 {
index f23b5b82d1e1983f0b58c9a54c9d825b0a78822b..15220810d0f63b5e9c871121084d110d7579f1ba 100644 (file)
@@ -35,7 +35,7 @@ struct dcp_subtitle_within_dcp_test;
 class DCPDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder
 {
 public:
-       DCPDecoder (boost::shared_ptr<const DCPContent>);
+       DCPDecoder (boost::shared_ptr<const DCPContent>, bool fast);
 
 private:
        friend struct dcp_subtitle_within_dcp_test;
index eab85c04ed48c626516b31a03dd4cd91af76327b..ae44ff5220d04a2730087b89ea4b7f49a24e1be3 100644 (file)
@@ -61,9 +61,9 @@ using std::max;
 using boost::shared_ptr;
 using dcp::Size;
 
-FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
        : VideoDecoder (c)
-       , AudioDecoder (c)
+       , AudioDecoder (c, fast)
        , SubtitleDecoder (c)
        , FFmpeg (c)
        , _log (log)
index 28d8e4baa637c5b88208b93f056eaaef36733912..5475be6122da98b51c4bb8414a837af46d0be087 100644 (file)
@@ -44,7 +44,7 @@ struct ffmpeg_pts_offset_test;
 class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder, public FFmpeg
 {
 public:
-       FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>);
+       FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>, bool fast);
 
 private:
        friend struct ::ffmpeg_pts_offset_test;
index 5e1fbcc632f96c90b14324bd59dc7101175d3460..302ab161c1128f160c520997e3d8d344dbb6efec 100644 (file)
@@ -76,6 +76,7 @@ Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist
        , _ignore_video (false)
        , _ignore_audio (false)
        , _always_burn_subtitles (false)
+       , _fast (false)
 {
        _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
        _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this));
@@ -127,13 +128,13 @@ Player::setup_pieces ()
                /* FFmpeg */
                shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i);
                if (fc) {
-                       decoder.reset (new FFmpegDecoder (fc, _film->log()));
+                       decoder.reset (new FFmpegDecoder (fc, _film->log(), _fast));
                        frc = FrameRateChange (fc->video_frame_rate(), _film->video_frame_rate());
                }
 
                shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
                if (dc) {
-                       decoder.reset (new DCPDecoder (dc));
+                       decoder.reset (new DCPDecoder (dc, _fast));
                        frc = FrameRateChange (dc->video_frame_rate(), _film->video_frame_rate());
                }
 
@@ -158,7 +159,7 @@ Player::setup_pieces ()
                /* SndfileContent */
                shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i);
                if (sc) {
-                       decoder.reset (new SndfileDecoder (sc));
+                       decoder.reset (new SndfileDecoder (sc, _fast));
                        frc = best_overlap_frc;
                }
 
@@ -674,3 +675,10 @@ Player::set_always_burn_subtitles (bool burn)
 {
        _always_burn_subtitles = burn;
 }
+
+void
+Player::set_fast ()
+{
+       _fast = true;
+       _have_valid_pieces = false;
+}
index 0a2117470a8570a5be67353bc583de9fbcd1c054..842c2283c7da034c89771bb151b9b317bc9bc0aa 100644 (file)
@@ -52,6 +52,7 @@ public:
        void set_ignore_audio ();
        void set_enable_subtitles (bool enable);
        void set_always_burn_subtitles (bool burn);
+       void set_fast ();
 
        /** Emitted when something has changed such that if we went back and emitted
         *  the last frame again it would look different.  This is not emitted after
@@ -124,6 +125,8 @@ private:
            of content settings
        */
        bool _always_burn_subtitles;
+       /** true if we should try to be fast rather than high quality */
+       bool _fast;
 
        boost::shared_ptr<AudioProcessor> _audio_processor;
 
index b12b549bf1f4618ccaacfdc4c401f7fd54adfd36..ba57deb6352bef03de31e21c03153a4c12ac9ac2 100644 (file)
@@ -31,13 +31,18 @@ using std::pair;
 using std::make_pair;
 using boost::shared_ptr;
 
-Resampler::Resampler (int in, int out, int channels)
+/** @param in Input sampling rate (Hz)
+ *  @param out Output sampling rate (Hz)
+ *  @param channels Number of channels.
+ *  @param fast true to be fast rather than good.
+ */
+Resampler::Resampler (int in, int out, int channels, bool fast)
        : _in_rate (in)
        , _out_rate (out)
        , _channels (channels)
 {
        int error;
-       _src = src_new (SRC_SINC_BEST_QUALITY, _channels, &error);
+       _src = src_new (fast ? SRC_LINEAR : SRC_SINC_BEST_QUALITY, _channels, &error);
        if (!_src) {
                throw StringError (String::compose (N_("could not create sample-rate converter (%1)"), error));
        }
index 5a69d09834e81bc483c350f26fc5ca5553263341..f51c3cdb57a3a889e4af224edb22e6975b5ab89d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ class AudioBuffers;
 class Resampler : public boost::noncopyable
 {
 public:
-       Resampler (int, int, int);
+       Resampler (int, int, int, bool fast);
        ~Resampler ();
 
        boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
index b2d35f3023937ae2b9471345b0f78e455fead2f5..49633dd1fad2e503b345bf078fa4c56e454b52c1 100644 (file)
@@ -32,9 +32,9 @@ using std::min;
 using std::cout;
 using boost::shared_ptr;
 
-SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c)
+SndfileDecoder::SndfileDecoder (shared_ptr<const SndfileContent> c, bool fast)
        : Sndfile (c)
-       , AudioDecoder (c)
+       , AudioDecoder (c, fast)
        , _done (0)
        , _remaining (_info.frames)
        , _deinterleave_buffer (0)
index c8d1f1f592df633efa5d7cd9f7d823bb5ac12425..da9016ee09a958c26211df60e4ae68b6a1d9620d 100644 (file)
@@ -25,7 +25,7 @@ class SndfileContent;
 class SndfileDecoder : public Sndfile, public AudioDecoder
 {
 public:
-       SndfileDecoder (boost::shared_ptr<const SndfileContent> c);
+       SndfileDecoder (boost::shared_ptr<const SndfileContent> c, bool fast);
        ~SndfileDecoder ();
 
 private:
index 00d555d86298ff600946b9002189d061bd3514ad..e63e1a5b0a2246b94dd94fe4bc354f7212ac81d0 100644 (file)
@@ -59,7 +59,7 @@ class TestAudioDecoder : public AudioDecoder
 {
 public:
        TestAudioDecoder (shared_ptr<TestAudioContent> content)
-               : AudioDecoder (content)
+               : AudioDecoder (content, false)
                , _test_audio_content (content)
                , _position (0)
        {}
index 9007ad6114ac2ce418121019fbb7be17f119aa63..1defe9d01f2101faf59ee13f9e4aad3c4c9467a3 100644 (file)
@@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE (dcp_subtitle_within_dcp_test)
        film->examine_and_add_content (content);
        wait_for_jobs ();
 
-       shared_ptr<DCPDecoder> decoder (new DCPDecoder (content));
+       shared_ptr<DCPDecoder> decoder (new DCPDecoder (content, false));
 
        list<ContentTimePeriod> ctp = decoder->text_subtitles_during (
                ContentTimePeriod (
index 39536f1abfd4537fd3f323cc9ce99ba1c3e6a9c2..2a9b4da715ed35ef2cab298f8b654a2759911157 100644 (file)
@@ -63,7 +63,7 @@ test (boost::filesystem::path file, vector<int> frames)
        film->examine_and_add_content (content);
        wait_for_jobs ();
        shared_ptr<Log> log (new NullLog);
-       shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
+       shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
 
        for (vector<int>::const_iterator i = frames.begin(); i != frames.end(); ++i) {
                check (decoder, *i);
index ce799bb24dc5c1175bf20497415ab3b965f3cff9..22ab61624e3c21bbeecc83c2195700bfe01b31be 100644 (file)
@@ -50,7 +50,7 @@ test (boost::filesystem::path file, float fps, int gaps)
        film->examine_and_add_content (content);
        wait_for_jobs ();
        shared_ptr<Log> log (new NullLog);
-       shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
+       shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
 
        BOOST_CHECK_CLOSE (decoder->video_content()->video_frame_rate(), fps, 0.01);
 
index 0ded564316cf8d990aaf5e8d59875770c4656632..65ed6436df9273d03d46fae506d0fa1b47353e51 100644 (file)
@@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
                /* Sound == video so no offset required */
                content->_first_video = ContentTime ();
                content->_audio_streams.front()->first_audio = ContentTime ();
-               FFmpegDecoder decoder (content, film->log());
+               FFmpegDecoder decoder (content, film->log(), false);
                BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
        }
 
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
                /* Common offset should be removed */
                content->_first_video = ContentTime::from_seconds (600);
                content->_audio_streams.front()->first_audio = ContentTime::from_seconds (600);
-               FFmpegDecoder decoder (content, film->log());
+               FFmpegDecoder decoder (content, film->log(), false);
                BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime::from_seconds (-600));
        }
 
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
                /* Video is on a frame boundary */
                content->_first_video = ContentTime::from_frames (1, 24);
                content->_audio_streams.front()->first_audio = ContentTime ();
-               FFmpegDecoder decoder (content, film->log());
+               FFmpegDecoder decoder (content, film->log(), false);
                BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
        }
 
@@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
                double const frame = 1.0 / 24.0;
                content->_first_video = ContentTime::from_seconds (frame + 0.0215);
                content->_audio_streams.front()->first_audio = ContentTime ();
-               FFmpegDecoder decoder (content, film->log());
+               FFmpegDecoder decoder (content, film->log(), false);
                BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215), 0.00001);
        }
 
@@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
                double const frame = 1.0 / 24.0;
                content->_first_video = ContentTime::from_seconds (frame + 0.0215 + 4.1);
                content->_audio_streams.front()->first_audio = ContentTime::from_seconds (4.1);
-               FFmpegDecoder decoder (content, film->log());
+               FFmpegDecoder decoder (content, film->log(), false);
                BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215) - 4.1, 0.1);
        }
 }
index d633f75c192f31a4cd3110688bcadc27d8b5304d..f536d6547612c556bfe81e41454cd25c51ed4144 100644 (file)
@@ -33,7 +33,7 @@ using boost::shared_ptr;
 static void
 resampler_test_one (int from, int to)
 {
-       Resampler resamp (from, to, 1);
+       Resampler resamp (from, to, 1, false);
 
        /* 3 hours */
        int64_t const N = int64_t (from) * 60 * 60 * 3;
index 5f870ba41f7605ceae92d2e28acb3cc1dcd2e37d..ab2b48198986adb7b9ad20d91bdea0427ba9cef0 100644 (file)
@@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE (seek_zero_test)
 
        Frame const first_frame = video_delay.round_up (content->video_frame_rate ()).frames_round (content->video_frame_rate ());
 
-       FFmpegDecoder decoder (content, film->log());
+       FFmpegDecoder decoder (content, film->log(), false);
        list<ContentVideo> a = decoder.get_video (first_frame, true);
        BOOST_CHECK (a.size() == 1);
        BOOST_CHECK_EQUAL (a.front().frame, first_frame);