Fixes for silence in projects, various cleanups.
[dcpomatic.git] / src / lib / audio_decoder.cc
index 4b77a8afbe0a1f56787f110c60c227cdd849b262..5425798f6b615a9ec10a3de15a8200b97dcb0219 100644 (file)
@@ -60,6 +60,11 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
                   we just count samples, as it seems that ContentTimes are unreliable from
                   FFmpegDecoder (not quite continuous; perhaps due to some rounding error).
                */
+               if (_content->delay() > 0) {
+                       /* Insert silence to give the delay */
+                       silence (_content->delay ());
+               }
+               time += ContentTime::from_seconds (_content->delay() / 1000.0);
                _positions[stream] = time.frames_round (stream->frame_rate ());
        }
 
@@ -93,12 +98,21 @@ AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data,
        _positions[stream] += data->frames();
 }
 
+/** @return Time just after the last thing that was emitted from a given stream */
+ContentTime
+AudioDecoder::stream_position (AudioStreamPtr stream) const
+{
+       map<AudioStreamPtr, Frame>::const_iterator i = _positions.find (stream);
+       DCPOMATIC_ASSERT (i != _positions.end ());
+       return ContentTime::from_frames (i->second, _content->resampled_frame_rate());
+}
+
 ContentTime
 AudioDecoder::position () const
 {
        optional<ContentTime> p;
        for (map<AudioStreamPtr, Frame>::const_iterator i = _positions.begin(); i != _positions.end(); ++i) {
-               ContentTime const ct = ContentTime::from_frames (i->second, _content->resampled_frame_rate());
+               ContentTime const ct = stream_position (i->first);
                if (!p || ct < *p) {
                        p = ct;
                }
@@ -130,4 +144,20 @@ AudioDecoder::flush ()
                        _positions[i->first] += ro->frames();
                }
        }
+
+       if (_content->delay() < 0) {
+               /* Finish off with the gap caused by the delay */
+               silence (-_content->delay ());
+       }
+}
+
+void
+AudioDecoder::silence (int milliseconds)
+{
+       BOOST_FOREACH (AudioStreamPtr i, _content->streams ()) {
+               int const samples = ContentTime::from_seconds(milliseconds / 1000.0).frames_round(i->frame_rate());
+               shared_ptr<AudioBuffers> silence (new AudioBuffers (i->channels(), samples));
+               silence->make_silent ();
+               Data (i, ContentAudio (silence, _positions[i]));
+       }
 }