Remove our forcing of analyzeduration and probesize as they seem to
[dcpomatic.git] / src / lib / audio_merger.h
index 126325a9d61cf127dd10bdaa94ac5b5998e2797e..d5a6ec43ad80ecd233049a971b813f8295785e33 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2017 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
 
 */
 
+/** @file  src/audio_merger.h
+ *  @brief AudioMerger class.
+ */
+
 #include "audio_buffers.h"
+#include "dcpomatic_time.h"
+#include "util.h"
 
-template <class T, class F>
+/** @class AudioMerger.
+ *  @brief A class that can merge audio data from many sources.
+ */
 class AudioMerger
 {
 public:
-       AudioMerger (int channels, boost::function<F (T)> t_to_f, boost::function<T (F)> f_to_t)
-               : _buffers (new AudioBuffers (channels, 0))
-               , _next_emission (0)
-               , _t_to_f (t_to_f)
-               , _f_to_t (f_to_t)
-       {}
-
-       void push (boost::shared_ptr<const AudioBuffers> audio, T time)
-       {
-               if (time > _next_emission) {
-                       /* We can emit some audio from our buffer; this is how many frames
-                          we are going to emit.
-                       */
-                       F const to_emit = _t_to_f (time - _next_emission);
-                       boost::shared_ptr<AudioBuffers> emit (new AudioBuffers (_buffers->channels(), to_emit));
-
-                       /* And this is how many we will get from our buffer */
-                       F const to_emit_from_buffers = min (to_emit, _buffers->frames ());
+       explicit AudioMerger (int frame_rate);
 
-                       /* Copy the data that we have to the back end of `emit' */
-                       emit->copy_from (_buffers.get(), to_emit_from_buffers, 0, to_emit - to_emit_from_buffers);
+       std::list<std::pair<boost::shared_ptr<AudioBuffers>, dcpomatic::DCPTime> > pull (dcpomatic::DCPTime time);
+       void push (boost::shared_ptr<const AudioBuffers> audio, dcpomatic::DCPTime time);
+       void clear ();
 
-                       /* Silence any gap at the start */
-                       emit->make_silent (0, to_emit - to_emit_from_buffers);
-
-                       /* Emit that */
-                       Audio (emit, _next_emission);
-
-                       _next_emission += _f_to_t (to_emit);
-
-                       /* And remove the data we've emitted from our buffers */
-                       if (_buffers->frames() > to_emit_from_buffers) {
-                               _buffers->move (to_emit_from_buffers, 0, _buffers->frames() - to_emit_from_buffers);
-                       }
-                       _buffers->set_frames (_buffers->frames() - to_emit_from_buffers);
-               }
-
-               /* Now accumulate the new audio into our buffers */
-               F frame = _t_to_f (time);
-               F after = max (_buffers->frames(), frame + audio->frames() - _t_to_f (_next_emission));
-               _buffers->ensure_size (after);
-               _buffers->accumulate_frames (audio.get(), 0, frame - _t_to_f (_next_emission), audio->frames ());
-               _buffers->set_frames (after);
-       }
-
-       F min (F a, int b)
-       {
-               if (a < b) {
-                       return a;
-               }
-
-               return b;
-       }
+private:
+       Frame frames (dcpomatic::DCPTime t) const;
 
-       F max (int a, F b)
+       class Buffer
        {
-               if (a > b) {
-                       return a;
+       public:
+               /** @param c Channels
+                *  @param f Frames
+                *  @param t Time
+                *  @param r Frame rate.
+                */
+               Buffer (int c, int32_t f, dcpomatic::DCPTime t, int r)
+                       : audio (new AudioBuffers (c, f))
+                       , time (t)
+                       , frame_rate (r)
+               {}
+
+               Buffer (boost::shared_ptr<AudioBuffers> a, dcpomatic::DCPTime t, int r)
+                       : audio (a)
+                       , time (t)
+                       , frame_rate (r)
+               {}
+
+               boost::shared_ptr<AudioBuffers> audio;
+               dcpomatic::DCPTime time;
+               int frame_rate;
+
+               dcpomatic::DCPTimePeriod period () const {
+                       return dcpomatic::DCPTimePeriod (time, time + dcpomatic::DCPTime::from_frames (audio->frames(), frame_rate));
                }
+       };
 
-               return b;
-       }
-               
-       void flush ()
+       class BufferComparator
        {
-               if (_buffers->frames() > 0) {
-                       Audio (_buffers, _next_emission);
+       public:
+               bool operator() (AudioMerger::Buffer const & a, AudioMerger::Buffer const & b)
+               {
+                       return a.time < b.time;
                }
-       }
-       
-       boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, T)> Audio;
+       };
 
-private:
-       boost::shared_ptr<AudioBuffers> _buffers;
-       T _next_emission;
-       boost::function<F (T)> _t_to_f;
-       boost::function<T (F)> _f_to_t;
+       std::list<Buffer> _buffers;
+       int _frame_rate;
 };