2 * Copyright (C) <2015> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
32 #include "audio-resampler.h"
34 /* Contains a collection of all things found in other resamplers:
35 * speex (optimizations), ffmpeg (fixed phase filter, blackman filter),
36 * SRC (linear interpolation, fixed precomputed tables),...
39 * - S16, S32, F32 and F64 formats
40 * - linear interpolation
41 * - cubic interpolation
42 * - sinc based interpolation with kaiser or blackman-nutall windows
43 * - fully configurable kaiser parameters
44 * - dynamic linear or cubic interpolation of filter table, this can
45 * use less memory but more CPU
46 * - full filter table, generated from optionally linear or cubic
47 * interpolation of filter table
48 * - fixed filter table size with nearest neighbour phase, optionally
49 * using a precomputed table
50 * - dynamic samplerate changes
53 typedef void (*ResampleFunc) (GstAudioResampler * resampler, gpointer in[],
54 gsize in_len, gpointer out[], gsize out_len, gsize * consumed);
55 typedef void (*DeinterleaveFunc) (GstAudioResampler * resampler,
56 gpointer * sbuf, gpointer in[], gsize in_frames);
58 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
60 #define TAPS_OVERREAD 16
62 struct _GstAudioResampler
64 GstAudioResamplerMethod method;
65 GstAudioResamplerFlags flags;
66 GstAudioFormat format;
67 GstStructure *options;
75 GstAudioResamplerFilterMode filter_mode;
76 guint filter_threshold;
77 GstAudioResamplerFilterInterpolation filter_interpolation;
87 /* oversampled main filter table */
98 gpointer *cached_phases;
100 gpointer cached_taps_mem;
101 gsize cached_taps_stride;
103 DeinterleaveFunc deinterleave;
104 ResampleFunc resample;
120 GST_DEBUG_CATEGORY_STATIC (audio_resampler_debug);
121 #define GST_CAT_DEFAULT audio_resampler_debug
124 * SECTION:gstaudioresampler
125 * @short_description: Utility structure for resampler information
127 * #GstAudioResampler is a structure which holds the information
128 * required to perform various kinds of resampling filtering.
132 static const gint oversample_qualities[] = {
133 4, 4, 4, 8, 8, 16, 16, 16, 16, 32, 32
139 gdouble downsample_cutoff_factor;
140 gdouble stopband_attenuation;
141 gdouble transition_bandwidth;
144 static const KaiserQualityMap kaiser_qualities[] = {
145 {0.860, 0.96511, 60, 0.7}, /* 8 taps */
146 {0.880, 0.96591, 65, 0.29}, /* 16 taps */
147 {0.910, 0.96923, 70, 0.145}, /* 32 taps */
148 {0.920, 0.97600, 80, 0.105}, /* 48 taps */
149 {0.940, 0.97979, 85, 0.087}, /* 64 taps default quality */
150 {0.940, 0.98085, 95, 0.077}, /* 80 taps */
151 {0.945, 0.99471, 100, 0.068}, /* 96 taps */
152 {0.950, 1.0, 105, 0.055}, /* 128 taps */
153 {0.960, 1.0, 110, 0.045}, /* 160 taps */
154 {0.968, 1.0, 115, 0.039}, /* 192 taps */
155 {0.975, 1.0, 120, 0.0305} /* 256 taps */
162 } BlackmanQualityMap;
164 static const BlackmanQualityMap blackman_qualities[] = {
169 {48, 0.85,}, /* default */
178 #define DEFAULT_RESAMPLER_METHOD GST_AUDIO_RESAMPLER_METHOD_KAISER
179 #define DEFAULT_QUALITY GST_AUDIO_RESAMPLER_QUALITY_DEFAULT
180 #define DEFAULT_OPT_CUBIC_B 1.0
181 #define DEFAULT_OPT_CUBIC_C 0.0
182 #define DEFAULT_OPT_FILTER_MODE GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO
183 #define DEFAULT_OPT_FILTER_MODE_THRESHOLD 1048576
184 #define DEFAULT_OPT_FILTER_INTERPOLATION GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC
185 #define DEFAULT_OPT_FILTER_OVERSAMPLE 8
186 #define DEFAULT_OPT_MAX_PHASE_ERROR 0.1
189 get_opt_double (GstStructure * options, const gchar * name, gdouble def)
192 if (!options || !gst_structure_get_double (options, name, &res))
198 get_opt_int (GstStructure * options, const gchar * name, gint def)
201 if (!options || !gst_structure_get_int (options, name, &res))
207 get_opt_enum (GstStructure * options, const gchar * name, GType type, gint def)
210 if (!options || !gst_structure_get_enum (options, name, type, &res))
216 #define GET_OPT_CUTOFF(options,def) get_opt_double(options, \
217 GST_AUDIO_RESAMPLER_OPT_CUTOFF,def)
218 #define GET_OPT_DOWN_CUTOFF_FACTOR(options,def) get_opt_double(options, \
219 GST_AUDIO_RESAMPLER_OPT_DOWN_CUTOFF_FACTOR, def)
220 #define GET_OPT_STOP_ATTENUATION(options,def) get_opt_double(options, \
221 GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, def)
222 #define GET_OPT_TRANSITION_BANDWIDTH(options,def) get_opt_double(options, \
223 GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, def)
224 #define GET_OPT_CUBIC_B(options) get_opt_double(options, \
225 GST_AUDIO_RESAMPLER_OPT_CUBIC_B, DEFAULT_OPT_CUBIC_B)
226 #define GET_OPT_CUBIC_C(options) get_opt_double(options, \
227 GST_AUDIO_RESAMPLER_OPT_CUBIC_C, DEFAULT_OPT_CUBIC_C)
228 #define GET_OPT_N_TAPS(options,def) get_opt_int(options, \
229 GST_AUDIO_RESAMPLER_OPT_N_TAPS, def)
230 #define GET_OPT_FILTER_MODE(options) get_opt_enum(options, \
231 GST_AUDIO_RESAMPLER_OPT_FILTER_MODE, GST_TYPE_AUDIO_RESAMPLER_FILTER_MODE, \
232 DEFAULT_OPT_FILTER_MODE)
233 #define GET_OPT_FILTER_MODE_THRESHOLD(options) get_opt_int(options, \
234 GST_AUDIO_RESAMPLER_OPT_FILTER_MODE_THRESHOLD, DEFAULT_OPT_FILTER_MODE_THRESHOLD)
235 #define GET_OPT_FILTER_INTERPOLATION(options) get_opt_enum(options, \
236 GST_AUDIO_RESAMPLER_OPT_FILTER_INTERPOLATION, GST_TYPE_AUDIO_RESAMPLER_FILTER_INTERPOLATION, \
237 DEFAULT_OPT_FILTER_INTERPOLATION)
238 #define GET_OPT_FILTER_OVERSAMPLE(options) get_opt_int(options, \
239 GST_AUDIO_RESAMPLER_OPT_FILTER_OVERSAMPLE, DEFAULT_OPT_FILTER_OVERSAMPLE)
240 #define GET_OPT_MAX_PHASE_ERROR(options) get_opt_double(options, \
241 GST_AUDIO_RESAMPLER_OPT_MAX_PHASE_ERROR, DEFAULT_OPT_MAX_PHASE_ERROR)
244 #define bessel dbesi0
246 static inline gdouble
247 get_nearest_tap (gdouble x, gint n_taps)
249 gdouble a = fabs (x), res;;
259 static inline gdouble
260 get_linear_tap (gdouble x, gint n_taps)
262 gdouble res = GST_ROUND_UP_2 (n_taps) / 2 - fabs (x);
266 static inline gdouble
267 get_cubic_tap (gdouble x, gint n_taps, gdouble b, gdouble c)
269 gdouble res, a, a2, a3;
271 a = fabs (x * 4.0) / n_taps;
276 res = ((12.0 - 9.0 * b - 6.0 * c) * a3 +
277 (-18.0 + 12.0 * b + 6.0 * c) * a2 + (6.0 - 2.0 * b)) / 6.0;
279 res = ((-b - 6.0 * c) * a3 +
280 (6.0 * b + 30.0 * c) * a2 +
281 (-12.0 * b - 48.0 * c) * a + (8.0 * b + 24.0 * c)) / 6.0;
288 static inline gdouble
289 get_blackman_nuttall_tap (gdouble x, gint n_taps, gdouble Fc)
294 s = (y == 0.0 ? Fc : sin (y * Fc) / y);
296 w = 2.0 * y / n_taps + G_PI;
297 return s * (0.3635819 - 0.4891775 * cos (w) + 0.1365995 * cos (2 * w) -
298 0.0106411 * cos (3 * w));
301 static inline gdouble
302 get_kaiser_tap (gdouble x, gint n_taps, gdouble Fc, gdouble beta)
307 s = (y == 0.0 ? Fc : sin (y * Fc) / y);
309 w = 2.0 * x / n_taps;
310 return s * bessel (beta * sqrt (MAX (1 - w * w, 0)));
313 #define PRECISION_S16 15
314 #define PRECISION_S32 31
317 make_taps (GstAudioResampler * resampler,
318 gdouble * tmp_taps, gdouble x, gint n_taps, gint oversample)
320 gdouble weight = 0.0;
323 switch (resampler->method) {
324 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
325 for (i = 0; i < n_taps; i++)
326 weight += tmp_taps[i] = get_nearest_tap (x + i, resampler->n_taps);
329 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
330 for (i = 0; i < n_taps; i++)
331 weight += tmp_taps[i] = get_linear_tap (x + i, resampler->n_taps);
334 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
335 for (i = 0; i < n_taps; i++)
336 weight += tmp_taps[i] = get_cubic_tap (x + i, resampler->n_taps,
337 resampler->b, resampler->c);
340 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
341 for (i = 0; i < n_taps; i++)
342 weight += tmp_taps[i] =
343 get_blackman_nuttall_tap (x + i / (double) oversample,
344 resampler->n_taps, resampler->cutoff);
347 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
348 for (i = 0; i < n_taps; i++)
349 weight += tmp_taps[i] =
350 get_kaiser_tap (x + i / (double) oversample, resampler->n_taps,
351 resampler->cutoff, resampler->kaiser_beta);
360 #define MAKE_CONVERT_TAPS_INT_FUNC(type, precision) \
362 convert_taps_##type (gdouble *tmp_taps, type *taps, \
363 gdouble weight, gint n_taps) \
365 gint64 one = (1LL << precision) - 1; \
366 gdouble multiplier = one; \
368 gdouble offset, l_offset, h_offset; \
369 gboolean exact = FALSE; \
370 /* Round to integer, but with an adjustable bias that we use to */ \
371 /* eliminate the DC error. */ \
375 for (i = 0; i < 32; i++) { \
377 for (j = 0; j < n_taps; j++) \
378 sum += floor (offset + tmp_taps[j] * multiplier / weight); \
383 if (l_offset == h_offset) \
386 if (offset > l_offset) \
388 offset += (h_offset - l_offset) / 2; \
390 if (offset < h_offset) \
392 offset -= (h_offset - l_offset) / 2; \
395 for (j = 0; j < n_taps; j++) \
396 taps[j] = floor (offset + tmp_taps[j] * multiplier / weight); \
398 GST_WARNING ("can't find exact taps"); \
401 #define MAKE_CONVERT_TAPS_FLOAT_FUNC(type) \
403 convert_taps_##type (gdouble *tmp_taps, type *taps, \
404 gdouble weight, gint n_taps) \
407 for (i = 0; i < n_taps; i++) \
408 taps[i] = tmp_taps[i] / weight; \
411 MAKE_CONVERT_TAPS_INT_FUNC (gint16, PRECISION_S16);
412 MAKE_CONVERT_TAPS_INT_FUNC (gint32, PRECISION_S32);
413 MAKE_CONVERT_TAPS_FLOAT_FUNC (gfloat);
414 MAKE_CONVERT_TAPS_FLOAT_FUNC (gdouble);
416 #define MAKE_EXTRACT_TAPS_FUNC(type) \
418 extract_taps_##type (GstAudioResampler * resampler, type *tmp_taps, \
419 gint n_taps, gint oversample, gint mult) \
421 gint i, j, k, o = oversample - 1; \
422 for (i = 0; i < oversample; i++, o--) { \
423 type *taps = (type *) ((gint8*)resampler->taps + \
424 o * resampler->taps_stride); \
425 for (j = 0; j < n_taps; j++) { \
426 for (k = 0; k < mult; k++) { \
427 *taps++ = tmp_taps[i + j*oversample + k]; \
432 MAKE_EXTRACT_TAPS_FUNC (gint16);
433 MAKE_EXTRACT_TAPS_FUNC (gint32);
434 MAKE_EXTRACT_TAPS_FUNC (gfloat);
435 MAKE_EXTRACT_TAPS_FUNC (gdouble);
437 typedef void (*InterpolateFunc) (gdouble * o, const gdouble * a, gint len,
438 const gdouble * icoeff);
441 interpolate_gdouble_linear_c (gdouble * o, const gdouble * a, gint len,
446 for (i = 0; i < len; i++)
447 o[i] = (a[2 * i + 0] - a[2 * i + 1]) * ic[0] + a[2 * i + 1];
451 interpolate_gdouble_cubic_c (gdouble * o, const gdouble * a, gint len,
456 for (i = 0; i < len; i++)
458 a[4 * i + 0] * ic[0] + a[4 * i + 1] * ic[1] + a[4 * i + 2] * ic[2] +
459 a[4 * i + 3] * ic[3];
462 static InterpolateFunc interpolate_funcs[] = {
463 interpolate_gdouble_linear_c,
464 interpolate_gdouble_cubic_c
467 #define interpolate_gdouble_linear interpolate_funcs[0]
468 #define interpolate_gdouble_cubic interpolate_funcs[1]
470 #define MAKE_COEFF_LINEAR_INT_FUNC(type,type2,prec) \
472 make_coeff_##type##_linear (gint frac, gint out_rate, type *icoeff) \
474 type x = ((gint64)frac << prec) / out_rate; \
475 icoeff[0] = icoeff[2] = x; \
476 icoeff[1] = icoeff[3] = (type)(((type2)1 << prec)-1) - x; \
478 #define MAKE_COEFF_LINEAR_FLOAT_FUNC(type) \
480 make_coeff_##type##_linear (gint frac, gint out_rate, type *icoeff) \
482 type x = (type)frac / out_rate; \
483 icoeff[0] = icoeff[2] = x; \
484 icoeff[1] = icoeff[3] = (type)1.0 - x; \
486 MAKE_COEFF_LINEAR_INT_FUNC (gint16, gint32, PRECISION_S16);
487 MAKE_COEFF_LINEAR_INT_FUNC (gint32, gint64, PRECISION_S32);
488 MAKE_COEFF_LINEAR_FLOAT_FUNC (gfloat);
489 MAKE_COEFF_LINEAR_FLOAT_FUNC (gdouble);
491 #define MAKE_COEFF_CUBIC_INT_FUNC(type,type2,prec) \
493 make_coeff_##type##_cubic (gint frac, gint out_rate, type *icoeff) \
495 type2 one = ((type2)1 << prec) - 1; \
496 type2 x = ((gint64) frac << prec) / out_rate; \
497 type2 x2 = (x * x) >> prec; \
498 type2 x3 = (x2 * x) >> prec; \
499 icoeff[0] = (((x3 - x) << prec) / 6) >> prec; \
500 icoeff[1] = x + ((x2 - x3) >> 1); \
501 icoeff[3] = -(((x << prec) / 3) >> prec) + \
502 (x2 >> 1) - (((x3 << prec) / 6) >> prec); \
503 icoeff[2] = one - icoeff[0] - icoeff[1] - icoeff[3]; \
505 #define MAKE_COEFF_CUBIC_FLOAT_FUNC(type) \
507 make_coeff_##type##_cubic (gint frac, gint out_rate, type *icoeff) \
509 type x = (type) frac / out_rate, x2 = x * x, x3 = x2 * x; \
510 icoeff[0] = 0.16667f * (x3 - x); \
511 icoeff[1] = x + 0.5f * (x2 - x3); \
512 icoeff[3] = -0.33333f * x + 0.5f * x2 - 0.16667f * x3; \
513 icoeff[2] = (type)1.0 - icoeff[0] - icoeff[1] - icoeff[3]; \
515 MAKE_COEFF_CUBIC_INT_FUNC (gint16, gint32, PRECISION_S16);
516 MAKE_COEFF_CUBIC_INT_FUNC (gint32, gint64, PRECISION_S32);
517 MAKE_COEFF_CUBIC_FLOAT_FUNC (gfloat);
518 MAKE_COEFF_CUBIC_FLOAT_FUNC (gdouble);
521 fill_taps (GstAudioResampler * resampler,
522 gdouble * tmp_taps, gint phase, gint n_phases, gint n_taps)
526 if (resampler->filter_interpolation ==
527 GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
528 gdouble x = 1.0 - n_taps / 2 - (gdouble) phase / n_phases;
529 res = make_taps (resampler, tmp_taps, x, n_taps, 1);
531 gint offset, pos, frac;
532 gint oversample = resampler->oversample;
533 gint taps_stride = resampler->taps_stride;
534 gdouble ic[4], *taps;
536 pos = phase * oversample;
537 offset = pos / n_phases;
538 frac = pos % n_phases;
540 taps = (gdouble *) ((gint8 *) resampler->taps + offset * taps_stride);
542 switch (resampler->filter_interpolation) {
543 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
544 make_coeff_gdouble_linear (frac, n_phases, ic);
545 interpolate_gdouble_linear (tmp_taps, taps, n_taps, ic);
547 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:
548 make_coeff_gdouble_cubic (frac, n_phases, ic);
549 interpolate_gdouble_cubic (tmp_taps, taps, n_taps, ic);
559 #define GET_TAPS_NONE_FUNC(type) \
560 static inline gpointer \
561 get_taps_##type##_none (GstAudioResampler * resampler, \
562 gint *samp_index, gint *samp_phase, type icoeff[4]) \
565 gint out_rate = resampler->out_rate; \
566 gint n_phases = resampler->n_phases; \
567 gint phase = (n_phases == out_rate ? *samp_phase : \
568 ((gint64)*samp_phase * n_phases) / out_rate); \
570 res = resampler->cached_phases[phase]; \
571 if (G_UNLIKELY (res == NULL)) { \
573 gdouble *tmp_taps = resampler->tmp_taps; \
574 gint n_taps = resampler->n_taps; \
576 res = (gint8 *) resampler->cached_taps + \
577 phase * resampler->cached_taps_stride; \
579 weight = fill_taps (resampler, tmp_taps, phase, n_phases, n_taps); \
580 convert_taps_##type (tmp_taps, res, weight, n_taps); \
582 resampler->cached_phases[phase] = res; \
584 *samp_index += resampler->samp_inc; \
585 *samp_phase += resampler->samp_frac; \
586 if (*samp_phase >= out_rate) { \
587 *samp_phase -= out_rate; \
592 GET_TAPS_NONE_FUNC (gint16);
593 GET_TAPS_NONE_FUNC (gint32);
594 GET_TAPS_NONE_FUNC (gfloat);
595 GET_TAPS_NONE_FUNC (gdouble);
597 #define GET_TAPS_INTERPOLATE_FUNC(type,inter) \
598 static inline gpointer \
599 get_taps_##type##_##inter (GstAudioResampler * resampler, \
600 gint *samp_index, gint *samp_phase, type icoeff[4]) \
603 gint out_rate = resampler->out_rate; \
604 gint offset, frac, pos; \
605 gint oversample = resampler->oversample; \
606 gint taps_stride = resampler->taps_stride; \
608 pos = *samp_phase * oversample; \
609 offset = pos / out_rate; \
610 frac = pos % out_rate; \
612 res = (gint8 *) resampler->taps + offset * taps_stride; \
613 make_coeff_##type##_##inter (frac, out_rate, icoeff); \
615 *samp_index += resampler->samp_inc; \
616 *samp_phase += resampler->samp_frac; \
617 if (*samp_phase >= out_rate) { \
618 *samp_phase -= out_rate; \
624 GET_TAPS_INTERPOLATE_FUNC (gint16, linear);
625 GET_TAPS_INTERPOLATE_FUNC (gint32, linear);
626 GET_TAPS_INTERPOLATE_FUNC (gfloat, linear);
627 GET_TAPS_INTERPOLATE_FUNC (gdouble, linear);
629 GET_TAPS_INTERPOLATE_FUNC (gint16, cubic);
630 GET_TAPS_INTERPOLATE_FUNC (gint32, cubic);
631 GET_TAPS_INTERPOLATE_FUNC (gfloat, cubic);
632 GET_TAPS_INTERPOLATE_FUNC (gdouble, cubic);
634 #define INNER_PRODUCT_INT_NONE_FUNC(type,type2,prec,limit) \
636 inner_product_##type##_none_1_c (type * o, const type * a, \
637 const type * b, gint len, const type *ic) \
640 type2 res[4] = { 0, 0, 0, 0 }; \
642 for (i = 0; i < len; i += 4) { \
643 res[0] += (type2) a[i + 0] * (type2) b[i + 0]; \
644 res[1] += (type2) a[i + 1] * (type2) b[i + 1]; \
645 res[2] += (type2) a[i + 2] * (type2) b[i + 2]; \
646 res[3] += (type2) a[i + 3] * (type2) b[i + 3]; \
648 res[0] = res[0] + res[1] + res[2] + res[3]; \
649 res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec); \
650 *o = CLAMP (res[0], -(limit), (limit) - 1); \
653 INNER_PRODUCT_INT_NONE_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
654 INNER_PRODUCT_INT_NONE_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
656 #define INNER_PRODUCT_INT_LINEAR_FUNC(type,type2,prec,limit) \
658 inner_product_##type##_linear_1_c (type * o, const type * a, \
659 const type * b, gint len, const type *ic) \
662 type2 res[4] = { 0, 0, 0, 0 }; \
664 for (i = 0; i < len; i += 2) { \
665 res[0] += (type2) a[i + 0] * (type2) b[2 * i + 0]; \
666 res[1] += (type2) a[i + 0] * (type2) b[2 * i + 1]; \
667 res[2] += (type2) a[i + 1] * (type2) b[2 * i + 2]; \
668 res[3] += (type2) a[i + 1] * (type2) b[2 * i + 3]; \
670 res[0] = (res[0] + res[2]) >> (prec); \
671 res[1] = (res[1] + res[3]) >> (prec); \
672 res[0] = (type2)(type)res[0] * (type2) ic[0] + \
673 (type2)(type)res[1] * (type2) ic[1]; \
674 res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec); \
675 *o = CLAMP (res[0], -(limit), (limit) - 1); \
678 INNER_PRODUCT_INT_LINEAR_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
679 INNER_PRODUCT_INT_LINEAR_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
681 #define INNER_PRODUCT_INT_CUBIC_FUNC(type,type2,prec,limit) \
683 inner_product_##type##_cubic_1_c (type * o, const type * a, \
684 const type * b, gint len, const type *ic) \
687 type2 res[4] = { 0, 0, 0, 0 }; \
689 for (i = 0; i < len; i++) { \
690 res[0] += (type2) a[i] * (type2) b[4 * i + 0]; \
691 res[1] += (type2) a[i] * (type2) b[4 * i + 1]; \
692 res[2] += (type2) a[i] * (type2) b[4 * i + 2]; \
693 res[3] += (type2) a[i] * (type2) b[4 * i + 3]; \
695 res[0] = (type2)(type)(res[0] >> (prec)) * (type2) ic[0] + \
696 (type2)(type)(res[1] >> (prec)) * (type2) ic[1] + \
697 (type2)(type)(res[2] >> (prec)) * (type2) ic[2] + \
698 (type2)(type)(res[3] >> (prec)) * (type2) ic[3]; \
699 res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec); \
700 *o = CLAMP (res[0], -(limit), (limit) - 1); \
703 INNER_PRODUCT_INT_CUBIC_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
704 INNER_PRODUCT_INT_CUBIC_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
706 #define INNER_PRODUCT_FLOAT_NONE_FUNC(type) \
708 inner_product_##type##_none_1_c (type * o, const type * a, \
709 const type * b, gint len, const type *ic) \
712 type res[4] = { 0.0, 0.0, 0.0, 0.0 }; \
714 for (i = 0; i < len; i += 4) { \
715 res[0] += a[i + 0] * b[i + 0]; \
716 res[1] += a[i + 1] * b[i + 1]; \
717 res[2] += a[i + 2] * b[i + 2]; \
718 res[3] += a[i + 3] * b[i + 3]; \
720 *o = res[0] + res[1] + res[2] + res[3]; \
723 INNER_PRODUCT_FLOAT_NONE_FUNC (gfloat);
724 INNER_PRODUCT_FLOAT_NONE_FUNC (gdouble);
726 #define INNER_PRODUCT_FLOAT_LINEAR_FUNC(type) \
728 inner_product_##type##_linear_1_c (type * o, const type * a, \
729 const type * b, gint len, const type *ic) \
732 type res[4] = { 0.0, 0.0, 0.0, 0.0 }; \
734 for (i = 0; i < len; i += 2) { \
735 res[0] += a[i] * b[2 * i + 0]; \
736 res[1] += a[i] * b[2 * i + 1]; \
737 res[2] += a[i] * b[2 * i + 2]; \
738 res[3] += a[i] * b[2 * i + 3]; \
740 *o = (res[0] + res[2]) * ic[0] + \
741 (res[1] + res[3]) * ic[1]; \
743 INNER_PRODUCT_FLOAT_LINEAR_FUNC (gfloat);
744 INNER_PRODUCT_FLOAT_LINEAR_FUNC (gdouble);
746 #define INNER_PRODUCT_FLOAT_CUBIC_FUNC(type) \
748 inner_product_##type##_cubic_1_c (type * o, const type * a, \
749 const type * b, gint len, const type *ic) \
752 type res[4] = { 0.0, 0.0, 0.0, 0.0 }; \
754 for (i = 0; i < len; i++) { \
755 res[0] += a[i] * b[4 * i + 0]; \
756 res[1] += a[i] * b[4 * i + 1]; \
757 res[2] += a[i] * b[4 * i + 2]; \
758 res[3] += a[i] * b[4 * i + 3]; \
760 *o = res[0] * ic[0] + res[1] * ic[1] + \
761 res[2] * ic[2] + res[3] * ic[3]; \
763 INNER_PRODUCT_FLOAT_CUBIC_FUNC (gfloat);
764 INNER_PRODUCT_FLOAT_CUBIC_FUNC (gdouble);
766 #define MAKE_RESAMPLE_FUNC(type,inter,channels,arch) \
768 resample_ ##type## _ ##inter## _ ##channels## _ ##arch (GstAudioResampler * resampler, \
769 gpointer in[], gsize in_len, gpointer out[], gsize out_len, \
773 gint n_taps = resampler->n_taps; \
774 gint blocks = resampler->blocks; \
775 gint ostride = resampler->ostride; \
776 gint samp_index = 0; \
777 gint samp_phase = 0; \
779 for (c = 0; c < blocks; c++) { \
781 type *op = ostride == 1 ? out[c] : (type *)out[0] + c; \
783 samp_index = resampler->samp_index; \
784 samp_phase = resampler->samp_phase; \
786 for (di = 0; di < out_len; di++) { \
787 type *ipp, icoeff[4], *taps; \
789 ipp = &ip[samp_index * channels]; \
791 taps = get_taps_ ##type##_##inter \
792 (resampler, &samp_index, &samp_phase, icoeff); \
793 inner_product_ ##type##_##inter##_##channels##_##arch \
794 (op, ipp, taps, n_taps, icoeff); \
797 if (in_len > samp_index) \
798 memmove (ip, &ip[samp_index * channels], \
799 (in_len - samp_index) * sizeof(type) * channels); \
801 *consumed = samp_index - resampler->samp_index; \
803 resampler->samp_index = 0; \
804 resampler->samp_phase = samp_phase; \
807 MAKE_RESAMPLE_FUNC (gint16, none, 1, c);
808 MAKE_RESAMPLE_FUNC (gint32, none, 1, c);
809 MAKE_RESAMPLE_FUNC (gfloat, none, 1, c);
810 MAKE_RESAMPLE_FUNC (gdouble, none, 1, c);
812 MAKE_RESAMPLE_FUNC (gint16, linear, 1, c);
813 MAKE_RESAMPLE_FUNC (gint32, linear, 1, c);
814 MAKE_RESAMPLE_FUNC (gfloat, linear, 1, c);
815 MAKE_RESAMPLE_FUNC (gdouble, linear, 1, c);
817 MAKE_RESAMPLE_FUNC (gint16, cubic, 1, c);
818 MAKE_RESAMPLE_FUNC (gint32, cubic, 1, c);
819 MAKE_RESAMPLE_FUNC (gfloat, cubic, 1, c);
820 MAKE_RESAMPLE_FUNC (gdouble, cubic, 1, c);
822 static ResampleFunc resample_funcs[] = {
823 resample_gint16_none_1_c,
824 resample_gint32_none_1_c,
825 resample_gfloat_none_1_c,
826 resample_gdouble_none_1_c,
832 resample_gint16_linear_1_c,
833 resample_gint32_linear_1_c,
834 resample_gfloat_linear_1_c,
835 resample_gdouble_linear_1_c,
841 resample_gint16_cubic_1_c,
842 resample_gint32_cubic_1_c,
843 resample_gfloat_cubic_1_c,
844 resample_gdouble_cubic_1_c,
851 #define resample_gint16_none_1 resample_funcs[0]
852 #define resample_gint32_none_1 resample_funcs[1]
853 #define resample_gfloat_none_1 resample_funcs[2]
854 #define resample_gdouble_none_1 resample_funcs[3]
855 #define resample_gint16_none_2 resample_funcs[4]
856 #define resample_gint32_none_2 resample_funcs[5]
857 #define resample_gfloat_none_2 resample_funcs[6]
858 #define resample_gdouble_none_2 resample_funcs[7]
860 #define resample_gint16_linear_1 resample_funcs[8]
861 #define resample_gint32_linear_1 resample_funcs[9]
862 #define resample_gfloat_linear_1 resample_funcs[10]
863 #define resample_gdouble_linear_1 resample_funcs[11]
865 #define resample_gint16_cubic_1 resample_funcs[16]
866 #define resample_gint32_cubic_1 resample_funcs[17]
867 #define resample_gfloat_cubic_1 resample_funcs[18]
868 #define resample_gdouble_cubic_1 resample_funcs[19]
870 #if defined HAVE_ORC && !defined DISABLE_ORC
871 # if defined (__ARM_NEON__)
873 # include "audio-resampler-neon.h"
875 # if defined (__i386__) || defined (__x86_64__)
877 # include "audio-resampler-x86.h"
882 audio_resampler_init (void)
884 static gsize init_gonce = 0;
886 if (g_once_init_enter (&init_gonce)) {
888 GST_DEBUG_CATEGORY_INIT (audio_resampler_debug, "audio-resampler", 0,
889 "audio-resampler object");
891 #if defined HAVE_ORC && !defined DISABLE_ORC
894 OrcTarget *target = orc_target_get_default ();
898 unsigned int flags = orc_target_get_default_flags (target);
899 const gchar *tname, *name;
901 tname = orc_target_get_name (target);
902 GST_DEBUG ("target %s, default flags %08x", tname, flags);
904 for (i = 0; i < 32; ++i) {
905 if (flags & (1U << i)) {
906 name = orc_target_get_flag_name (target, i);
907 GST_DEBUG ("target flag %s", name);
909 audio_resampler_check_x86 (tname, name);
912 audio_resampler_check_neon (tname, name);
919 g_once_init_leave (&init_gonce, 1);
923 #define MAKE_DEINTERLEAVE_FUNC(type) \
925 deinterleave_ ##type (GstAudioResampler * resampler, gpointer sbuf[], \
926 gpointer in[], gsize in_frames) \
928 gint i, c, channels = resampler->channels; \
929 gsize samples_avail = resampler->samples_avail; \
930 for (c = 0; c < channels; c++) { \
931 type *s = (type *) sbuf[c] + samples_avail; \
932 if (G_UNLIKELY (in == NULL)) { \
933 for (i = 0; i < in_frames; i++) \
936 type *ip = (type *) in[0] + c; \
937 for (i = 0; i < in_frames; i++, ip += channels) \
943 MAKE_DEINTERLEAVE_FUNC (gint16);
944 MAKE_DEINTERLEAVE_FUNC (gint32);
945 MAKE_DEINTERLEAVE_FUNC (gfloat);
946 MAKE_DEINTERLEAVE_FUNC (gdouble);
948 static DeinterleaveFunc deinterleave_funcs[] = {
956 deinterleave_copy (GstAudioResampler * resampler, gpointer sbuf[],
957 gpointer in[], gsize in_frames)
959 gint c, blocks = resampler->blocks;
960 gsize bytes_avail, in_bytes, bpf;
962 bpf = resampler->bps * resampler->inc;
963 bytes_avail = resampler->samples_avail * bpf;
964 in_bytes = in_frames * bpf;
966 for (c = 0; c < blocks; c++) {
967 if (G_UNLIKELY (in == NULL))
968 memset ((gint8 *) sbuf[c] + bytes_avail, 0, in_bytes);
970 memcpy ((gint8 *) sbuf[c] + bytes_avail, in[c], in_bytes);
975 calculate_kaiser_params (GstAudioResampler * resampler)
977 gdouble A, B, dw, tr_bw, Fc;
979 const KaiserQualityMap *q = &kaiser_qualities[DEFAULT_QUALITY];
983 if (resampler->out_rate < resampler->in_rate)
984 Fc *= q->downsample_cutoff_factor;
986 Fc = GET_OPT_CUTOFF (resampler->options, Fc);
987 A = GET_OPT_STOP_ATTENUATION (resampler->options, q->stopband_attenuation);
989 GET_OPT_TRANSITION_BANDWIDTH (resampler->options,
990 q->transition_bandwidth);
992 GST_LOG ("Fc %f, A %f, tr_bw %f", Fc, A, tr_bw);
996 B = 0.1102 * (A - 8.7);
998 B = 0.5842 * pow (A - 21, 0.4) + 0.07886 * (A - 21);
1001 /* calculate transition width in radians */
1002 dw = 2 * G_PI * (tr_bw);
1003 /* order of the filter */
1004 n = (A - 8.0) / (2.285 * dw);
1006 resampler->kaiser_beta = B;
1007 resampler->n_taps = n + 1;
1008 resampler->cutoff = Fc;
1010 GST_LOG ("using Beta %f n_taps %d cutoff %f", resampler->kaiser_beta,
1011 resampler->n_taps, resampler->cutoff);
1015 alloc_taps_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
1016 gint n_phases, gint n_mult)
1018 if (resampler->alloc_taps >= n_taps && resampler->alloc_phases >= n_phases)
1021 GST_DEBUG ("allocate n_taps %d n_phases %d n_mult %d", n_taps, n_phases,
1024 resampler->tmp_taps =
1025 g_realloc_n (resampler->tmp_taps, n_taps, sizeof (gdouble));
1027 resampler->taps_stride =
1028 GST_ROUND_UP_32 (bps * (n_mult * n_taps + TAPS_OVERREAD));
1030 g_free (resampler->taps_mem);
1031 resampler->taps_mem =
1032 g_malloc0 (n_phases * resampler->taps_stride + ALIGN - 1);
1033 resampler->taps = MEM_ALIGN ((gint8 *) resampler->taps_mem, ALIGN);
1034 resampler->alloc_taps = n_taps;
1035 resampler->alloc_phases = n_phases;
1039 alloc_cache_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
1044 resampler->tmp_taps =
1045 g_realloc_n (resampler->tmp_taps, n_taps, sizeof (gdouble));
1047 resampler->cached_taps_stride =
1048 GST_ROUND_UP_32 (bps * (n_taps + TAPS_OVERREAD));
1050 phases_size = sizeof (gpointer) * n_phases;
1052 g_free (resampler->cached_taps_mem);
1053 resampler->cached_taps_mem =
1054 g_malloc0 (phases_size + n_phases * resampler->cached_taps_stride +
1056 resampler->cached_taps =
1057 MEM_ALIGN ((gint8 *) resampler->cached_taps_mem + phases_size, ALIGN);
1058 resampler->cached_phases = resampler->cached_taps_mem;
1062 setup_functions (GstAudioResampler * resampler)
1064 gboolean non_interleaved;
1066 DeinterleaveFunc deinterleave;
1067 ResampleFunc resample, resample_2;
1069 n_taps = resampler->n_taps;
1071 (resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED);
1073 resampler->ostride = non_interleaved ? 1 : resampler->channels;
1075 switch (resampler->format) {
1076 case GST_AUDIO_FORMAT_S16:
1077 GST_DEBUG ("using S16 functions");
1080 case GST_AUDIO_FORMAT_S32:
1081 GST_DEBUG ("using S32 functions");
1084 case GST_AUDIO_FORMAT_F32:
1085 GST_DEBUG ("using F32 functions");
1088 case GST_AUDIO_FORMAT_F64:
1089 GST_DEBUG ("using F64 functions");
1093 g_assert_not_reached ();
1096 deinterleave = deinterleave_funcs[index];
1098 switch (resampler->filter_mode) {
1100 case GST_AUDIO_RESAMPLER_FILTER_MODE_FULL:
1101 GST_DEBUG ("using full filter function");
1103 case GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED:
1104 switch (resampler->filter_interpolation) {
1105 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1106 GST_DEBUG ("using linear interpolation filter function");
1109 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:
1110 GST_DEBUG ("using cubic interpolation filter function");
1118 resample = resample_funcs[index];
1119 resample_2 = resample_funcs[index + 4];
1121 if (!non_interleaved && resampler->channels == 2 && n_taps >= 4 && resample_2) {
1122 /* we resample 2 channels in parallel */
1123 resampler->resample = resample_2;
1124 resampler->deinterleave = deinterleave_copy;
1125 resampler->blocks = 1;
1126 resampler->inc = resampler->channels;;
1127 GST_DEBUG ("resample 2 channels at a time");
1129 /* we resample each channel separately */
1130 resampler->resample = resample;
1131 resampler->deinterleave = deinterleave;
1132 resampler->blocks = resampler->channels;
1134 GST_DEBUG ("resample 1 channel at a time");
1139 resampler_calculate_taps (GstAudioResampler * resampler)
1142 gint n_taps, oversample;
1143 gint in_rate, out_rate;
1144 gboolean scale = TRUE, sinc_table = FALSE;
1145 GstAudioResamplerFilterInterpolation filter_interpolation;
1147 switch (resampler->method) {
1148 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
1149 resampler->n_taps = 2;
1152 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
1153 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 2);
1155 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
1156 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 4);
1157 resampler->b = GET_OPT_CUBIC_B (resampler->options);
1158 resampler->c = GET_OPT_CUBIC_C (resampler->options);;
1160 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
1162 const BlackmanQualityMap *q = &blackman_qualities[DEFAULT_QUALITY];
1163 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, q->n_taps);
1164 resampler->cutoff = GET_OPT_CUTOFF (resampler->options, q->cutoff);
1168 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
1169 calculate_kaiser_params (resampler);
1174 in_rate = resampler->in_rate;
1175 out_rate = resampler->out_rate;
1177 if (out_rate < in_rate && scale) {
1178 resampler->cutoff = resampler->cutoff * out_rate / in_rate;
1180 gst_util_uint64_scale_int (resampler->n_taps, in_rate, out_rate);
1184 resampler->n_taps = GST_ROUND_UP_8 (resampler->n_taps);
1185 resampler->filter_mode = GET_OPT_FILTER_MODE (resampler->options);
1186 resampler->filter_threshold =
1187 GET_OPT_FILTER_MODE_THRESHOLD (resampler->options);
1188 filter_interpolation = GET_OPT_FILTER_INTERPOLATION (resampler->options);
1190 /* interpolated table but no interpolation given, assume default */
1191 if (resampler->filter_mode != GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
1192 filter_interpolation == GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE)
1193 filter_interpolation = DEFAULT_OPT_FILTER_INTERPOLATION;
1195 resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
1196 filter_interpolation = GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE;
1199 /* calculate oversampling for interpolated filter */
1200 if (filter_interpolation != GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
1203 oversample = GET_OPT_FILTER_OVERSAMPLE (resampler->options);
1204 while (oversample > 1) {
1205 if (mult * out_rate >= in_rate)
1212 switch (filter_interpolation) {
1213 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1222 resampler->oversample = oversample;
1223 resampler->filter_interpolation = filter_interpolation;
1225 n_taps = resampler->n_taps;
1226 bps = resampler->bps;
1228 GST_LOG ("using n_taps %d cutoff %f oversample %d", n_taps, resampler->cutoff,
1231 if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO) {
1232 if (out_rate <= oversample) {
1233 /* don't interpolate if we need to calculate at least the same amount
1234 * of filter coefficients than the full table case */
1235 resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
1236 GST_DEBUG ("automatically selected full filter, %d <= %d", out_rate,
1239 GST_DEBUG ("automatically selected interpolated filter");
1240 resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED;
1244 if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL) {
1245 GST_DEBUG ("setting up filter cache");
1246 resampler->n_phases = out_rate;
1247 alloc_cache_mem (resampler, bps, n_taps, out_rate);
1250 if (resampler->filter_interpolation !=
1251 GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
1253 gdouble x, weight, *tmp_taps;
1254 GstAudioFormat format;
1257 switch (resampler->filter_interpolation) {
1259 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1260 GST_DEBUG ("using linear interpolation to build filter");
1263 case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:
1264 GST_DEBUG ("using cubic interpolation to build filter");
1268 otaps = oversample * n_taps + isize - 1;
1270 if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL) {
1271 format = GST_AUDIO_FORMAT_F64;
1272 bps = sizeof (gdouble);
1274 format = resampler->format;
1276 alloc_taps_mem (resampler, bps, otaps, oversample, isize);
1278 taps = tmp_taps = resampler->tmp_taps;
1279 x = 1.0 - n_taps / 2;
1280 weight = make_taps (resampler, tmp_taps, x, otaps, oversample);
1283 case GST_AUDIO_FORMAT_S16:
1284 convert_taps_gint16 (tmp_taps, taps, weight / oversample, otaps);
1285 extract_taps_gint16 (resampler, taps, n_taps, oversample, isize);
1287 case GST_AUDIO_FORMAT_S32:
1288 convert_taps_gint32 (tmp_taps, taps, weight / oversample, otaps);
1289 extract_taps_gint32 (resampler, taps, n_taps, oversample, isize);
1291 case GST_AUDIO_FORMAT_F32:
1292 convert_taps_gfloat (tmp_taps, taps, weight / oversample, otaps);
1293 extract_taps_gfloat (resampler, taps, n_taps, oversample, isize);
1296 case GST_AUDIO_FORMAT_F64:
1297 convert_taps_gdouble (tmp_taps, taps, weight / oversample, otaps);
1298 extract_taps_gdouble (resampler, taps, n_taps, oversample, isize);
1302 setup_functions (resampler);
1305 #define PRINT_TAPS(type,print) \
1307 type sum = 0.0, *taps; \
1309 gint samp_index = 0, samp_phase = i; \
1311 taps = get_taps_##type##_none (resampler, &samp_index,\
1312 &samp_phase, icoeff); \
1314 for (j = 0; j < n_taps; j++) { \
1315 type tap = taps[j]; \
1316 fprintf (stderr, "\t%" print " ", tap); \
1319 fprintf (stderr, "\t: sum %" print "\n", sum); \
1323 resampler_dump (GstAudioResampler * resampler)
1326 gint i, n_taps, out_rate;
1329 out_rate = resampler->out_rate;
1330 n_taps = resampler->n_taps;
1332 fprintf (stderr, "out size %d, max taps %d\n", out_rate, n_taps);
1334 a = g_get_monotonic_time ();
1336 for (i = 0; i < out_rate; i++) {
1339 //fprintf (stderr, "%u: %d %d\t ", i, t->sample_inc, t->next_phase);
1340 switch (resampler->format) {
1341 case GST_AUDIO_FORMAT_F64:
1342 PRINT_TAPS (gdouble, "f");
1344 case GST_AUDIO_FORMAT_F32:
1345 PRINT_TAPS (gfloat, "f");
1347 case GST_AUDIO_FORMAT_S32:
1348 PRINT_TAPS (gint32, "d");
1350 case GST_AUDIO_FORMAT_S16:
1351 PRINT_TAPS (gint16, "d");
1357 fprintf (stderr, "time %" G_GUINT64_FORMAT "\n", g_get_monotonic_time () - a);
1362 * gst_audio_resampler_options_set_quality:
1363 * @method: a #GstAudioResamplerMethod
1364 * @quality: the quality
1365 * @in_rate: the input rate
1366 * @out_rate: the output rate
1367 * @options: a #GstStructure
1369 * Set the parameters for resampling from @in_rate to @out_rate using @method
1370 * for @quality in @options.
1373 gst_audio_resampler_options_set_quality (GstAudioResamplerMethod method,
1374 guint quality, gint in_rate, gint out_rate, GstStructure * options)
1376 g_return_if_fail (options != NULL);
1377 g_return_if_fail (quality <= GST_AUDIO_RESAMPLER_QUALITY_MAX);
1378 g_return_if_fail (in_rate > 0 && out_rate > 0);
1381 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
1383 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
1384 gst_structure_set (options,
1385 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 2, NULL);
1387 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
1388 gst_structure_set (options,
1389 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 4,
1390 GST_AUDIO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_B,
1391 GST_AUDIO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_C,
1394 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
1396 const BlackmanQualityMap *map = &blackman_qualities[quality];
1397 gst_structure_set (options,
1398 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, map->n_taps,
1399 GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, map->cutoff, NULL);
1402 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
1404 const KaiserQualityMap *map = &kaiser_qualities[quality];
1407 cutoff = map->cutoff;
1408 if (out_rate < in_rate)
1409 cutoff *= map->downsample_cutoff_factor;
1411 gst_structure_set (options,
1412 GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, cutoff,
1413 GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, G_TYPE_DOUBLE,
1414 map->stopband_attenuation,
1415 GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, G_TYPE_DOUBLE,
1416 map->transition_bandwidth, NULL);
1420 gst_structure_set (options,
1421 GST_AUDIO_RESAMPLER_OPT_FILTER_OVERSAMPLE, G_TYPE_INT,
1422 oversample_qualities[quality], NULL);
1426 * gst_audio_resampler_new:
1427 * @resampler: a #GstAudioResampler
1428 * @method: a #GstAudioResamplerMethod
1429 * @flags: #GstAudioResamplerFlags
1430 * @in_rate: input rate
1431 * @out_rate: output rate
1432 * @options: extra options
1434 * Make a new resampler.
1436 * Returns: %TRUE on success
1439 gst_audio_resampler_new (GstAudioResamplerMethod method,
1440 GstAudioResamplerFlags flags,
1441 GstAudioFormat format, gint channels,
1442 gint in_rate, gint out_rate, GstStructure * options)
1444 GstAudioResampler *resampler;
1445 const GstAudioFormatInfo *info;
1446 GstStructure *def_options = NULL;
1448 g_return_val_if_fail (channels > 0, FALSE);
1449 g_return_val_if_fail (in_rate > 0, FALSE);
1450 g_return_val_if_fail (out_rate > 0, FALSE);
1452 audio_resampler_init ();
1454 resampler = g_slice_new0 (GstAudioResampler);
1455 resampler->method = method;
1456 resampler->flags = flags;
1457 resampler->format = format;
1458 resampler->channels = channels;
1460 info = gst_audio_format_get_info (format);
1461 resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
1462 resampler->sbuf = g_malloc0 (sizeof (gpointer) * channels);
1464 GST_DEBUG ("method %d, bps %d, channels %d", method, resampler->bps,
1465 resampler->channels);
1467 if (options == NULL) {
1468 options = def_options =
1469 gst_structure_new_empty ("GstAudioResampler.options");
1470 gst_audio_resampler_options_set_quality (DEFAULT_RESAMPLER_METHOD,
1471 GST_AUDIO_RESAMPLER_QUALITY_DEFAULT, in_rate, out_rate, options);
1474 gst_audio_resampler_update (resampler, in_rate, out_rate, options);
1476 /* half of the filter is filled with 0 */
1477 resampler->samp_index = 0;
1478 resampler->samples_avail = resampler->n_taps / 2 - 1;
1481 gst_structure_free (def_options);
1486 /* make the buffers to hold the (deinterleaved) samples */
1487 static inline gpointer *
1488 get_sample_bufs (GstAudioResampler * resampler, gsize need)
1490 if (G_LIKELY (resampler->samples_len < need)) {
1491 gint c, blocks = resampler->blocks;
1492 gsize bytes, to_move = 0;
1493 gint8 *ptr, *samples;
1495 GST_LOG ("realloc %d -> %d", (gint) resampler->samples_len, (gint) need);
1497 bytes = GST_ROUND_UP_N (need * resampler->bps * resampler->inc, ALIGN);
1499 samples = g_malloc0 (blocks * bytes + ALIGN - 1);
1500 ptr = MEM_ALIGN (samples, ALIGN);
1502 /* if we had some data, move history */
1503 if (resampler->samples_len > 0)
1504 to_move = resampler->samples_avail * resampler->bps * resampler->inc;
1506 /* set up new pointers */
1507 for (c = 0; c < blocks; c++) {
1508 memcpy (ptr + (c * bytes), resampler->sbuf[c], to_move);
1509 resampler->sbuf[c] = ptr + (c * bytes);
1511 g_free (resampler->samples);
1512 resampler->samples = samples;
1513 resampler->samples_len = need;
1515 return resampler->sbuf;
1519 * gst_audio_resampler_reset:
1520 * @resampler: a #GstAudioResampler
1522 * Reset @resampler to the state it was when it was first created, discarding
1523 * all sample history.
1526 gst_audio_resampler_reset (GstAudioResampler * resampler)
1528 g_return_if_fail (resampler != NULL);
1530 if (resampler->samples) {
1532 gint c, blocks, bpf;
1534 bpf = resampler->bps * resampler->inc;
1535 bytes = (resampler->n_taps / 2) * bpf;
1536 blocks = resampler->blocks;
1538 for (c = 0; c < blocks; c++)
1539 memset (resampler->sbuf[c], 0, bytes);
1541 /* half of the filter is filled with 0 */
1542 resampler->samp_index = 0;
1543 resampler->samples_avail = resampler->n_taps / 2 - 1;
1547 * gst_audio_resampler_update:
1548 * @resampler: a #GstAudioResampler
1549 * @in_rate: new input rate
1550 * @out_rate: new output rate
1551 * @options: new options or %NULL
1553 * Update the resampler parameters for @resampler. This function should
1554 * not be called concurrently with any other function on @resampler.
1556 * When @in_rate or @out_rate is 0, its value is unchanged.
1558 * When @options is %NULL, the previously configured options are reused.
1560 * Returns: %TRUE if the new parameters could be set
1563 gst_audio_resampler_update (GstAudioResampler * resampler,
1564 gint in_rate, gint out_rate, GstStructure * options)
1566 gint gcd, samp_phase, old_n_taps;
1569 g_return_val_if_fail (resampler != NULL, FALSE);
1572 in_rate = resampler->in_rate;
1574 out_rate = resampler->out_rate;
1576 if (resampler->out_rate > 0) {
1577 GST_INFO ("old phase %d/%d", resampler->samp_phase, resampler->out_rate);
1579 gst_util_uint64_scale_int (resampler->samp_phase, out_rate,
1580 resampler->out_rate);
1584 gcd = gst_util_greatest_common_divisor (in_rate, out_rate);
1586 max_error = GET_OPT_MAX_PHASE_ERROR (resampler->options);
1588 if (max_error < 1.0e-8) {
1589 GST_INFO ("using exact phase divider");
1590 gcd = gst_util_greatest_common_divisor (gcd, samp_phase);
1593 gdouble ph1 = (gdouble) samp_phase / out_rate;
1596 /* reduce the factor until we have a phase error of less than 10% */
1597 gdouble ph2 = (gdouble) (samp_phase / gcd) / (out_rate / gcd);
1599 if (fabs (ph1 - ph2) < max_error)
1602 while (gcd % factor != 0)
1606 GST_INFO ("divide by factor %d, gcd %d", factor, gcd);
1610 GST_INFO ("phase %d out_rate %d, in_rate %d, gcd %d", samp_phase, out_rate,
1613 resampler->samp_phase = samp_phase /= gcd;
1614 resampler->in_rate = in_rate /= gcd;
1615 resampler->out_rate = out_rate /= gcd;
1617 GST_INFO ("new phase %d/%d", resampler->samp_phase, resampler->out_rate);
1619 resampler->samp_inc = in_rate / out_rate;
1620 resampler->samp_frac = in_rate % out_rate;
1623 GST_INFO ("have new options, reconfigure filter");
1625 if (resampler->options)
1626 gst_structure_free (resampler->options);
1627 resampler->options = gst_structure_copy (options);
1629 old_n_taps = resampler->n_taps;
1631 resampler_calculate_taps (resampler);
1632 resampler_dump (resampler);
1634 if (old_n_taps > 0 && old_n_taps != resampler->n_taps) {
1636 gint i, bpf, bytes, soff, doff, diff;
1638 sbuf = get_sample_bufs (resampler, resampler->n_taps);
1640 bpf = resampler->bps * resampler->inc;
1641 bytes = resampler->samples_avail * bpf;
1642 soff = doff = resampler->samp_index * bpf;
1644 diff = ((gint) resampler->n_taps - old_n_taps) / 2;
1646 GST_DEBUG ("taps %d->%d, %d", old_n_taps, resampler->n_taps, diff);
1649 /* diff < 0, decrease taps, adjust source */
1650 soff += -diff * bpf;
1651 bytes -= -diff * bpf;
1653 /* diff > 0, increase taps, adjust dest */
1657 /* now shrink or enlarge the history buffer, when we enlarge we
1658 * just leave the old samples in there. FIXME, probably do something better
1659 * like mirror or fill with zeroes. */
1660 for (i = 0; i < resampler->blocks; i++)
1661 memmove ((gint8 *) sbuf[i] + doff, (gint8 *) sbuf[i] + soff, bytes);
1663 resampler->samples_avail += diff;
1665 } else if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL) {
1666 GST_DEBUG ("setting up filter cache");
1667 resampler->n_phases = resampler->out_rate;
1668 alloc_cache_mem (resampler, resampler->bps, resampler->n_taps,
1669 resampler->n_phases);
1675 * gst_audio_resampler_free:
1676 * @resampler: a #GstAudioResampler
1678 * Free a previously allocated #GstAudioResampler @resampler.
1683 gst_audio_resampler_free (GstAudioResampler * resampler)
1685 g_return_if_fail (resampler != NULL);
1687 g_free (resampler->cached_taps_mem);
1688 g_free (resampler->taps_mem);
1689 g_free (resampler->tmp_taps);
1690 g_free (resampler->samples);
1691 g_free (resampler->sbuf);
1692 if (resampler->options)
1693 gst_structure_free (resampler->options);
1694 g_slice_free (GstAudioResampler, resampler);
1698 * gst_audio_resampler_get_out_frames:
1699 * @resampler: a #GstAudioResampler
1700 * @in_frames: number of input frames
1702 * Get the number of output frames that would be currently available when
1703 * @in_frames are given to @resampler.
1705 * Returns: The number of frames that would be availabe after giving
1706 * @in_frames as input to @resampler.
1709 gst_audio_resampler_get_out_frames (GstAudioResampler * resampler,
1712 gsize need, avail, out;
1714 g_return_val_if_fail (resampler != NULL, 0);
1716 need = resampler->n_taps + resampler->samp_index + resampler->skip;
1717 avail = resampler->samples_avail + in_frames;
1718 GST_LOG ("need %d = %d + %d + %d, avail %d = %d + %d", (gint) need,
1719 resampler->n_taps, resampler->samp_index, resampler->skip,
1720 (gint) avail, (gint) resampler->samples_avail, (gint) in_frames);
1724 out = (avail - need) * resampler->out_rate;
1725 if (out < resampler->samp_phase)
1728 out = ((out - resampler->samp_phase) / resampler->in_rate) + 1;
1729 GST_LOG ("out %d = ((%d * %d - %d) / %d) + 1", (gint) out,
1730 (gint) (avail - need), resampler->out_rate, resampler->samp_phase,
1731 resampler->in_rate);
1737 * gst_audio_resampler_get_in_frames:
1738 * @resampler: a #GstAudioResampler
1739 * @out_frames: number of input frames
1741 * Get the number of input frames that would currently be needed
1742 * to produce @out_frames from @resampler.
1744 * Returns: The number of input frames needed for producing
1745 * @out_frames of data from @resampler.
1748 gst_audio_resampler_get_in_frames (GstAudioResampler * resampler,
1753 g_return_val_if_fail (resampler != NULL, 0);
1756 (resampler->samp_phase +
1757 out_frames * resampler->samp_frac) / resampler->out_rate;
1758 in_frames += out_frames * resampler->samp_inc;
1764 * gst_audio_resampler_get_max_latency:
1765 * @resampler: a #GstAudioResampler
1767 * Get the maximum number of input samples that the resampler would
1768 * need before producing output.
1770 * Returns: the latency of @resampler as expressed in the number of
1774 gst_audio_resampler_get_max_latency (GstAudioResampler * resampler)
1776 g_return_val_if_fail (resampler != NULL, 0);
1778 return resampler->n_taps / 2;
1782 * gst_audio_resampler_resample:
1783 * @resampler: a #GstAudioResampler
1784 * @in: input samples
1785 * @in_frames: number of input frames
1786 * @out: output samples
1787 * @out_frames: number of output frames
1789 * Perform resampling on @in_frames frames in @in and write @out_frames to @out.
1791 * In case the samples are interleaved, @in and @out must point to an
1792 * array with a single element pointing to a block of interleaved samples.
1794 * If non-interleaved samples are used, @in and @out must point to an
1795 * array with pointers to memory blocks, one for each channel.
1797 * @in may be %NULL, in which case @in_frames of silence samples are pushed
1798 * into the resampler.
1800 * This function always produces @out_frames of output and consumes @in_frames of
1801 * input. Use gst_audio_resampler_get_out_frames() and
1802 * gst_audio_resampler_get_in_frames() to make sure @in_frames and @out_frames
1803 * are matching and @in and @out point to enough memory.
1806 gst_audio_resampler_resample (GstAudioResampler * resampler,
1807 gpointer in[], gsize in_frames, gpointer out[], gsize out_frames)
1809 gsize samples_avail;
1810 gsize need, consumed;
1813 /* do sample skipping */
1814 if (G_UNLIKELY (resampler->skip >= in_frames)) {
1815 /* we need tp skip all input */
1816 resampler->skip -= in_frames;
1819 /* skip the last samples by advancing the sample index */
1820 resampler->samp_index += resampler->skip;
1822 samples_avail = resampler->samples_avail;
1824 /* make sure we have enough space to copy our samples */
1825 sbuf = get_sample_bufs (resampler, in_frames + samples_avail);
1827 /* copy/deinterleave the samples */
1828 resampler->deinterleave (resampler, sbuf, in, in_frames);
1830 /* update new amount of samples in our buffer */
1831 resampler->samples_avail = samples_avail += in_frames;
1833 need = resampler->n_taps + resampler->samp_index;
1834 if (G_UNLIKELY (samples_avail < need)) {
1835 /* not enough samples to start */
1839 /* resample all channels */
1840 resampler->resample (resampler, sbuf, samples_avail, out, out_frames,
1843 GST_LOG ("in %" G_GSIZE_FORMAT ", avail %" G_GSIZE_FORMAT ", consumed %"
1844 G_GSIZE_FORMAT, in_frames, samples_avail, consumed);
1846 /* update pointers */
1847 if (G_LIKELY (consumed > 0)) {
1848 gssize left = samples_avail - consumed;
1850 /* we consumed part of our samples */
1851 resampler->samples_avail = left;
1853 /* we consumed all our samples, empty our buffers */
1854 resampler->samples_avail = 0;
1855 resampler->skip = -left;