Merge.
[dcpomatic.git] / src / lib / resampler.cc
1 /*
2     Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 extern "C" {
21 #include "libavutil/channel_layout.h"
22 #include "libavutil/opt.h"
23 }
24 #include "resampler.h"
25 #include "audio_buffers.h"
26 #include "exceptions.h"
27 #include "compose.hpp"
28
29 #include "i18n.h"
30
31 using std::cout;
32 using std::pair;
33 using std::make_pair;
34 using boost::shared_ptr;
35
36 Resampler::Resampler (int in, int out, int channels)
37         : _in_rate (in)
38         , _out_rate (out)
39         , _channels (channels)
40 {
41         _swr_context = swr_alloc ();
42
43         /* Sample formats */
44         av_opt_set_int (_swr_context, "isf", AV_SAMPLE_FMT_FLTP, 0);
45         av_opt_set_int (_swr_context, "osf", AV_SAMPLE_FMT_FLTP, 0);
46
47         /* Channel counts */
48         av_opt_set_int (_swr_context, "ich", _channels, 0);
49         av_opt_set_int (_swr_context, "och", _channels, 0);
50
51         /* Sample rates */
52         av_opt_set_int (_swr_context, "isr", _in_rate, 0);
53         av_opt_set_int (_swr_context, "osr", _out_rate, 0);
54
55         av_opt_set (_swr_context, "resampler", "soxr", 0);
56
57         swr_init (_swr_context);
58 }
59
60 Resampler::~Resampler ()
61 {
62         swr_free (&_swr_context);
63 }
64
65 shared_ptr<const AudioBuffers>
66 Resampler::run (shared_ptr<const AudioBuffers> in)
67 {
68         /* Compute the resampled frames count and add 32 for luck */
69         int const max_resampled_frames = ceil ((double) in->frames() * _out_rate / _in_rate) + 32;
70         shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, max_resampled_frames));
71
72         int const resampled_frames = swr_convert (
73                 _swr_context, (uint8_t **) resampled->data(), max_resampled_frames, (uint8_t const **) in->data(), in->frames()
74                 );
75
76         if (resampled_frames < 0) {
77                 char buf[256];
78                 av_strerror (resampled_frames, buf, sizeof(buf));
79                 throw EncodeError (String::compose (_("could not run sample-rate converter for %1 samples (%2) (%3)"), in->frames(), resampled_frames, buf));
80         }
81
82         resampled->set_frames (resampled_frames);
83         return resampled;
84 }
85
86 shared_ptr<const AudioBuffers>
87 Resampler::flush ()
88 {
89         shared_ptr<AudioBuffers> out (new AudioBuffers (_channels, 0));
90         int out_offset = 0;
91         int64_t const pass_size = 256;
92         shared_ptr<AudioBuffers> pass (new AudioBuffers (_channels, 256));
93
94         while (true) {
95                 int const frames = swr_convert (_swr_context, (uint8_t **) pass->data(), pass_size, 0, 0);
96
97                 if (frames < 0) {
98                         throw EncodeError (_("could not run sample-rate converter"));
99                 }
100
101                 if (frames == 0) {
102                         break;
103                 }
104
105                 out->ensure_size (out_offset + frames);
106                 out->copy_from (pass.get(), frames, 0, out_offset);
107                 out_offset += frames;
108                 out->set_frames (out_offset);
109         }
110
111         return out;
112 }