Take audio device latency into account.
authorCarl Hetherington <cth@carlh.net>
Tue, 18 Apr 2017 11:00:30 +0000 (12:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 22:04:32 +0000 (23:04 +0100)
src/wx/film_viewer.cc
src/wx/film_viewer.h

index 56f9c15e863d4f7cd56ee634d441e6287e2b672e..fb9c5d2aba49891bead89fb83557b5e0441a1eba 100644 (file)
@@ -92,6 +92,7 @@ FilmViewer::FilmViewer (wxWindow* p)
        , _audio_channels (0)
        , _audio_block_size (1024)
        , _playing (false)
+       , _latency_history_count (0)
 {
 #ifndef __WXOSX__
        _panel->SetDoubleBuffered (true);
@@ -200,6 +201,9 @@ FilmViewer::set_film (shared_ptr<Film> film)
        _film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
        _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1));
 
+       /* Keep about 1 second's worth of history samples */
+       _latency_history_count = _film->audio_frame_rate() / _audio_block_size;
+
        recreate_butler ();
 
        calculate_sizes ();
@@ -714,7 +718,8 @@ DCPTime
 FilmViewer::time () const
 {
        if (_audio.isStreamRunning ()) {
-               return DCPTime::from_seconds (const_cast<RtAudio*>(&_audio)->getStreamTime ());
+               return DCPTime::from_seconds (const_cast<RtAudio*>(&_audio)->getStreamTime ()) -
+                       DCPTime::from_frames (average_latency(), _film->audio_frame_rate());
        }
 
        return _video_position;
@@ -724,5 +729,30 @@ int
 FilmViewer::audio_callback (void* out_p, unsigned int frames)
 {
        _butler->get_audio (reinterpret_cast<float*> (out_p), frames);
+
+        boost::mutex::scoped_lock lm (_latency_history_mutex, boost::try_to_lock);
+        if (lm) {
+                _latency_history.push_back (_audio.getStreamLatency ());
+                if (_latency_history.size() > static_cast<size_t> (_latency_history_count)) {
+                        _latency_history.pop_front ();
+                }
+        }
+
        return 0;
 }
+
+Frame
+FilmViewer::average_latency () const
+{
+        boost::mutex::scoped_lock lm (_latency_history_mutex);
+        if (_latency_history.empty()) {
+                return 0;
+        }
+
+        Frame total = 0;
+        BOOST_FOREACH (Frame i, _latency_history) {
+                total += i;
+        }
+
+        return total / _latency_history.size();
+}
index ed7795dad3f1a96233a449412caca2d609aea09f..aacede06e5bf64ff43629d8be01fb82951fff273 100644 (file)
@@ -89,6 +89,7 @@ private:
        DCPTime time () const;
        void start ();
        bool stop ();
+       Frame average_latency () const;
 
        boost::shared_ptr<Film> _film;
        boost::shared_ptr<Player> _player;
@@ -130,5 +131,10 @@ private:
        bool _playing;
        boost::shared_ptr<Butler> _butler;
 
+        std::list<Frame> _latency_history;
+        /** Mutex to protect _latency_history */
+        mutable boost::mutex _latency_history_mutex;
+        int _latency_history_count;
+
        boost::signals2::scoped_connection _config_changed_connection;
 };