- /* Compute the resampled frames count and add 32 for luck */
- int const max_resampled_frames = ceil ((double) in->frames() * _out_rate / _in_rate) + 32;
- shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, max_resampled_frames));
-
- int const resampled_frames = swr_convert (
- _swr_context, (uint8_t **) resampled->data(), max_resampled_frames, (uint8_t const **) in->data(), in->frames()
- );
-
- if (resampled_frames < 0) {
- char buf[256];
- av_strerror (resampled_frames, buf, sizeof(buf));
- throw EncodeError (String::compose (_("could not run sample-rate converter for %1 samples (%2) (%3)"), in->frames(), resampled_frames, buf));
+ 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;
+ shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, 0));
+
+ while (in_frames > 0) {
+
+ /* Compute the resampled frames count and add 32 for luck */
+ int const max_resampled_frames = ceil ((double) in_frames * _out_rate / _in_rate) + 32;
+
+ SRC_DATA data;
+ float* in_buffer = new float[in_frames * _channels];
+
+ {
+ float** p = in->data ();
+ 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];
+ }
+ }
+ }
+
+ data.data_in = in_buffer;
+ data.input_frames = in_frames;
+
+ data.data_out = new float[max_resampled_frames * _channels];
+ data.output_frames = max_resampled_frames;
+
+ data.end_of_input = 0;
+ data.src_ratio = double (_out_rate) / _in_rate;
+
+ int const r = src_process (_src, &data);
+ if (r) {
+ delete[] data.data_in;
+ delete[] data.data_out;
+ throw EncodeError (
+ String::compose (
+ N_("could not run sample-rate converter (%1) [processing %2 to %3, %4 channels]"),
+ src_strerror (r),
+ in_frames,
+ max_resampled_frames,
+ _channels
+ )
+ );
+ }
+
+ if (data.output_frames_gen == 0) {
+ break;
+ }
+
+ resampled->ensure_size (out_offset + data.output_frames_gen);
+ resampled->set_frames (out_offset + data.output_frames_gen);
+
+ {
+ float* p = data.data_out;
+ float** q = resampled->data ();
+ for (int i = 0; i < data.output_frames_gen; ++i) {
+ for (int j = 0; j < _channels; ++j) {
+ q[j][out_offset + i] = *p++;
+ }
+ }
+ }
+
+ in_frames -= data.input_frames_used;
+ in_offset += data.input_frames_used;
+ out_offset += data.output_frames_gen;
+
+ delete[] data.data_in;
+ delete[] data.data_out;