Strip trailing whitespace and fix other whitespace errors (e.g. space/tab mixing...
[ardour.git] / libs / ardour / export_utilities.cc
1 /*
2     Copyright (C) 1999-2008 Paul Davis
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 /* see gdither.cc for why we have to do this */
21
22 #define _ISOC9X_SOURCE  1
23 #define _ISOC99_SOURCE  1
24 #include <cmath>
25 #undef  _ISOC99_SOURCE
26 #undef  _ISOC9X_SOURCE
27 #undef  __USE_SVID
28 #define __USE_SVID 1
29 #include <cstdlib>
30 #undef  __USE_SVID
31
32 #include <unistd.h>
33 #include <inttypes.h>
34 #include <float.h>
35
36 /* ...*/
37
38 #include "ardour/export_utilities.h"
39
40 #include <string.h>
41
42 #include "ardour/export_failed.h"
43 #include "ardour/gdither.h"
44 #include "ardour/dB.h"
45 #include "pbd/failed_constructor.h"
46
47 #include "i18n.h"
48
49 using namespace PBD;
50
51 namespace ARDOUR
52 {
53 /* SampleRateConverter */
54
55 SampleRateConverter::SampleRateConverter (uint32_t channels, nframes_t in_rate, nframes_t out_rate, int quality) :
56   channels (channels),
57   leftover_frames (0),
58   max_leftover_frames (0),
59   frames_in (0),
60   frames_out(0),
61   data_in (0),
62   leftover_data (0),
63   data_out (0),
64   data_out_size (0),
65   src_state (0)
66 {
67         if (in_rate == out_rate) {
68                 active = false;
69                 return;
70         }
71
72         active = true;
73         int err;
74
75         if ((src_state = src_new (quality, channels, &err)) == 0) {
76                 throw ExportFailed (string_compose (X_("Cannot initialize sample rate conversion: %1"), src_strerror (err)));
77         }
78
79         src_data.src_ratio = out_rate / (double) in_rate;
80 }
81
82 SampleRateConverter::~SampleRateConverter ()
83 {
84         if (src_state) {
85                 src_delete (src_state);
86         }
87
88         delete [] data_out;
89
90         if (leftover_data) {
91                 free (leftover_data);
92         }
93 }
94
95 nframes_t
96 SampleRateConverter::process (float * data, nframes_t frames)
97 {
98         if (!active) {
99                 // Just pass it on...
100                 return piped_to->write (data, frames);
101         }
102
103         /* Manage memory */
104
105         nframes_t out_samples_max = (nframes_t) ceil (frames * src_data.src_ratio * channels);
106         if (data_out_size < out_samples_max) {
107
108                 delete[] data_out;
109
110                 data_out = new float[out_samples_max];
111                 src_data.data_out = data_out;
112
113                 max_leftover_frames = 4 * frames;
114                 leftover_data = (float *) realloc (leftover_data, max_leftover_frames * channels * sizeof (float));
115                 if (!leftover_data) {
116                         throw ExportFailed (X_("A memory allocation error occured during sample rate conversion"));
117                 }
118
119                 data_out_size = out_samples_max;
120         }
121
122         /* Do SRC */
123
124         data_in = data;
125         frames_in = frames;
126
127         int err;
128         int cnt = 0;
129         nframes_t frames_out_total = 0;
130
131         do {
132                 src_data.output_frames = out_samples_max / channels;
133                 src_data.end_of_input = end_of_input;
134                 src_data.data_out = data_out;
135
136                 if (leftover_frames > 0) {
137
138                         /* input data will be in leftover_data rather than data_in */
139
140                         src_data.data_in = leftover_data;
141
142                         if (cnt == 0) {
143
144                                 /* first time, append new data from data_in into the leftover_data buffer */
145
146                                 memcpy (leftover_data + (leftover_frames * channels), data_in, frames_in * channels * sizeof(float));
147                                 src_data.input_frames = frames_in + leftover_frames;
148                         } else {
149
150                                 /* otherwise, just use whatever is still left in leftover_data; the contents
151                                         were adjusted using memmove() right after the last SRC call (see
152                                         below)
153                                 */
154
155                                 src_data.input_frames = leftover_frames;
156                         }
157
158                 } else {
159
160                         src_data.data_in = data_in;
161                         src_data.input_frames = frames_in;
162
163                 }
164
165                 ++cnt;
166
167                 if ((err = src_process (src_state, &src_data)) != 0) {
168                         throw ExportFailed (string_compose ("An error occured during sample rate conversion: %1", src_strerror (err)));
169                 }
170
171                 frames_out = src_data.output_frames_gen;
172                 leftover_frames = src_data.input_frames - src_data.input_frames_used;
173
174                 if (leftover_frames > 0) {
175                         if (leftover_frames > max_leftover_frames) {
176                                 error << _("warning, leftover frames overflowed, glitches might occur in output") << endmsg;
177                                 leftover_frames = max_leftover_frames;
178                         }
179                         memmove (leftover_data, (char *) (src_data.data_in + (src_data.input_frames_used * channels)),
180                                         leftover_frames * channels * sizeof(float));
181                 }
182
183
184                 nframes_t frames_written = piped_to->write (data_out, frames_out);
185                 frames_out_total += frames_written;
186
187         } while (leftover_frames > frames_in);
188
189
190         return frames_out_total;
191 }
192
193 /* SampleFormatConverter */
194
195 template <typename TOut>
196 SampleFormatConverter<TOut>::SampleFormatConverter (uint32_t channels, ExportFormatBase::DitherType type, int data_width_) :
197   channels (channels),
198   data_width (data_width_),
199   dither (0),
200   data_out_size (0),
201   data_out (0),
202   clip_floats (false)
203 {
204         if (data_width != 24) {
205                 data_width = sizeof (TOut) * 8;
206         }
207
208         GDitherSize dither_size = GDitherFloat;
209
210         switch (data_width) {
211         case 8:
212                 dither_size = GDither8bit;
213                 break;
214
215         case 16:
216                 dither_size = GDither16bit;
217                 break;
218         case 24:
219                 dither_size = GDither32bit;
220         }
221
222         dither = gdither_new ((GDitherType) type, channels, dither_size, data_width);
223 }
224
225 template <typename TOut>
226 SampleFormatConverter<TOut>::~SampleFormatConverter ()
227 {
228         if (dither) {
229                 gdither_free (dither);
230         }
231
232         delete[] data_out;
233 }
234
235 template <typename TOut>
236 nframes_t
237 SampleFormatConverter<TOut>::process (float * data, nframes_t frames)
238 {
239         /* Make sure we have enough memory allocated */
240
241         size_t data_size = channels * frames * sizeof (TOut);
242         if (data_size  > data_out_size) {
243
244                 delete[] data_out;
245
246                 data_out = new TOut[data_size];
247                 data_out_size = data_size;
248         }
249
250         /* Do conversion */
251
252         if (data_width < 32) {
253                 for (uint32_t chn = 0; chn < channels; ++chn) {
254                         gdither_runf (dither, chn, frames, data, data_out);
255                 }
256         } else {
257                 for (uint32_t chn = 0; chn < channels; ++chn) {
258
259                         TOut * ob = data_out;
260                         const double int_max = (float) INT_MAX;
261                         const double int_min = (float) INT_MIN;
262
263                         nframes_t i;
264                         for (nframes_t x = 0; x < frames; ++x) {
265                                 i = chn + (x * channels);
266
267                                 if (data[i] > 1.0f) {
268                                         ob[i] = static_cast<TOut> (INT_MAX);
269                                 } else if (data[i] < -1.0f) {
270                                         ob[i] = static_cast<TOut> (INT_MIN);
271                                 } else {
272                                         if (data[i] >= 0.0f) {
273                                                 ob[i] = lrintf (int_max * data[i]);
274                                         } else {
275                                                 ob[i] = - lrintf (int_min * data[i]);
276                                         }
277                                 }
278                         }
279                 }
280         }
281
282         /* Write forward */
283
284         return GraphSinkVertex<float, TOut>::piped_to->write (data_out, frames);
285 }
286
287 template<>
288 nframes_t
289 SampleFormatConverter<float>::process (float * data, nframes_t frames)
290 {
291         if (clip_floats) {
292                 for (nframes_t x = 0; x < frames * channels; ++x) {
293                         if (data[x] > 1.0f) {
294                                 data[x] = 1.0f;
295                         } else if (data[x] < -1.0f) {
296                                 data[x] = -1.0f;
297                         }
298                 }
299         }
300
301         return piped_to->write (data, frames);
302 }
303
304 template class SampleFormatConverter<short>;
305 template class SampleFormatConverter<int>;
306 template class SampleFormatConverter<float>;
307
308 /* Normalizer */
309
310 Normalizer::Normalizer (uint32_t channels, float target_dB) :
311   channels (channels),
312   enabled (false)
313 {
314         target = dB_to_coefficient (target_dB);
315
316         if (target == 1.0f) {
317                 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
318                    that we may have clipped.
319                 */
320                 target -= FLT_EPSILON;
321         }
322 }
323
324 Normalizer::~Normalizer ()
325 {
326
327 }
328
329 void
330 Normalizer::set_peak (float peak)
331 {
332         if (peak == 0.0f || peak == target) {
333                 /* don't even try */
334                 enabled = false;
335         } else {
336                 enabled = true;
337                 gain = target / peak;
338         }
339 }
340
341 nframes_t
342 Normalizer::process (float * data, nframes_t frames)
343 {
344         if (enabled) {
345                 for (nframes_t i = 0; i < (channels * frames); ++i) {
346                         data[i] *= gain;
347                 }
348         }
349         return piped_to->write (data, frames);
350 }
351
352 };