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"
43 typedef void (*MakeTapsFunc) (GstAudioResampler * resampler, Tap * t, gint j);
44 typedef void (*ResampleFunc) (GstAudioResampler * resampler, gpointer in[],
45 gsize in_len, gpointer out[], gsize out_len, gsize * consumed);
46 typedef void (*DeinterleaveFunc) (GstAudioResampler * resampler,
47 gpointer * sbuf, gpointer in[], gsize in_frames);
49 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
51 #define TAPS_OVERREAD 16
53 struct _GstAudioResampler
55 GstAudioResamplerMethod method;
56 GstAudioResamplerFlags flags;
57 GstAudioFormat format;
58 GstStructure *options;
77 DeinterleaveFunc deinterleave;
78 ResampleFunc resample;
94 GST_DEBUG_CATEGORY_STATIC (audio_resampler_debug);
95 #define GST_CAT_DEFAULT audio_resampler_debug
98 * SECTION:gstaudioresampler
99 * @short_description: Utility structure for resampler information
101 * #GstAudioResampler is a structure which holds the information
102 * required to perform various kinds of resampling filtering.
109 gdouble downsample_cutoff_factor;
110 gdouble stopband_attenuation;
111 gdouble transition_bandwidth;
114 static const KaiserQualityMap kaiser_qualities[] = {
115 {0.860, 0.96511, 60, 0.7}, /* 8 taps */
116 {0.880, 0.96591, 65, 0.29}, /* 16 taps */
117 {0.910, 0.96923, 70, 0.145}, /* 32 taps */
118 {0.920, 0.97600, 80, 0.105}, /* 48 taps */
119 {0.940, 0.97979, 85, 0.087}, /* 64 taps default quality */
120 {0.940, 0.98085, 95, 0.077}, /* 80 taps */
121 {0.945, 0.99471, 100, 0.068}, /* 96 taps */
122 {0.950, 1.0, 105, 0.055}, /* 128 taps */
123 {0.960, 1.0, 110, 0.045}, /* 160 taps */
124 {0.968, 1.0, 115, 0.039}, /* 192 taps */
125 {0.975, 1.0, 120, 0.0305} /* 256 taps */
132 } BlackmanQualityMap;
134 static const BlackmanQualityMap blackman_qualities[] = {
139 {48, 0.85,}, /* default */
148 #define DEFAULT_QUALITY GST_AUDIO_RESAMPLER_QUALITY_DEFAULT
149 #define DEFAULT_OPT_CUBIC_B 1.0
150 #define DEFAULT_OPT_CUBIC_C 0.0
153 get_opt_double (GstStructure * options, const gchar * name, gdouble def)
156 if (!options || !gst_structure_get_double (options, name, &res))
162 get_opt_int (GstStructure * options, const gchar * name, gint def)
165 if (!options || !gst_structure_get_int (options, name, &res))
170 #define GET_OPT_CUTOFF(options,def) get_opt_double(options, \
171 GST_AUDIO_RESAMPLER_OPT_CUTOFF,def)
172 #define GET_OPT_DOWN_CUTOFF_FACTOR(options,def) get_opt_double(options, \
173 GST_AUDIO_RESAMPLER_OPT_DOWN_CUTOFF_FACTOR, def)
174 #define GET_OPT_STOP_ATTENUATION(options,def) get_opt_double(options, \
175 GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, def)
176 #define GET_OPT_TRANSITION_BANDWIDTH(options,def) get_opt_double(options, \
177 GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, def)
178 #define GET_OPT_CUBIC_B(options) get_opt_double(options, \
179 GST_AUDIO_RESAMPLER_OPT_CUBIC_B, DEFAULT_OPT_CUBIC_B)
180 #define GET_OPT_CUBIC_C(options) get_opt_double(options, \
181 GST_AUDIO_RESAMPLER_OPT_CUBIC_C, DEFAULT_OPT_CUBIC_C)
182 #define GET_OPT_N_TAPS(options,def) get_opt_int(options, \
183 GST_AUDIO_RESAMPLER_OPT_N_TAPS, def)
186 #define bessel dbesi0
188 static inline gdouble
189 get_nearest_tap (GstAudioResampler * resampler, gdouble x)
191 gdouble a = fabs (x);
199 static inline gdouble
200 get_linear_tap (GstAudioResampler * resampler, gdouble x)
204 a = fabs (x) / resampler->n_taps;
212 static inline gdouble
213 get_cubic_tap (GstAudioResampler * resampler, gdouble x)
215 gdouble a, a2, a3, b, c;
217 a = fabs (x * 4.0) / resampler->n_taps;
225 return ((12.0 - 9.0 * b - 6.0 * c) * a3 +
226 (-18.0 + 12.0 * b + 6.0 * c) * a2 + (6.0 - 2.0 * b)) / 6.0;
228 return ((-b - 6.0 * c) * a3 +
229 (6.0 * b + 30.0 * c) * a2 +
230 (-12.0 * b - 48.0 * c) * a + (8.0 * b + 24.0 * c)) / 6.0;
235 static inline gdouble
236 get_blackman_nuttall_tap (GstAudioResampler * resampler, gdouble x)
238 gdouble s, y, w, Fc = resampler->cutoff;
241 s = (y == 0.0 ? Fc : sin (y * Fc) / y);
243 w = 2.0 * y / resampler->n_taps + G_PI;
244 return s * (0.3635819 - 0.4891775 * cos (w) + 0.1365995 * cos (2 * w) -
245 0.0106411 * cos (3 * w));
248 static inline gdouble
249 get_kaiser_tap (GstAudioResampler * resampler, gdouble x)
251 gdouble s, y, w, Fc = resampler->cutoff;
254 s = (y == 0.0 ? Fc : sin (y * Fc) / y);
256 w = 2.0 * x / resampler->n_taps;
257 return s * bessel (resampler->kaiser_beta * sqrt (MAX (1 - w * w, 0)));
260 #define CONVERT_TAPS(type, precision) \
262 type *taps = res = (type *) ((gint8*)resampler->coeff + j * resampler->cstride); \
263 gdouble multiplier = (1 << precision); \
265 gdouble offset, l_offset, h_offset; \
266 gboolean exact = FALSE; \
267 /* Round to integer, but with an adjustable bias that we use to */ \
268 /* eliminate the DC error. */ \
272 for (i = 0; i < 32; i++) { \
274 for (j = 0; j < n_taps; j++) \
275 sum += taps[j] = floor (offset + tmpcoeff[j] * multiplier / weight); \
276 if (sum == (1 << precision)) { \
280 if (l_offset == h_offset) \
282 if (sum < (1 << precision)) { \
283 if (offset > l_offset) \
285 offset += (h_offset - l_offset) / 2; \
287 if (offset < h_offset) \
289 offset -= (h_offset - l_offset) / 2; \
293 GST_WARNING ("can't find exact taps"); \
296 #define PRECISION_S16 15
297 #define PRECISION_S32 30
300 make_taps (GstAudioResampler * resampler, Tap * t, gint j)
303 gint n_taps = resampler->n_taps;
304 gdouble x, weight = 0.0;
305 gdouble *tmpcoeff = resampler->tmpcoeff;
306 gint tap_offs = n_taps / 2;
307 gint in_rate = resampler->in_rate;
308 gint out_rate = resampler->out_rate;
311 x = ((double) (1.0 - tap_offs) - (double) j / out_rate);
313 switch (resampler->method) {
314 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
315 for (l = 0; l < n_taps; l++, x += 1.0)
316 weight += tmpcoeff[l] = get_nearest_tap (resampler, x);
319 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
320 for (l = 0; l < n_taps; l++, x += 1.0)
321 weight += tmpcoeff[l] = get_linear_tap (resampler, x);
324 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
325 for (l = 0; l < n_taps; l++, x += 1.0)
326 weight += tmpcoeff[l] = get_cubic_tap (resampler, x);
329 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
330 for (l = 0; l < n_taps; l++, x += 1.0)
331 weight += tmpcoeff[l] = get_blackman_nuttall_tap (resampler, x);
334 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
335 for (l = 0; l < n_taps; l++, x += 1.0)
336 weight += tmpcoeff[l] = get_kaiser_tap (resampler, x);
343 switch (resampler->format) {
344 case GST_AUDIO_FORMAT_F64:
346 gdouble *taps = res =
347 (gdouble *) ((gint8 *) resampler->coeff + j * resampler->cstride);
348 for (l = 0; l < n_taps; l++)
349 taps[l] = tmpcoeff[l] / weight;
352 case GST_AUDIO_FORMAT_F32:
355 (gfloat *) ((gint8 *) resampler->coeff + j * resampler->cstride);
356 for (l = 0; l < n_taps; l++)
357 taps[l] = tmpcoeff[l] / weight;
360 case GST_AUDIO_FORMAT_S32:
361 CONVERT_TAPS (gint32, PRECISION_S32);
363 case GST_AUDIO_FORMAT_S16:
364 CONVERT_TAPS (gint16, PRECISION_S16);
367 g_assert_not_reached ();
372 t->sample_inc = (j + in_rate) / out_rate;
373 t->next_phase = (j + in_rate) % out_rate;
379 inner_product_gint16_1_c (gint16 * o, const gint16 * a, const gint16 * b,
385 for (i = 0; i < len; i++)
386 res += (gint32) a[i] * (gint32) b[i];
388 res = (res + (1 << (PRECISION_S16 - 1))) >> PRECISION_S16;
389 *o = CLAMP (res, -(1L << 15), (1L << 15) - 1);
393 inner_product_gint32_1_c (gint32 * o, const gint32 * a, const gint32 * b,
399 for (i = 0; i < len; i++)
400 res += (gint64) a[i] * (gint64) b[i];
402 res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
403 *o = CLAMP (res, -(1L << 31), (1L << 31) - 1);
407 inner_product_gfloat_1_c (gfloat * o, const gfloat * a, const gfloat * b,
413 for (i = 0; i < len; i++)
420 inner_product_gdouble_1_c (gdouble * o, const gdouble * a, const gdouble * b,
426 for (i = 0; i < len; i++)
432 #define MAKE_RESAMPLE_FUNC(type,channels,arch) \
434 resample_ ##type## _ ##channels## _ ##arch (GstAudioResampler * resampler, \
435 gpointer in[], gsize in_len, gpointer out[], gsize out_len, \
439 gint n_taps = resampler->n_taps; \
440 gint blocks = resampler->blocks; \
441 gint ostride = resampler->ostride; \
442 gint samp_index = 0; \
443 gint samp_phase = 0; \
445 for (c = 0; c < blocks; c++) { \
447 type *op = ostride == 1 ? out[c] : (type *)out[0] + c; \
449 samp_index = resampler->samp_index; \
450 samp_phase = resampler->samp_phase; \
452 for (di = 0; di < out_len; di++) { \
453 Tap *t = &resampler->taps[samp_phase]; \
454 type *ipp = &ip[samp_index * channels]; \
457 if (G_UNLIKELY ((taps = t->taps) == NULL)) \
458 taps = make_taps (resampler, t, samp_phase); \
460 inner_product_ ##type## _##channels##_##arch (op, ipp, taps, n_taps); \
463 samp_phase = t->next_phase; \
464 samp_index += t->sample_inc; \
466 memmove (ip, &ip[samp_index * channels], \
467 (in_len - samp_index) * sizeof(type) * channels); \
469 *consumed = samp_index - resampler->samp_index; \
471 resampler->samp_index = 0; \
472 resampler->samp_phase = samp_phase; \
475 MAKE_RESAMPLE_FUNC (gint16, 1, c);
476 MAKE_RESAMPLE_FUNC (gint32, 1, c);
477 MAKE_RESAMPLE_FUNC (gfloat, 1, c);
478 MAKE_RESAMPLE_FUNC (gdouble, 1, c);
480 static ResampleFunc resample_funcs[] = {
484 resample_gdouble_1_c,
491 #define resample_gint16_1 resample_funcs[0]
492 #define resample_gint32_1 resample_funcs[1]
493 #define resample_gfloat_1 resample_funcs[2]
494 #define resample_gdouble_1 resample_funcs[3]
495 #define resample_gint16_2 resample_funcs[4]
496 #define resample_gint32_2 resample_funcs[5]
497 #define resample_gfloat_2 resample_funcs[6]
498 #define resample_gdouble_2 resample_funcs[7]
500 #if defined HAVE_ORC && !defined DISABLE_ORC
501 # if defined (__i386__) || defined (__x86_64__)
503 # include "audio-resampler-x86.h"
508 audio_resampler_init (void)
510 static gsize init_gonce = 0;
512 if (g_once_init_enter (&init_gonce)) {
514 GST_DEBUG_CATEGORY_INIT (audio_resampler_debug, "audio-resampler", 0,
515 "audio-resampler object");
517 #if defined HAVE_ORC && !defined DISABLE_ORC
520 OrcTarget *target = orc_target_get_default ();
524 unsigned int flags = orc_target_get_default_flags (target);
527 name = orc_target_get_name (target);
528 GST_DEBUG ("target %s, default flags %08x", name, flags);
530 for (i = 0; i < 32; ++i) {
531 if (flags & (1U << i)) {
532 name = orc_target_get_flag_name (target, i);
533 GST_DEBUG ("target flag %s", name);
535 audio_resampler_check_x86 (name);
542 g_once_init_leave (&init_gonce, 1);
546 #define MAKE_DEINTERLEAVE_FUNC(type) \
548 deinterleave_ ##type (GstAudioResampler * resampler, gpointer sbuf[], \
549 gpointer in[], gsize in_frames) \
551 guint i, c, channels = resampler->channels; \
552 gsize samples_avail = resampler->samples_avail; \
553 for (c = 0; c < channels; c++) { \
554 type *s = (type *) sbuf[c] + samples_avail; \
555 if (G_UNLIKELY (in == NULL)) { \
556 for (i = 0; i < in_frames; i++) \
559 type *ip = (type *) in[0] + c; \
560 for (i = 0; i < in_frames; i++, ip += channels) \
566 MAKE_DEINTERLEAVE_FUNC (gdouble);
567 MAKE_DEINTERLEAVE_FUNC (gfloat);
568 MAKE_DEINTERLEAVE_FUNC (gint32);
569 MAKE_DEINTERLEAVE_FUNC (gint16);
572 deinterleave_copy (GstAudioResampler * resampler, gpointer sbuf[],
573 gpointer in[], gsize in_frames)
575 guint c, blocks = resampler->blocks;
576 gsize bytes_avail, in_bytes, bpf;
578 bpf = resampler->bps * resampler->inc;
579 bytes_avail = resampler->samples_avail * bpf;
580 in_bytes = in_frames * bpf;
582 for (c = 0; c < blocks; c++) {
583 if (G_UNLIKELY (in == NULL))
584 memset ((guint8 *) sbuf[c] + bytes_avail, 0, in_bytes);
586 memcpy ((guint8 *) sbuf[c] + bytes_avail, in[c], in_bytes);
591 calculate_kaiser_params (GstAudioResampler * resampler)
593 gdouble A, B, dw, tr_bw, Fc;
595 const KaiserQualityMap *q = &kaiser_qualities[DEFAULT_QUALITY];
599 if (resampler->out_rate < resampler->in_rate)
600 Fc *= q->downsample_cutoff_factor;
602 Fc = GET_OPT_CUTOFF (resampler->options, Fc);
603 A = GET_OPT_STOP_ATTENUATION (resampler->options, q->stopband_attenuation);
605 GET_OPT_TRANSITION_BANDWIDTH (resampler->options,
606 q->transition_bandwidth);
608 GST_LOG ("Fc %f, A %f, tr_bw %f", Fc, A, tr_bw);
612 B = 0.1102 * (A - 8.7);
614 B = 0.5842 * pow (A - 21, 0.4) + 0.07886 * (A - 21);
617 /* calculate transition width in radians */
618 dw = 2 * G_PI * (tr_bw);
619 /* order of the filter */
620 n = (A - 8.0) / (2.285 * dw);
622 resampler->kaiser_beta = B;
623 resampler->n_taps = n + 1;
624 resampler->cutoff = Fc;
626 GST_LOG ("using Beta %f n_taps %d cutoff %f", resampler->kaiser_beta,
627 resampler->n_taps, resampler->cutoff);
631 resampler_calculate_taps (GstAudioResampler * resampler)
638 gboolean non_interleaved;
639 DeinterleaveFunc deinterleave;
640 ResampleFunc resample, resample_2;
642 switch (resampler->method) {
643 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
644 resampler->n_taps = 2;
646 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
647 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 2);
649 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
650 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 4);
651 resampler->b = GET_OPT_CUBIC_B (resampler->options);
652 resampler->c = GET_OPT_CUBIC_C (resampler->options);;
654 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
656 const BlackmanQualityMap *q = &blackman_qualities[DEFAULT_QUALITY];
657 resampler->n_taps = GET_OPT_N_TAPS (resampler->options, q->n_taps);
658 resampler->cutoff = GET_OPT_CUTOFF (resampler->options, q->cutoff);
661 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
662 calculate_kaiser_params (resampler);
666 in_rate = resampler->in_rate;
667 out_rate = resampler->out_rate;
669 if (out_rate < in_rate) {
670 resampler->cutoff = resampler->cutoff * out_rate / in_rate;
672 gst_util_uint64_scale_int (resampler->n_taps, in_rate, out_rate);
674 /* only round up for bigger taps, the small taps are used for nearest,
675 * linear and cubic and we want to use less taps for those. */
676 if (resampler->n_taps > 4)
677 resampler->n_taps = GST_ROUND_UP_8 (resampler->n_taps);
679 n_taps = resampler->n_taps;
680 bps = resampler->bps;
682 GST_LOG ("using n_taps %d cutoff %f", n_taps, resampler->cutoff);
684 resampler->taps = g_realloc_n (resampler->taps, out_rate, sizeof (Tap));
686 resampler->cstride = GST_ROUND_UP_32 (bps * (n_taps + TAPS_OVERREAD));
687 g_free (resampler->coeffmem);
688 resampler->coeffmem = g_malloc0 (out_rate * resampler->cstride + ALIGN - 1);
689 resampler->coeff = MEM_ALIGN (resampler->coeffmem, ALIGN);
691 resampler->tmpcoeff =
692 g_realloc_n (resampler->tmpcoeff, n_taps, sizeof (gdouble));
694 resampler->samp_inc = in_rate / out_rate;
695 resampler->samp_frac = in_rate % out_rate;
697 for (j = 0; j < out_rate; j++) {
698 Tap *t = &resampler->taps[j];
703 (resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED);
705 resampler->ostride = non_interleaved ? 1 : resampler->channels;
707 /* we resample each channel separately */
708 resampler->blocks = resampler->channels;
711 switch (resampler->format) {
712 case GST_AUDIO_FORMAT_S16:
713 resample = resample_gint16_1;
714 resample_2 = resample_gint16_2;
715 deinterleave = deinterleave_gint16;
717 case GST_AUDIO_FORMAT_S32:
718 resample = resample_gint32_1;
719 resample_2 = resample_gint32_2;
720 deinterleave = deinterleave_gint32;
722 case GST_AUDIO_FORMAT_F32:
723 resample = resample_gfloat_1;
724 resample_2 = resample_gfloat_2;
725 deinterleave = deinterleave_gfloat;
727 case GST_AUDIO_FORMAT_F64:
728 resample = resample_gdouble_1;
729 resample_2 = resample_gdouble_2;
730 deinterleave = deinterleave_gdouble;
733 g_assert_not_reached ();
736 if (!non_interleaved && resampler->channels == 2 && n_taps >= 4 && resample_2) {
737 resampler->resample = resample_2;
738 resampler->deinterleave = deinterleave_copy;
739 resampler->blocks = 1;
740 resampler->inc = resampler->channels;;
742 resampler->resample = resample;
743 resampler->deinterleave = deinterleave;
747 #define PRINT_TAPS(type,print) \
749 type sum = 0.0, *taps; \
751 if ((taps = t->taps) == NULL) \
752 taps = make_taps (resampler, t, i); \
754 for (j = 0; j < n_taps; j++) { \
755 type tap = taps[j]; \
756 fprintf (stderr, "\t%" print " ", tap); \
759 fprintf (stderr, "\t: sum %" print "\n", sum);\
763 resampler_dump (GstAudioResampler * resampler)
766 gint i, n_taps, out_rate;
769 out_rate = resampler->out_rate;
770 n_taps = resampler->n_taps;
772 fprintf (stderr, "out size %d, max taps %d\n", out_rate, n_taps);
774 a = g_get_monotonic_time ();
776 for (i = 0; i < out_rate; i++) {
778 Tap *t = &resampler->taps[i];
780 fprintf (stderr, "%u: %d %d\t ", i, t->sample_inc, t->next_phase);
781 switch (resampler->format) {
782 case GST_AUDIO_FORMAT_F64:
783 PRINT_TAPS (gdouble, "f");
785 case GST_AUDIO_FORMAT_F32:
786 PRINT_TAPS (gfloat, "f");
788 case GST_AUDIO_FORMAT_S32:
789 PRINT_TAPS (gint32, "d");
791 case GST_AUDIO_FORMAT_S16:
792 PRINT_TAPS (gint16, "d");
798 fprintf (stderr, "time %" G_GUINT64_FORMAT "\n", g_get_monotonic_time () - a);
803 * gst_audio_resampler_options_set_quality:
804 * @method: a #GstAudioResamplerMethod
805 * @quality: the quality
806 * @in_rate: the input rate
807 * @out_rate: the output rate
808 * @options: a #GstStructure
810 * Set the parameters for resampling from @in_rate to @out_rate using @method
811 * for @quality in @options.
814 gst_audio_resampler_options_set_quality (GstAudioResamplerMethod method,
815 guint quality, gint in_rate, gint out_rate, GstStructure * options)
817 g_return_if_fail (options != NULL);
818 g_return_if_fail (quality <= GST_AUDIO_RESAMPLER_QUALITY_MAX);
819 g_return_if_fail (in_rate > 0 && out_rate > 0);
822 case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
824 case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
825 gst_structure_set (options,
826 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 2, NULL);
828 case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
829 gst_structure_set (options,
830 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 4,
831 GST_AUDIO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_B,
832 GST_AUDIO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_C,
835 case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
837 const BlackmanQualityMap *map = &blackman_qualities[quality];
838 gst_structure_set (options,
839 GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, map->n_taps,
840 GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, map->cutoff, NULL);
843 case GST_AUDIO_RESAMPLER_METHOD_KAISER:
845 const KaiserQualityMap *map = &kaiser_qualities[quality];
848 cutoff = map->cutoff;
849 if (out_rate < in_rate)
850 cutoff *= map->downsample_cutoff_factor;
852 gst_structure_set (options,
853 GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, cutoff,
854 GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, G_TYPE_DOUBLE,
855 map->stopband_attenuation,
856 GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, G_TYPE_DOUBLE,
857 map->transition_bandwidth, NULL);
864 * gst_audio_resampler_new:
865 * @resampler: a #GstAudioResampler
866 * @method: a #GstAudioResamplerMethod
867 * @flags: #GstAudioResamplerFlags
868 * @in_rate: input rate
869 * @out_rate: output rate
870 * @options: extra options
872 * Make a new resampler.
874 * Returns: %TRUE on success
877 gst_audio_resampler_new (GstAudioResamplerMethod method,
878 GstAudioResamplerFlags flags,
879 GstAudioFormat format, gint channels,
880 gint in_rate, gint out_rate, GstStructure * options)
882 GstAudioResampler *resampler;
883 const GstAudioFormatInfo *info;
885 g_return_val_if_fail (channels > 0, FALSE);
886 g_return_val_if_fail (in_rate > 0, FALSE);
887 g_return_val_if_fail (out_rate > 0, FALSE);
889 audio_resampler_init ();
891 resampler = g_slice_new0 (GstAudioResampler);
892 resampler->method = method;
893 resampler->flags = flags;
894 resampler->format = format;
895 resampler->channels = channels;
897 info = gst_audio_format_get_info (format);
898 resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
899 resampler->sbuf = g_malloc0 (sizeof (gpointer) * channels);
901 GST_DEBUG ("method %d, bps %d, channels %d", method, resampler->bps,
902 resampler->channels);
904 gst_audio_resampler_update (resampler, in_rate, out_rate, options);
906 /* half of the filter is filled with 0 */
907 resampler->samp_index = 0;
908 resampler->samples_avail = resampler->n_taps / 2 - 1;
913 /* make the buffers to hold the (deinterleaved) samples */
914 static inline gpointer *
915 get_sample_bufs (GstAudioResampler * resampler, gsize need)
917 if (G_LIKELY (resampler->samples_len < need)) {
918 guint c, blocks = resampler->blocks;
919 gsize bytes, to_move = 0;
920 gint8 *ptr, *samples;
922 GST_LOG ("realloc %d -> %d", (gint) resampler->samples_len, (gint) need);
924 bytes = GST_ROUND_UP_N (need * resampler->bps * resampler->inc, ALIGN);
926 samples = g_malloc0 (blocks * bytes + ALIGN - 1);
927 ptr = MEM_ALIGN (samples, ALIGN);
929 /* if we had some data, move history */
930 if (resampler->samples_len > 0)
931 to_move = resampler->samples_avail * resampler->bps * resampler->inc;
933 /* set up new pointers */
934 for (c = 0; c < blocks; c++) {
935 memcpy (ptr + (c * bytes), resampler->sbuf[c], to_move);
936 resampler->sbuf[c] = ptr + (c * bytes);
938 g_free (resampler->samples);
939 resampler->samples = samples;
940 resampler->samples_len = need;
942 return resampler->sbuf;
946 * gst_audio_resampler_reset:
947 * @resampler: a #GstAudioResampler
949 * Reset @resampler to the state it was when it was first created, discarding
950 * all sample history.
953 gst_audio_resampler_reset (GstAudioResampler * resampler)
955 g_return_if_fail (resampler != NULL);
957 if (resampler->samples) {
961 bpf = resampler->bps * resampler->inc;
962 bytes = (resampler->n_taps / 2) * bpf;
963 blocks = resampler->blocks;
965 for (c = 0; c < blocks; c++)
966 memset (resampler->sbuf[c], 0, bytes);
968 /* half of the filter is filled with 0 */
969 resampler->samp_index = 0;
970 resampler->samples_avail = resampler->n_taps / 2 - 1;
974 * gst_audio_resampler_update:
975 * @resampler: a #GstAudioResampler
976 * @in_rate: new input rate
977 * @out_rate: new output rate
978 * @options: new options or %NULL
980 * Update the resampler parameters for @resampler. This function should
981 * not be called concurrently with any other function on @resampler.
983 * When @in_rate or @out_rate is 0, its value is unchanged.
985 * When @options is %NULL, the previously configured options are reused.
987 * Returns: %TRUE if the new parameters could be set
990 gst_audio_resampler_update (GstAudioResampler * resampler,
991 gint in_rate, gint out_rate, GstStructure * options)
993 gint gcd, samp_phase, old_n_taps;
995 g_return_val_if_fail (resampler != NULL, FALSE);
998 in_rate = resampler->in_rate;
1000 out_rate = resampler->out_rate;
1002 if (resampler->out_rate > 0)
1004 gst_util_uint64_scale_int (resampler->samp_phase, out_rate,
1005 resampler->out_rate);
1009 gcd = gst_util_greatest_common_divisor (in_rate, out_rate);
1012 gdouble ph1 = (gdouble) samp_phase / out_rate;
1015 /* reduce the factor until we have a phase error of less than 10% */
1017 gdouble ph2 = (gdouble) (samp_phase / gcd) / (out_rate / gcd);
1019 if (fabs (ph1 - ph2) < 0.1)
1022 while (gcd % factor != 0)
1026 GST_INFO ("divide by factor %d, gcd %d", factor, gcd);
1031 GST_INFO ("phase %d, out_rate %d, in_rate %d, gcd %d", samp_phase, out_rate,
1034 resampler->samp_phase = samp_phase / gcd;
1035 resampler->in_rate = in_rate / gcd;
1036 resampler->out_rate = out_rate / gcd;
1039 if (resampler->options)
1040 gst_structure_free (resampler->options);
1041 resampler->options = gst_structure_copy (options);
1044 old_n_taps = resampler->n_taps;
1046 resampler_calculate_taps (resampler);
1047 resampler_dump (resampler);
1049 GST_DEBUG ("rate %u->%u, taps %d->%d", resampler->in_rate,
1050 resampler->out_rate, old_n_taps, resampler->n_taps);
1052 if (old_n_taps > 0) {
1054 gint i, bpf, bytes, soff, doff, diff;
1056 sbuf = get_sample_bufs (resampler, resampler->n_taps);
1058 bpf = resampler->bps * resampler->inc;
1059 bytes = resampler->samples_avail * bpf;
1060 soff = doff = resampler->samp_index * bpf;
1062 diff = ((gint) resampler->n_taps - old_n_taps) / 2;
1065 /* diff < 0, decrease taps, adjust source */
1066 soff += -diff * bpf;
1067 bytes -= -diff * bpf;
1069 /* diff > 0, increase taps, adjust dest */
1073 /* now shrink or enlarge the history buffer, when we enlarge we
1074 * just leave the old samples in there. FIXME, probably do something better
1075 * like mirror or fill with zeroes. */
1076 for (i = 0; i < resampler->blocks; i++)
1077 memmove ((gint8 *) sbuf[i] + doff, (gint8 *) sbuf[i] + soff, bytes);
1079 resampler->samples_avail += diff;
1085 * gst_audio_resampler_free:
1086 * @resampler: a #GstAudioResampler
1088 * Free a previously allocated #GstAudioResampler @resampler.
1093 gst_audio_resampler_free (GstAudioResampler * resampler)
1095 g_return_if_fail (resampler != NULL);
1097 g_free (resampler->taps);
1098 g_free (resampler->coeffmem);
1099 g_free (resampler->tmpcoeff);
1100 g_free (resampler->samples);
1101 g_free (resampler->sbuf);
1102 if (resampler->options)
1103 gst_structure_free (resampler->options);
1104 g_slice_free (GstAudioResampler, resampler);
1108 calc_out (GstAudioResampler * resampler, gsize in)
1112 out = in * resampler->out_rate;
1113 if (out < resampler->samp_phase)
1116 out = ((out - resampler->samp_phase) / resampler->in_rate) + 1;
1117 GST_LOG ("out %d = ((%d * %d - %d) / %d) + 1", (gint) out,
1118 (gint) in, resampler->out_rate, resampler->samp_phase,
1119 resampler->in_rate);
1125 * gst_audio_resampler_get_out_frames:
1126 * @resampler: a #GstAudioResampler
1127 * @in_frames: number of input frames
1129 * Get the number of output frames that would be currently available when
1130 * @in_frames are given to @resampler.
1132 * Returns: The number of frames that would be availabe after giving
1133 * @in_frames as input to @resampler.
1136 gst_audio_resampler_get_out_frames (GstAudioResampler * resampler,
1141 g_return_val_if_fail (resampler != NULL, 0);
1143 need = resampler->n_taps + resampler->samp_index + resampler->skip;
1144 avail = resampler->samples_avail + in_frames;
1145 GST_LOG ("need %d = %d + %d + %d, avail %d = %d + %d", (gint) need,
1146 resampler->n_taps, resampler->samp_index, resampler->skip,
1147 (gint) avail, (gint) resampler->samples_avail, (gint) in_frames);
1151 return calc_out (resampler, avail - need);
1155 * gst_audio_resampler_get_in_frames:
1156 * @resampler: a #GstAudioResampler
1157 * @out_frames: number of input frames
1159 * Get the number of input frames that would currently be needed
1160 * to produce @out_frames from @resampler.
1162 * Returns: The number of input frames needed for producing
1163 * @out_frames of data from @resampler.
1166 gst_audio_resampler_get_in_frames (GstAudioResampler * resampler,
1171 g_return_val_if_fail (resampler != NULL, 0);
1174 (resampler->samp_phase +
1175 out_frames * resampler->samp_frac) / resampler->out_rate;
1176 in_frames += out_frames * resampler->samp_inc;
1182 * gst_audio_resampler_get_max_latency:
1183 * @resampler: a #GstAudioResampler
1185 * Get the maximum number of input samples that the resampler would
1186 * need before producing output.
1188 * Returns: the latency of @resampler as expressed in the number of
1192 gst_audio_resampler_get_max_latency (GstAudioResampler * resampler)
1194 g_return_val_if_fail (resampler != NULL, 0);
1196 return resampler->n_taps / 2;
1200 * gst_audio_resampler_resample:
1201 * @resampler: a #GstAudioResampler
1202 * @in: input samples
1203 * @in_frames: number of input frames
1204 * @out: output samples
1205 * @out_frames: number of output frames
1207 * Perform resampling on @in_frames frames in @in and write @out_frames to @out.
1209 * In case the samples are interleaved, @in and @out must point to an
1210 * array with a single element pointing to a block of interleaved samples.
1212 * If non-interleaved samples are used, @in and @out must point to an
1213 * array with pointers to memory blocks, one for each channel.
1215 * @in may be %NULL, in which case @in_frames of silence samples are pushed
1216 * into the resampler.
1218 * This function always produces @out_frames of output and consumes @in_frames of
1219 * input. Use gst_audio_resampler_get_out_frames() and
1220 * gst_audio_resampler_get_in_frames() to make sure @in_frames and @out_frames
1221 * are matching and @in and @out point to enough memory.
1224 gst_audio_resampler_resample (GstAudioResampler * resampler,
1225 gpointer in[], gsize in_frames, gpointer out[], gsize out_frames)
1227 gsize samples_avail;
1228 gsize need, consumed;
1231 /* do sample skipping */
1232 if (G_UNLIKELY (resampler->skip >= in_frames)) {
1233 /* we need tp skip all input */
1234 resampler->skip -= in_frames;
1237 /* skip the last samples by advancing the sample index */
1238 resampler->samp_index += resampler->skip;
1240 samples_avail = resampler->samples_avail;
1242 /* make sure we have enough space to copy our samples */
1243 sbuf = get_sample_bufs (resampler, in_frames + samples_avail);
1245 /* copy/deinterleave the samples */
1246 resampler->deinterleave (resampler, sbuf, in, in_frames);
1248 /* update new amount of samples in our buffer */
1249 resampler->samples_avail = samples_avail += in_frames;
1251 need = resampler->n_taps + resampler->samp_index;
1252 if (G_UNLIKELY (samples_avail < need)) {
1253 /* not enough samples to start */
1257 /* resample all channels */
1258 resampler->resample (resampler, sbuf, samples_avail, out, out_frames,
1261 GST_LOG ("in %" G_GSIZE_FORMAT ", avail %" G_GSIZE_FORMAT ", consumed %"
1262 G_GSIZE_FORMAT, in_frames, samples_avail, consumed);
1264 /* update pointers */
1265 if (G_LIKELY (consumed > 0)) {
1266 gssize left = samples_avail - consumed;
1268 /* we consumed part of our samples */
1269 resampler->samples_avail = left;
1271 /* we consumed all our samples, empty our buffers */
1272 resampler->samples_avail = 0;
1273 resampler->skip = -left;