use a note tracker to resolve notes cut off during render by the end of the region
[ardour.git] / libs / ardour / resampled_source.cc
1 /*
2  * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2008-2011 David Robillard <d@drobilla.net>
4  * Copyright (C) 2010 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
6  * Copyright (C) 2015-2016 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "pbd/error.h"
24 #include "ardour/resampled_source.h"
25 #include "pbd/failed_constructor.h"
26
27 #include "pbd/i18n.h"
28
29 using namespace ARDOUR;
30 using namespace PBD;
31
32 #ifdef PLATFORM_WINDOWS
33 const uint32_t ResampledImportableSource::blocksize = 524288U;
34 #else
35 const uint32_t ResampledImportableSource::blocksize = 16384U;
36 #endif
37
38 ResampledImportableSource::ResampledImportableSource (boost::shared_ptr<ImportableSource> src, samplecnt_t rate, SrcQuality srcq)
39         : source (src)
40         , _src_state (0)
41 {
42         _src_type = SRC_SINC_BEST_QUALITY;
43
44         switch (srcq) {
45         case SrcBest:
46                 _src_type = SRC_SINC_BEST_QUALITY;
47                 break;
48         case SrcGood:
49                 _src_type = SRC_SINC_MEDIUM_QUALITY;
50                 break;
51         case SrcQuick:
52                 _src_type = SRC_SINC_FASTEST;
53                 break;
54         case SrcFast:
55                 _src_type = SRC_ZERO_ORDER_HOLD;
56                 break;
57         case SrcFastest:
58                 _src_type = SRC_LINEAR;
59                 break;
60         }
61
62         _input = new float[blocksize];
63
64         seek (0);
65
66         _src_data.src_ratio = ((float) rate) / source->samplerate();
67 }
68
69 ResampledImportableSource::~ResampledImportableSource ()
70 {
71         _src_state = src_delete (_src_state) ;
72         delete [] _input;
73 }
74
75 samplecnt_t
76 ResampledImportableSource::read (Sample* output, samplecnt_t nframes)
77 {
78         int err;
79         size_t bs = floor ((float)(blocksize / source->channels())) *  source->channels();
80
81         /* If the input buffer is empty, refill it. */
82         if (_src_data.input_frames == 0) {
83
84                 _src_data.input_frames = source->read (_input, bs);
85
86                 /* The last read will not be a full buffer, so set end_of_input. */
87                 if ((size_t) _src_data.input_frames < bs) {
88                         _end_of_input = true;
89                 }
90
91                 _src_data.input_frames /= source->channels();
92                 _src_data.data_in = _input;
93         }
94
95         _src_data.data_out = output;
96         _src_data.output_frames = nframes / source->channels();
97
98         if (_end_of_input && _src_data.input_frames * _src_data.src_ratio <= _src_data.output_frames) {
99                 /* only set src_data.end_of_input for the last cycle.
100                  *
101                  * The flag only affects writing out remaining data in the
102                  * internal buffer of src_state.
103                  * SRC is not aware of data bufered here in _src_data.input
104                  * which needs to be processed first.
105                  */
106                 _src_data.end_of_input = true;
107         }
108
109         if ((err = src_process (_src_state, &_src_data))) {
110                 error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
111                 return 0 ;
112         }
113
114         /* Terminate if at end */
115         if (_src_data.end_of_input && _src_data.output_frames_gen == 0) {
116                 return 0;
117         }
118
119         _src_data.data_in += _src_data.input_frames_used * source->channels();
120         _src_data.input_frames -= _src_data.input_frames_used ;
121
122         return _src_data.output_frames_gen * source->channels();
123 }
124
125 void
126 ResampledImportableSource::seek (samplepos_t pos)
127 {
128         source->seek (pos);
129
130         /* and reset things so that we start from scratch with the conversion */
131
132         if (_src_state) {
133                 src_delete (_src_state);
134         }
135
136         int err;
137
138         if ((_src_state = src_new (_src_type, source->channels(), &err)) == 0) {
139                 error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
140                 throw failed_constructor ();
141         }
142
143         _src_data.input_frames = 0;
144         _src_data.data_in = _input;
145         _src_data.end_of_input = 0;
146         _end_of_input = false;
147 }
148
149 samplepos_t
150 ResampledImportableSource::natural_position () const
151 {
152         return source->natural_position() * ratio ();
153 }