Fix merging of audio in various circumstances.
[dcpomatic.git] / src / lib / writer.cc
index 88925cbbdbeb8596c1a809faf45884dad913b586..c507c552758bb4ca8ee9a0f081042b9de20f5f42 100644 (file)
@@ -229,23 +229,40 @@ Writer::fake_write (Frame frame, Eyes eyes)
        _empty_condition.notify_all ();
 }
 
-/** Write one video frame's worth of audio frames to the DCP.
+/** Write some audio frames to the DCP.
  *  @param audio Audio data or 0 if there is no audio to be written here (i.e. it is referenced).
  *  This method is not thread safe.
  */
 void
 Writer::write (shared_ptr<const AudioBuffers> audio)
 {
-       if (_audio_reel == _reels.end ()) {
-               /* This audio is off the end of the last reel; ignore it */
-               return;
-       }
+       /* The audio we get might span a reel boundary, and if so we have to write it in bits */
 
-       _audio_reel->write (audio);
+       int32_t offset = 0;
+       while (offset < audio->frames ()) {
+
+               if (_audio_reel == _reels.end ()) {
+                       /* This audio is off the end of the last reel; ignore it */
+                       return;
+               }
+
+               int32_t const this_time = min (
+                       audio->frames() - offset,
+                       (int32_t) (_audio_reel->period().duration().frames_floor(_film->audio_frame_rate()) - _audio_reel->total_written_audio_frames())
+                       );
+
+               if (this_time == audio->frames()) {
+                       /* Easy case: we can write all the audio to this reel */
+                       _audio_reel->write (audio);
+               } else {
+                       /* Write the part we can */
+                       shared_ptr<AudioBuffers> part (new AudioBuffers (audio->channels(), this_time));
+                       part->copy_from (audio.get(), this_time, offset, 0);
+                       _audio_reel->write (part);
+                       ++_audio_reel;
+               }
 
-       /* written is in video frames, not audio frames */
-       if (_audio_reel->total_written_audio_frames() >= _audio_reel->period().duration().frames_floor (_film->video_frame_rate())) {
-               ++_audio_reel;
+               offset += this_time;
        }
 }