Various fixes to push audio vaguely in the right direction.
[dcpomatic.git] / src / lib / resampler.cc
index db5552d15ab3159b17510ca1295704d8806507a0..d08e7bc38e22f60eab6486d4c9626dc5562837f7 100644 (file)
@@ -25,6 +25,7 @@
 #include "dcpomatic_assert.h"
 #include <samplerate.h>
 #include <iostream>
+#include <cmath>
 
 #include "i18n.h"
 
@@ -37,15 +38,14 @@ using boost::shared_ptr;
 /** @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)
+Resampler::Resampler (int in, int out, int channels)
        : _in_rate (in)
        , _out_rate (out)
        , _channels (channels)
 {
        int error;
-       _src = src_new (fast ? SRC_LINEAR : SRC_SINC_BEST_QUALITY, _channels, &error);
+       _src = src_new (SRC_SINC_BEST_QUALITY, _channels, &error);
        if (!_src) {
                throw runtime_error (String::compose (N_("could not create sample-rate converter (%1)"), error));
        }
@@ -56,9 +56,30 @@ Resampler::~Resampler ()
        src_delete (_src);
 }
 
-shared_ptr<const AudioBuffers>
-Resampler::run (shared_ptr<const AudioBuffers> in)
+void
+Resampler::set_fast ()
+{
+       src_delete (_src);
+       int error;
+       _src = src_new (SRC_LINEAR, _channels, &error);
+       if (!_src) {
+               throw runtime_error (String::compose (N_("could not create sample-rate converter (%1)"), error));
+       }
+}
+
+pair<shared_ptr<const AudioBuffers>, Frame>
+Resampler::run (shared_ptr<const AudioBuffers> in, Frame frame)
 {
+       if (!_next_in || !_next_out || _next_in.get() != frame) {
+               /* Either there was a discontinuity in the input or this is the first input;
+                  reset _next_out.
+               */
+               _next_out = lrintf (frame * _out_rate / _in_rate);
+       }
+
+       /* Expected next input frame */
+       _next_in = frame + in->frames ();
+
        int in_frames = in->frames ();
        int in_offset = 0;
        int out_offset = 0;
@@ -70,11 +91,11 @@ Resampler::run (shared_ptr<const AudioBuffers> in)
                int const max_resampled_frames = ceil ((double) in_frames * _out_rate / _in_rate) + 32;
 
                SRC_DATA data;
-               data.data_in = new float[in_frames * _channels];
+               float* in_buffer = new float[in_frames * _channels];
 
                {
                        float** p = in->data ();
-                       float* q = data.data_in;
+                       float* q = in_buffer;
                        for (int i = 0; i < in_frames; ++i) {
                                for (int j = 0; j < _channels; ++j) {
                                        *q++ = p[j][in_offset + i];
@@ -82,6 +103,7 @@ Resampler::run (shared_ptr<const AudioBuffers> in)
                        }
                }
 
+               data.data_in = in_buffer;
                data.input_frames = in_frames;
 
                data.data_out = new float[max_resampled_frames * _channels];
@@ -130,7 +152,12 @@ Resampler::run (shared_ptr<const AudioBuffers> in)
                delete[] data.data_out;
        }
 
-       return resampled;
+       Frame out_frame = _next_out.get ();
+
+       /* Expected next output frame */
+       _next_out = _next_out.get() + resampled->frames();
+
+       return make_pair (resampled, out_frame);
 }
 
 shared_ptr<const AudioBuffers>