2 Copyright (C) 1999-2008 Paul Davis
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.
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.
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.
20 /* see gdither.cc for why we have to do this */
22 #define _ISOC9X_SOURCE 1
23 #define _ISOC99_SOURCE 1
38 #include <ardour/export_utilities.h>
40 #include <ardour/export_failed.h>
41 #include <ardour/gdither.h>
42 #include <ardour/dB.h>
43 #include <pbd/failed_constructor.h>
51 /* SampleRateConverter */
53 SampleRateConverter::SampleRateConverter (uint32_t channels, nframes_t in_rate, nframes_t out_rate, int quality) :
62 if (in_rate == out_rate) {
70 if ((src_state = src_new (quality, channels, &err)) == 0) {
71 throw ExportFailed (string_compose (_("cannot initialize sample rate conversion: %1"), src_strerror (err)), "Cannot initialize sample rate conversion");
74 src_data.src_ratio = out_rate / (double) in_rate;
77 SampleRateConverter::~SampleRateConverter ()
80 src_delete (src_state);
91 SampleRateConverter::process (float * data, nframes_t frames)
95 return piped_to->write (data, frames);
100 nframes_t out_samples_max = (nframes_t) ceil (frames * src_data.src_ratio * channels);
101 if (data_out_size < out_samples_max) {
104 data_out = new float[out_samples_max];
105 src_data.data_out = data_out;
107 max_leftover_frames = 4 * frames;
108 leftover_data = (float *) realloc (leftover_data, max_leftover_frames * channels * sizeof (float));
109 if (!leftover_data) {
110 throw ExportFailed (_("A memory allocation error occured during sample rate conversion"), "Samplerate conversion failed");
113 data_out_size = out_samples_max;
123 nframes_t frames_out_total = 0;
126 src_data.output_frames = out_samples_max / channels;
127 src_data.end_of_input = end_of_input;
128 src_data.data_out = data_out;
130 if (leftover_frames > 0) {
132 /* input data will be in leftover_data rather than data_in */
134 src_data.data_in = leftover_data;
138 /* first time, append new data from data_in into the leftover_data buffer */
140 memcpy (leftover_data + (leftover_frames * channels), data_in, frames_in * channels * sizeof(float));
141 src_data.input_frames = frames_in + leftover_frames;
144 /* otherwise, just use whatever is still left in leftover_data; the contents
145 were adjusted using memmove() right after the last SRC call (see
149 src_data.input_frames = leftover_frames;
154 src_data.data_in = data_in;
155 src_data.input_frames = frames_in;
161 if ((err = src_process (src_state, &src_data)) != 0) {
162 throw ExportFailed (_("an error occured during sample rate conversion"), string_compose ("an error occured during sample rate conversion: %1", src_strerror (err)));
165 frames_out = src_data.output_frames_gen;
166 leftover_frames = src_data.input_frames - src_data.input_frames_used;
168 if (leftover_frames > 0) {
169 if (leftover_frames > max_leftover_frames) {
170 error << _("warning, leftover frames overflowed, glitches might occur in output") << endmsg;
171 leftover_frames = max_leftover_frames;
173 memmove (leftover_data, (char *) (src_data.data_in + (src_data.input_frames_used * channels)),
174 leftover_frames * channels * sizeof(float));
178 nframes_t frames_written = piped_to->write (data_out, frames_out);
179 if (frames_written < 0) {
180 return frames_written;
182 frames_out_total += frames_written;
185 } while (leftover_frames > frames_in);
188 return frames_out_total;
191 /* SampleFormatConverter */
193 template <typename TOut>
194 SampleFormatConverter<TOut>::SampleFormatConverter (uint32_t channels, ExportFormatBase::DitherType type, int data_width_) :
196 data_width (data_width_),
202 if (data_width != 24) {
203 data_width = sizeof (TOut) * 8;
206 GDitherSize dither_size = GDitherFloat;
208 switch (data_width) {
210 dither_size = GDither8bit;
214 dither_size = GDither16bit;
217 dither_size = GDither32bit;
220 dither = gdither_new ((GDitherType) type, channels, dither_size, data_width);
223 template <typename TOut>
224 SampleFormatConverter<TOut>::~SampleFormatConverter ()
227 gdither_free (dither);
234 template <typename TOut>
236 SampleFormatConverter<TOut>::process (float * data, nframes_t frames)
238 /* Make sure we have enough memory allocated */
240 size_t data_size = channels * frames * sizeof (TOut);
241 if (data_size > data_out_size) {
243 data_out = new TOut[data_size];
244 data_out_size = data_size;
249 if (data_width < 32) {
250 for (uint32_t chn = 0; chn < channels; ++chn) {
251 gdither_runf (dither, chn, frames, data, data_out);
254 for (uint32_t chn = 0; chn < channels; ++chn) {
256 TOut * ob = data_out;
257 const double int_max = (float) INT_MAX;
258 const double int_min = (float) INT_MIN;
261 for (nframes_t x = 0; x < frames; ++x) {
262 i = chn + (x * channels);
264 if (data[i] > 1.0f) {
265 ob[i] = static_cast<TOut> (INT_MAX);
266 } else if (data[i] < -1.0f) {
267 ob[i] = static_cast<TOut> (INT_MIN);
269 if (data[i] >= 0.0f) {
270 ob[i] = lrintf (int_max * data[i]);
272 ob[i] = - lrintf (int_min * data[i]);
281 return GraphSinkVertex<float, TOut>::piped_to->write (data_out, frames);
286 SampleFormatConverter<float>::process (float * data, nframes_t frames)
289 for (nframes_t x = 0; x < frames * channels; ++x) {
290 if (data[x] > 1.0f) {
292 } else if (data[x] < -1.0f) {
298 return piped_to->write (data, frames);
301 template class SampleFormatConverter<short>;
302 template class SampleFormatConverter<int>;
303 template class SampleFormatConverter<float>;
307 Normalizer::Normalizer (uint32_t channels, float target_dB) :
311 target = dB_to_coefficient (target_dB);
313 if (target == 1.0f) {
314 /* do not normalize to precisely 1.0 (0 dBFS), to avoid making it appear
315 that we may have clipped.
317 target -= FLT_EPSILON;
321 Normalizer::~Normalizer ()
327 Normalizer::set_peak (float peak)
329 if (peak == 0.0f || peak == target) {
334 gain = target / peak;
339 Normalizer::process (float * data, nframes_t frames)
342 for (nframes_t i = 0; i < (channels * frames); ++i) {
346 return piped_to->write (data, frames);