Merge remote-tracking branch 'origin/master' into 2.0
[dcpomatic.git] / src / lib / resampler.cc
1 /*
2     Copyright (C) 2013-2014 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         swr_init (_swr_context);
56 }
57
58 Resampler::~Resampler ()
59 {
60         swr_free (&_swr_context);
61 }
62
63 shared_ptr<const AudioBuffers>
64 Resampler::run (shared_ptr<const AudioBuffers> in)
65 {
66         /* Compute the resampled frames count and add 32 for luck */
67         int const max_resampled_frames = ceil ((double) in->frames() * _out_rate / _in_rate) + 32;
68         shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, max_resampled_frames));
69
70         int const resampled_frames = swr_convert (
71                 _swr_context, (uint8_t **) resampled->data(), max_resampled_frames, (uint8_t const **) in->data(), in->frames()
72                 );
73         
74         if (resampled_frames < 0) {
75                 char buf[256];
76                 av_strerror (resampled_frames, buf, sizeof(buf));
77                 throw EncodeError (String::compose (_("could not run sample-rate converter for %1 samples (%2) (%3)"), in->frames(), resampled_frames, buf));
78         }
79         
80         resampled->set_frames (resampled_frames);
81         return resampled;
82 }       
83
84 shared_ptr<const AudioBuffers>
85 Resampler::flush ()
86 {
87         shared_ptr<AudioBuffers> out (new AudioBuffers (_channels, 0));
88         int out_offset = 0;
89         int64_t const pass_size = 256;
90         shared_ptr<AudioBuffers> pass (new AudioBuffers (_channels, 256));
91
92         while (true) {
93                 int const frames = swr_convert (_swr_context, (uint8_t **) pass->data(), pass_size, 0, 0);
94                 
95                 if (frames < 0) {
96                         throw EncodeError (_("could not run sample-rate converter"));
97                 }
98                 
99                 if (frames == 0) {
100                         break;
101                 }
102
103                 out->ensure_size (out_offset + frames);
104                 out->copy_from (pass.get(), frames, 0, out_offset);
105                 out_offset += frames;
106                 out->set_frames (out_offset);
107         }
108
109         return out;
110 }