• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2015> Wim Taymans <wim.taymans@gmail.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <string.h>
25 #include <stdio.h>
26 #include <math.h>
27 
28 #ifdef HAVE_ORC
29 #include <orc/orc.h>
30 #endif
31 
32 #include "audio-resampler.h"
33 #include "audio-resampler-private.h"
34 #include "audio-resampler-macros.h"
35 
36 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
37 #define ALIGN 16
38 #define TAPS_OVERREAD 16
39 
40 GST_DEBUG_CATEGORY_STATIC (audio_resampler_debug);
41 #define GST_CAT_DEFAULT audio_resampler_debug
42 
43 /**
44  * SECTION:gstaudioresampler
45  * @title: GstAudioResampler
46  * @short_description: Utility structure for resampler information
47  *
48  * #GstAudioResampler is a structure which holds the information
49  * required to perform various kinds of resampling filtering.
50  *
51  */
52 
53 static const gint oversample_qualities[] = {
54   4, 4, 4, 8, 8, 16, 16, 16, 16, 32, 32
55 };
56 
57 typedef struct
58 {
59   gdouble cutoff;
60   gdouble downsample_cutoff_factor;
61   gdouble stopband_attenuation;
62   gdouble transition_bandwidth;
63 } KaiserQualityMap;
64 
65 static const KaiserQualityMap kaiser_qualities[] = {
66   {0.860, 0.96511, 60, 0.7},    /* 8 taps */
67   {0.880, 0.96591, 65, 0.29},   /* 16 taps */
68   {0.910, 0.96923, 70, 0.145},  /* 32 taps */
69   {0.920, 0.97600, 80, 0.105},  /* 48 taps */
70   {0.940, 0.97979, 85, 0.087},  /* 64 taps default quality */
71   {0.940, 0.98085, 95, 0.077},  /* 80 taps */
72   {0.945, 0.99471, 100, 0.068}, /* 96 taps */
73   {0.950, 1.0, 105, 0.055},     /* 128 taps */
74   {0.960, 1.0, 110, 0.045},     /* 160 taps */
75   {0.968, 1.0, 115, 0.039},     /* 192 taps */
76   {0.975, 1.0, 120, 0.0305}     /* 256 taps */
77 };
78 
79 typedef struct
80 {
81   gint n_taps;
82   gdouble cutoff;
83 } BlackmanQualityMap;
84 
85 static const BlackmanQualityMap blackman_qualities[] = {
86   {8, 0.5,},
87   {16, 0.6,},
88   {24, 0.72,},
89   {32, 0.8,},
90   {48, 0.85,},                  /* default */
91   {64, 0.90,},
92   {80, 0.92,},
93   {96, 0.933,},
94   {128, 0.950,},
95   {148, 0.955,},
96   {160, 0.960,}
97 };
98 
99 #define DEFAULT_RESAMPLER_METHOD GST_AUDIO_RESAMPLER_METHOD_KAISER
100 #define DEFAULT_QUALITY GST_AUDIO_RESAMPLER_QUALITY_DEFAULT
101 #define DEFAULT_OPT_CUBIC_B 1.0
102 #define DEFAULT_OPT_CUBIC_C 0.0
103 #define DEFAULT_OPT_FILTER_MODE GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO
104 #define DEFAULT_OPT_FILTER_MODE_THRESHOLD 1048576
105 #define DEFAULT_OPT_FILTER_INTERPOLATION GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC
106 #define DEFAULT_OPT_FILTER_OVERSAMPLE 8
107 #define DEFAULT_OPT_MAX_PHASE_ERROR 0.1
108 
109 static gdouble
get_opt_double(GstStructure * options,const gchar * name,gdouble def)110 get_opt_double (GstStructure * options, const gchar * name, gdouble def)
111 {
112   gdouble res;
113   if (!options || !gst_structure_get_double (options, name, &res))
114     res = def;
115   return res;
116 }
117 
118 static gint
get_opt_int(GstStructure * options,const gchar * name,gint def)119 get_opt_int (GstStructure * options, const gchar * name, gint def)
120 {
121   gint res;
122   if (!options || !gst_structure_get_int (options, name, &res))
123     res = def;
124   return res;
125 }
126 
127 static gint
get_opt_enum(GstStructure * options,const gchar * name,GType type,gint def)128 get_opt_enum (GstStructure * options, const gchar * name, GType type, gint def)
129 {
130   gint res;
131   if (!options || !gst_structure_get_enum (options, name, type, &res))
132     res = def;
133   return res;
134 }
135 
136 
137 #define GET_OPT_CUTOFF(options,def) get_opt_double(options, \
138     GST_AUDIO_RESAMPLER_OPT_CUTOFF,def)
139 #define GET_OPT_DOWN_CUTOFF_FACTOR(options,def) get_opt_double(options, \
140     GST_AUDIO_RESAMPLER_OPT_DOWN_CUTOFF_FACTOR, def)
141 #define GET_OPT_STOP_ATTENUATION(options,def) get_opt_double(options, \
142     GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, def)
143 #define GET_OPT_TRANSITION_BANDWIDTH(options,def) get_opt_double(options, \
144     GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, def)
145 #define GET_OPT_CUBIC_B(options) get_opt_double(options, \
146     GST_AUDIO_RESAMPLER_OPT_CUBIC_B, DEFAULT_OPT_CUBIC_B)
147 #define GET_OPT_CUBIC_C(options) get_opt_double(options, \
148     GST_AUDIO_RESAMPLER_OPT_CUBIC_C, DEFAULT_OPT_CUBIC_C)
149 #define GET_OPT_N_TAPS(options,def) get_opt_int(options, \
150     GST_AUDIO_RESAMPLER_OPT_N_TAPS, def)
151 #define GET_OPT_FILTER_MODE(options) get_opt_enum(options, \
152     GST_AUDIO_RESAMPLER_OPT_FILTER_MODE, GST_TYPE_AUDIO_RESAMPLER_FILTER_MODE, \
153     DEFAULT_OPT_FILTER_MODE)
154 #define GET_OPT_FILTER_MODE_THRESHOLD(options) get_opt_int(options, \
155     GST_AUDIO_RESAMPLER_OPT_FILTER_MODE_THRESHOLD, DEFAULT_OPT_FILTER_MODE_THRESHOLD)
156 #define GET_OPT_FILTER_INTERPOLATION(options) get_opt_enum(options, \
157     GST_AUDIO_RESAMPLER_OPT_FILTER_INTERPOLATION, GST_TYPE_AUDIO_RESAMPLER_FILTER_INTERPOLATION, \
158     DEFAULT_OPT_FILTER_INTERPOLATION)
159 #define GET_OPT_FILTER_OVERSAMPLE(options) get_opt_int(options, \
160     GST_AUDIO_RESAMPLER_OPT_FILTER_OVERSAMPLE, DEFAULT_OPT_FILTER_OVERSAMPLE)
161 #define GET_OPT_MAX_PHASE_ERROR(options) get_opt_double(options, \
162     GST_AUDIO_RESAMPLER_OPT_MAX_PHASE_ERROR, DEFAULT_OPT_MAX_PHASE_ERROR)
163 
164 #include "dbesi0.c"
165 #define bessel dbesi0
166 
167 static inline gdouble
get_linear_tap(gdouble x,gint n_taps)168 get_linear_tap (gdouble x, gint n_taps)
169 {
170   gdouble res = GST_ROUND_UP_2 (n_taps) / 2 - fabs (x);
171   return res;
172 }
173 
174 static inline gdouble
get_cubic_tap(gdouble x,gint n_taps,gdouble b,gdouble c)175 get_cubic_tap (gdouble x, gint n_taps, gdouble b, gdouble c)
176 {
177   gdouble res, a, a2, a3;
178 
179   a = fabs (x * 4.0) / n_taps;
180   a2 = a * a;
181   a3 = a2 * a;
182 
183   if (a <= 1.0)
184     res = ((12.0 - 9.0 * b - 6.0 * c) * a3 +
185         (-18.0 + 12.0 * b + 6.0 * c) * a2 + (6.0 - 2.0 * b)) / 6.0;
186   else if (a <= 2.0)
187     res = ((-b - 6.0 * c) * a3 +
188         (6.0 * b + 30.0 * c) * a2 +
189         (-12.0 * b - 48.0 * c) * a + (8.0 * b + 24.0 * c)) / 6.0;
190   else
191     res = 0.0;
192 
193   return res;
194 }
195 
196 static inline gdouble
get_blackman_nuttall_tap(gdouble x,gint n_taps,gdouble Fc)197 get_blackman_nuttall_tap (gdouble x, gint n_taps, gdouble Fc)
198 {
199   gdouble s, y, w;
200 
201   y = G_PI * x;
202   s = (y == 0.0 ? Fc : sin (y * Fc) / y);
203 
204   w = 2.0 * y / n_taps + G_PI;
205   return s * (0.3635819 - 0.4891775 * cos (w) + 0.1365995 * cos (2 * w) -
206       0.0106411 * cos (3 * w));
207 }
208 
209 static inline gdouble
get_kaiser_tap(gdouble x,gint n_taps,gdouble Fc,gdouble beta)210 get_kaiser_tap (gdouble x, gint n_taps, gdouble Fc, gdouble beta)
211 {
212   gdouble s, y, w;
213 
214   y = G_PI * x;
215   s = (y == 0.0 ? Fc : sin (y * Fc) / y);
216 
217   w = 2.0 * x / n_taps;
218   return s * bessel (beta * sqrt (MAX (1 - w * w, 0)));
219 }
220 
221 #define MAKE_CONVERT_TAPS_INT_FUNC(type, precision)                     \
222 static void                                                             \
223 convert_taps_##type##_c (gdouble *tmp_taps, gpointer taps,              \
224     gdouble weight, gint n_taps)                                        \
225 {                                                                       \
226   gint64 one = (1LL << precision) - 1;                                  \
227   type *t = taps;                                                       \
228   gdouble multiplier = one;                                             \
229   gint i, j;                                                            \
230   gdouble offset, l_offset, h_offset;                                   \
231   gboolean exact = FALSE;                                               \
232   /* Round to integer, but with an adjustable bias that we use to */    \
233   /* eliminate the DC error. */                                         \
234   l_offset = 0.0;                                                       \
235   h_offset = 1.0;                                                       \
236   offset = 0.5;                                                         \
237   for (i = 0; i < 32; i++) {                                            \
238     gint64 sum = 0;                                                     \
239     for (j = 0; j < n_taps; j++)                                        \
240       sum += floor (offset + tmp_taps[j] * multiplier / weight);        \
241     if (sum == one) {                                                   \
242       exact = TRUE;                                                     \
243       break;                                                            \
244     }                                                                   \
245     if (l_offset == h_offset)                                           \
246       break;                                                            \
247     if (sum < one) {                                                    \
248       if (offset > l_offset)                                            \
249         l_offset = offset;                                              \
250       offset += (h_offset - l_offset) / 2;                              \
251     } else {                                                            \
252       if (offset < h_offset)                                            \
253         h_offset = offset;                                              \
254       offset -= (h_offset - l_offset) / 2;                              \
255     }                                                                   \
256   }                                                                     \
257   for (j = 0; j < n_taps; j++)                                          \
258     t[j] = floor (offset + tmp_taps[j] * multiplier / weight);          \
259   if (!exact)                                                           \
260     GST_WARNING ("can't find exact taps");                              \
261 }
262 
263 #define MAKE_CONVERT_TAPS_FLOAT_FUNC(type)                              \
264 static void                                                             \
265 convert_taps_##type##_c (gdouble *tmp_taps, gpointer taps,              \
266     gdouble weight, gint n_taps)                                        \
267 {                                                                       \
268   gint i;                                                               \
269   type *t = taps;                                                       \
270   for (i = 0; i < n_taps; i++)                                          \
271     t[i] = tmp_taps[i] / weight;                                        \
272 }
273 
274 MAKE_CONVERT_TAPS_INT_FUNC (gint16, PRECISION_S16);
275 MAKE_CONVERT_TAPS_INT_FUNC (gint32, PRECISION_S32);
276 MAKE_CONVERT_TAPS_FLOAT_FUNC (gfloat);
277 MAKE_CONVERT_TAPS_FLOAT_FUNC (gdouble);
278 
279 static ConvertTapsFunc convert_taps_funcs[] = {
280   convert_taps_gint16_c,
281   convert_taps_gint32_c,
282   convert_taps_gfloat_c,
283   convert_taps_gdouble_c
284 };
285 
286 #define convert_taps_gint16   convert_taps_funcs[0]
287 #define convert_taps_gint32   convert_taps_funcs[1]
288 #define convert_taps_gfloat   convert_taps_funcs[2]
289 #define convert_taps_gdouble  convert_taps_funcs[3]
290 
291 static void
make_taps(GstAudioResampler * resampler,gdouble * res,gdouble x,gint n_taps)292 make_taps (GstAudioResampler * resampler, gdouble * res, gdouble x, gint n_taps)
293 {
294   gdouble weight = 0.0, *tmp_taps = resampler->tmp_taps;
295   gint i;
296 
297   switch (resampler->method) {
298     case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
299       break;
300 
301     case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
302       for (i = 0; i < n_taps; i++)
303         weight += tmp_taps[i] = get_linear_tap (x + i, resampler->n_taps);
304       break;
305 
306     case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
307       for (i = 0; i < n_taps; i++)
308         weight += tmp_taps[i] = get_cubic_tap (x + i, resampler->n_taps,
309             resampler->b, resampler->c);
310       break;
311 
312     case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
313       for (i = 0; i < n_taps; i++)
314         weight += tmp_taps[i] =
315             get_blackman_nuttall_tap (x + i,
316             resampler->n_taps, resampler->cutoff);
317       break;
318 
319     case GST_AUDIO_RESAMPLER_METHOD_KAISER:
320       for (i = 0; i < n_taps; i++)
321         weight += tmp_taps[i] =
322             get_kaiser_tap (x + i, resampler->n_taps,
323             resampler->cutoff, resampler->kaiser_beta);
324       break;
325   }
326   resampler->convert_taps (tmp_taps, res, weight, n_taps);
327 }
328 
329 #define MAKE_COEFF_LINEAR_INT_FUNC(type,type2,prec)                     \
330 static inline void                                                      \
331 make_coeff_##type##_linear (gint num, gint denom, type *icoeff)         \
332 {                                                                       \
333   type x = ((gint64)num << prec) / denom;                               \
334   icoeff[0] = icoeff[2] = x;                                            \
335   icoeff[1] = icoeff[3] = (type)(((type2)1 << prec)-1)  - x;            \
336 }
337 #define MAKE_COEFF_LINEAR_FLOAT_FUNC(type)                              \
338 static inline void                                                      \
339 make_coeff_##type##_linear (gint num, gint denom, type *icoeff)         \
340 {                                                                       \
341   type x = (type)num / denom;                                           \
342   icoeff[0] = icoeff[2] = x;                                            \
343   icoeff[1] = icoeff[3] = (type)1.0 - x;                                \
344 }
345 MAKE_COEFF_LINEAR_INT_FUNC (gint16, gint32, PRECISION_S16);
346 MAKE_COEFF_LINEAR_INT_FUNC (gint32, gint64, PRECISION_S32);
347 MAKE_COEFF_LINEAR_FLOAT_FUNC (gfloat);
348 MAKE_COEFF_LINEAR_FLOAT_FUNC (gdouble);
349 
350 #define MAKE_COEFF_CUBIC_INT_FUNC(type,type2,prec)                      \
351 static inline void                                                      \
352 make_coeff_##type##_cubic (gint num, gint denom, type *icoeff)          \
353 {                                                                       \
354   type2 one = ((type2)1 << prec) - 1;                                   \
355   type2 x = ((gint64) num << prec) / denom;                             \
356   type2 x2 = (x * x) >> prec;                                           \
357   type2 x3 = (x2 * x) >> prec;                                          \
358   icoeff[0] = (((x3 - x) << prec) / 6) >> prec;                         \
359   icoeff[1] = x + ((x2 - x3) >> 1);                                     \
360   icoeff[3] = -(((x << prec) / 3) >> prec) +                            \
361             (x2 >> 1) - (((x3 << prec) / 6) >> prec);                   \
362   icoeff[2] = one - icoeff[0] - icoeff[1] - icoeff[3];                  \
363 }
364 #define MAKE_COEFF_CUBIC_FLOAT_FUNC(type)                               \
365 static inline void                                                      \
366 make_coeff_##type##_cubic (gint num, gint denom, type *icoeff)          \
367 {                                                                       \
368   type x = (type) num / denom, x2 = x * x, x3 = x2 * x;                 \
369   icoeff[0] = 0.16667f * (x3 - x);                                      \
370   icoeff[1] = x + 0.5f * (x2 - x3);                                     \
371   icoeff[3] = -0.33333f * x + 0.5f * x2 - 0.16667f * x3;                \
372   icoeff[2] = (type)1.0 - icoeff[0] - icoeff[1] - icoeff[3];            \
373 }
374 MAKE_COEFF_CUBIC_INT_FUNC (gint16, gint32, PRECISION_S16);
375 MAKE_COEFF_CUBIC_INT_FUNC (gint32, gint64, PRECISION_S32);
376 MAKE_COEFF_CUBIC_FLOAT_FUNC (gfloat);
377 MAKE_COEFF_CUBIC_FLOAT_FUNC (gdouble);
378 
379 #define INTERPOLATE_INT_LINEAR_FUNC(type,type2,prec,limit)      \
380 static inline void                                              \
381 interpolate_##type##_linear_c (gpointer op, const gpointer ap,  \
382     gint len, const gpointer icp, gint astride)                 \
383 {                                                               \
384   gint i;                                                       \
385   type *o = op, *a = ap, *ic = icp;                             \
386   type2 tmp, c0 = ic[0];                                        \
387   const type *c[2] = {(type*)((gint8*)a + 0*astride),           \
388                       (type*)((gint8*)a + 1*astride)};          \
389                                                                 \
390   for (i = 0; i < len; i++) {                                   \
391     tmp = ((type2)c[0][i] - (type2)c[1][i]) * c0 +              \
392          (((type2)c[1][i]) << (prec));                          \
393     o[i] = (tmp + ((type2)1 << ((prec) - 1))) >> (prec);        \
394   }                                                             \
395 }
396 #define INTERPOLATE_FLOAT_LINEAR_FUNC(type)                     \
397 static inline void                                              \
398 interpolate_##type##_linear_c (gpointer op, const gpointer ap,  \
399     gint len, const gpointer icp, gint astride)                 \
400 {                                                               \
401   gint i;                                                       \
402   type *o = op, *a = ap, *ic = icp;                             \
403   type c0 = ic[0];                                              \
404   const type *c[2] = {(type*)((gint8*)a + 0*astride),           \
405                       (type*)((gint8*)a + 1*astride)};          \
406                                                                 \
407   for (i = 0; i < len; i++) {                                   \
408     o[i] = (c[0][i] - c[1][i]) * c0 + c[1][i];                  \
409   }                                                             \
410 }
411 
412 INTERPOLATE_INT_LINEAR_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
413 INTERPOLATE_INT_LINEAR_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
414 INTERPOLATE_FLOAT_LINEAR_FUNC (gfloat);
415 INTERPOLATE_FLOAT_LINEAR_FUNC (gdouble);
416 
417 #define INTERPOLATE_INT_CUBIC_FUNC(type,type2,prec,limit)       \
418 static inline void                                              \
419 interpolate_##type##_cubic_c (gpointer op, const gpointer ap,   \
420     gint len, const gpointer icp, gint astride)                 \
421 {                                                               \
422   gint i;                                                       \
423   type *o = op, *a = ap, *ic = icp;                             \
424   type2 tmp, c0 = ic[0], c1 = ic[1], c2 = ic[2], c3 = ic[3];    \
425   const type *c[4] = {(type*)((gint8*)a + 0*astride),           \
426                       (type*)((gint8*)a + 1*astride),           \
427                       (type*)((gint8*)a + 2*astride),           \
428                       (type*)((gint8*)a + 3*astride)};          \
429                                                                 \
430   for (i = 0; i < len; i++) {                                   \
431     tmp = (type2)c[0][i] * c0 + (type2)c[1][i] * c1 +           \
432           (type2)c[2][i] * c2 + (type2)c[3][i] * c3;            \
433     tmp = (tmp + ((type2)1 << ((prec) - 1))) >> (prec);         \
434     o[i] = CLAMP (tmp, -(limit), (limit) - 1);                  \
435   }                                                             \
436 }
437 #define INTERPOLATE_FLOAT_CUBIC_FUNC(type)                      \
438 static inline void                                              \
439 interpolate_##type##_cubic_c (gpointer op, const gpointer ap,   \
440     gint len, const gpointer icp, gint astride)                 \
441 {                                                               \
442   gint i;                                                       \
443   type *o = op, *a = ap, *ic = icp;                             \
444   type c0 = ic[0], c1 = ic[1], c2 = ic[2], c3 = ic[3];          \
445   const type *c[4] = {(type*)((gint8*)a + 0*astride),           \
446                       (type*)((gint8*)a + 1*astride),           \
447                       (type*)((gint8*)a + 2*astride),           \
448                       (type*)((gint8*)a + 3*astride)};          \
449                                                                 \
450   for (i = 0; i < len; i++) {                                   \
451     o[i] = c[0][i] * c0 + c[1][i] * c1 +                        \
452            c[2][i] * c2 + c[3][i] * c3;                         \
453   }                                                             \
454 }
455 
456 INTERPOLATE_INT_CUBIC_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
457 INTERPOLATE_INT_CUBIC_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
458 INTERPOLATE_FLOAT_CUBIC_FUNC (gfloat);
459 INTERPOLATE_FLOAT_CUBIC_FUNC (gdouble);
460 
461 static InterpolateFunc interpolate_funcs[] = {
462   interpolate_gint16_linear_c,
463   interpolate_gint32_linear_c,
464   interpolate_gfloat_linear_c,
465   interpolate_gdouble_linear_c,
466 
467   interpolate_gint16_cubic_c,
468   interpolate_gint32_cubic_c,
469   interpolate_gfloat_cubic_c,
470   interpolate_gdouble_cubic_c,
471 };
472 
473 #define interpolate_gint16_linear  interpolate_funcs[0]
474 #define interpolate_gint32_linear  interpolate_funcs[1]
475 #define interpolate_gfloat_linear  interpolate_funcs[2]
476 #define interpolate_gdouble_linear interpolate_funcs[3]
477 
478 #define interpolate_gint16_cubic   interpolate_funcs[4]
479 #define interpolate_gint32_cubic   interpolate_funcs[5]
480 #define interpolate_gfloat_cubic   interpolate_funcs[6]
481 #define interpolate_gdouble_cubic  interpolate_funcs[7]
482 
483 #define GET_TAPS_NEAREST_FUNC(type)                                             \
484 static inline gpointer                                                          \
485 get_taps_##type##_nearest (GstAudioResampler * resampler,                       \
486     gint *samp_index, gint *samp_phase, type icoeff[4])                         \
487 {                                                                               \
488   gint out_rate = resampler->out_rate;                                          \
489   *samp_index += resampler->samp_inc;                                           \
490   *samp_phase += resampler->samp_frac;                                          \
491   if (*samp_phase >= out_rate) {                                                \
492     *samp_phase -= out_rate;                                                    \
493     *samp_index += 1;                                                           \
494   }                                                                             \
495   return NULL;                                                                  \
496 }
497 GET_TAPS_NEAREST_FUNC (gint16);
498 GET_TAPS_NEAREST_FUNC (gint32);
499 GET_TAPS_NEAREST_FUNC (gfloat);
500 GET_TAPS_NEAREST_FUNC (gdouble);
501 
502 #define get_taps_gint16_nearest get_taps_gint16_nearest
503 #define get_taps_gint32_nearest get_taps_gint32_nearest
504 #define get_taps_gfloat_nearest get_taps_gfloat_nearest
505 #define get_taps_gdouble_nearest get_taps_gdouble_nearest
506 
507 #define GET_TAPS_FULL_FUNC(type)                                                \
508 DECL_GET_TAPS_FULL_FUNC(type)                                                   \
509 {                                                                               \
510   gpointer res;                                                                 \
511   gint out_rate = resampler->out_rate;                                          \
512   gint n_phases = resampler->n_phases;                                          \
513   gint phase = (n_phases == out_rate ? *samp_phase :                            \
514       ((gint64)*samp_phase * n_phases) / out_rate);                             \
515                                                                                 \
516   res = resampler->cached_phases[phase];                                        \
517   if (G_UNLIKELY (res == NULL)) {                                               \
518     res = (gint8 *) resampler->cached_taps +                                    \
519                         phase * resampler->cached_taps_stride;                  \
520     switch (resampler->filter_interpolation) {                                  \
521       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE:                       \
522       {                                                                         \
523         gdouble x;                                                              \
524         gint n_taps = resampler->n_taps;                                        \
525                                                                                 \
526         x = 1.0 - n_taps / 2 - (gdouble) phase / n_phases;                      \
527         make_taps (resampler, res, x, n_taps);                                  \
528         break;                                                                  \
529       }                                                                         \
530       default:                                                                  \
531       {                                                                         \
532         gint offset, pos, frac;                                                 \
533         gint oversample = resampler->oversample;                                \
534         gint taps_stride = resampler->taps_stride;                              \
535         gint n_taps = resampler->n_taps;                                        \
536         type ic[4], *taps;                                                      \
537                                                                                 \
538         pos = phase * oversample;                                               \
539         offset = (oversample - 1) - pos / n_phases;                             \
540         frac = pos % n_phases;                                                  \
541                                                                                 \
542         taps = (type *) ((gint8 *) resampler->taps + offset * taps_stride);     \
543                                                                                 \
544         switch (resampler->filter_interpolation) {                              \
545           default:                                                              \
546           case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:                 \
547             make_coeff_##type##_linear (frac, n_phases, ic);                    \
548             break;                                                              \
549           case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:                  \
550             make_coeff_##type##_cubic (frac, n_phases, ic);                     \
551             break;                                                              \
552         }                                                                       \
553         resampler->interpolate (res, taps, n_taps, ic, taps_stride);            \
554       }                                                                         \
555     }                                                                           \
556     resampler->cached_phases[phase] = res;                                      \
557   }                                                                             \
558   *samp_index += resampler->samp_inc;                                           \
559   *samp_phase += resampler->samp_frac;                                          \
560   if (*samp_phase >= out_rate) {                                                \
561     *samp_phase -= out_rate;                                                    \
562     *samp_index += 1;                                                           \
563   }                                                                             \
564   return res;                                                                   \
565 }
566 GET_TAPS_FULL_FUNC (gint16);
567 GET_TAPS_FULL_FUNC (gint32);
568 GET_TAPS_FULL_FUNC (gfloat);
569 GET_TAPS_FULL_FUNC (gdouble);
570 
571 #define GET_TAPS_INTERPOLATE_FUNC(type,inter)                   \
572 DECL_GET_TAPS_INTERPOLATE_FUNC (type, inter)                    \
573 {                                                               \
574   gpointer res;                                                 \
575   gint out_rate = resampler->out_rate;                          \
576   gint offset, frac, pos;                                       \
577   gint oversample = resampler->oversample;                      \
578   gint taps_stride = resampler->taps_stride;                    \
579                                                                 \
580   pos = *samp_phase * oversample;                               \
581   offset = (oversample - 1) - pos / out_rate;                   \
582   frac = pos % out_rate;                                        \
583                                                                 \
584   res = (gint8 *) resampler->taps + offset * taps_stride;       \
585   make_coeff_##type##_##inter (frac, out_rate, icoeff);         \
586                                                                 \
587   *samp_index += resampler->samp_inc;                           \
588   *samp_phase += resampler->samp_frac;                          \
589   if (*samp_phase >= out_rate) {                                \
590     *samp_phase -= out_rate;                                    \
591     *samp_index += 1;                                           \
592   }                                                             \
593   return res;                                                   \
594 }
595 
596 GET_TAPS_INTERPOLATE_FUNC (gint16, linear);
597 GET_TAPS_INTERPOLATE_FUNC (gint32, linear);
598 GET_TAPS_INTERPOLATE_FUNC (gfloat, linear);
599 GET_TAPS_INTERPOLATE_FUNC (gdouble, linear);
600 
601 GET_TAPS_INTERPOLATE_FUNC (gint16, cubic);
602 GET_TAPS_INTERPOLATE_FUNC (gint32, cubic);
603 GET_TAPS_INTERPOLATE_FUNC (gfloat, cubic);
604 GET_TAPS_INTERPOLATE_FUNC (gdouble, cubic);
605 
606 #define INNER_PRODUCT_NEAREST_FUNC(type)                        \
607 static inline void                                              \
608 inner_product_##type##_nearest_1_c (type * o, const type * a,   \
609     const type * b, gint len, const type *ic, gint bstride)     \
610 {                                                               \
611   *o = *a;                                                      \
612 }
613 INNER_PRODUCT_NEAREST_FUNC (gint16);
614 INNER_PRODUCT_NEAREST_FUNC (gint32);
615 INNER_PRODUCT_NEAREST_FUNC (gfloat);
616 INNER_PRODUCT_NEAREST_FUNC (gdouble);
617 
618 #define INNER_PRODUCT_INT_FULL_FUNC(type,type2,prec,limit)      \
619 static inline void                                              \
620 inner_product_##type##_full_1_c (type * o, const type * a,      \
621     const type * b, gint len, const type *ic, gint bstride)     \
622 {                                                               \
623   gint i;                                                       \
624   type2 res[4] = { 0, 0, 0, 0 };                                \
625                                                                 \
626   for (i = 0; i < len; i += 4) {                                \
627     res[0] += (type2) a[i + 0] * (type2) b[i + 0];              \
628     res[1] += (type2) a[i + 1] * (type2) b[i + 1];              \
629     res[2] += (type2) a[i + 2] * (type2) b[i + 2];              \
630     res[3] += (type2) a[i + 3] * (type2) b[i + 3];              \
631   }                                                             \
632   res[0] = res[0] + res[1] + res[2] + res[3];                   \
633   res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec);     \
634   *o = CLAMP (res[0], -(limit), (limit) - 1);                   \
635 }
636 
637 INNER_PRODUCT_INT_FULL_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
638 INNER_PRODUCT_INT_FULL_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
639 
640 #define INNER_PRODUCT_INT_LINEAR_FUNC(type,type2,prec,limit)    \
641 static inline void                                              \
642 inner_product_##type##_linear_1_c (type * o, const type * a,    \
643     const type * b, gint len, const type *ic, gint bstride)     \
644 {                                                               \
645   gint i;                                                       \
646   type2 res[4] = { 0, 0, 0, 0 }, c0 = ic[0];                    \
647   const type *c[2] = {(type*)((gint8*)b + 0*bstride),           \
648                       (type*)((gint8*)b + 1*bstride)};          \
649                                                                 \
650   for (i = 0; i < len; i += 2) {                                \
651     res[0] += (type2) a[i + 0] * (type2) c[0][i + 0];           \
652     res[1] += (type2) a[i + 0] * (type2) c[1][i + 0];           \
653     res[2] += (type2) a[i + 1] * (type2) c[0][i + 1];           \
654     res[3] += (type2) a[i + 1] * (type2) c[1][i + 1];           \
655   }                                                             \
656   res[0] = (res[0] + res[2]) >> (prec);                         \
657   res[1] = (res[1] + res[3]) >> (prec);                         \
658   res[0] = ((type2)(type)res[0] - (type2)(type)res[1]) * c0 +   \
659            ((type2)(type)res[1] << (prec));                     \
660   res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec);     \
661   *o = CLAMP (res[0], -(limit), (limit) - 1);                   \
662 }
663 
664 INNER_PRODUCT_INT_LINEAR_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
665 INNER_PRODUCT_INT_LINEAR_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
666 
667 #define INNER_PRODUCT_INT_CUBIC_FUNC(type,type2,prec,limit)     \
668 static inline void                                              \
669 inner_product_##type##_cubic_1_c (type * o, const type * a,     \
670     const type * b, gint len, const type *ic, gint bstride)     \
671 {                                                               \
672   gint i;                                                       \
673   type2 res[4] = { 0, 0, 0, 0 };                                \
674   const type *c[4] = {(type*)((gint8*)b + 0*bstride),           \
675                       (type*)((gint8*)b + 1*bstride),           \
676                       (type*)((gint8*)b + 2*bstride),           \
677                       (type*)((gint8*)b + 3*bstride)};          \
678                                                                 \
679   for (i = 0; i < len; i++) {                                   \
680     res[0] += (type2) a[i] * (type2) c[0][i];                   \
681     res[1] += (type2) a[i] * (type2) c[1][i];                   \
682     res[2] += (type2) a[i] * (type2) c[2][i];                   \
683     res[3] += (type2) a[i] * (type2) c[3][i];                   \
684   }                                                             \
685   res[0] = (type2)(type)(res[0] >> (prec)) * (type2) ic[0] +    \
686            (type2)(type)(res[1] >> (prec)) * (type2) ic[1] +    \
687            (type2)(type)(res[2] >> (prec)) * (type2) ic[2] +    \
688            (type2)(type)(res[3] >> (prec)) * (type2) ic[3];     \
689   res[0] = (res[0] + ((type2)1 << ((prec) - 1))) >> (prec);     \
690   *o = CLAMP (res[0], -(limit), (limit) - 1);                   \
691 }
692 
693 INNER_PRODUCT_INT_CUBIC_FUNC (gint16, gint32, PRECISION_S16, (gint32) 1 << 15);
694 INNER_PRODUCT_INT_CUBIC_FUNC (gint32, gint64, PRECISION_S32, (gint64) 1 << 31);
695 
696 #define INNER_PRODUCT_FLOAT_FULL_FUNC(type)                     \
697 static inline void                                              \
698 inner_product_##type##_full_1_c (type * o, const type * a,      \
699     const type * b, gint len, const type *ic, gint bstride)     \
700 {                                                               \
701   gint i;                                                       \
702   type res[4] = { 0.0, 0.0, 0.0, 0.0 };                         \
703                                                                 \
704   for (i = 0; i < len; i += 4) {                                \
705     res[0] += a[i + 0] * b[i + 0];                              \
706     res[1] += a[i + 1] * b[i + 1];                              \
707     res[2] += a[i + 2] * b[i + 2];                              \
708     res[3] += a[i + 3] * b[i + 3];                              \
709   }                                                             \
710   *o = res[0] + res[1] + res[2] + res[3];                       \
711 }
712 
713 INNER_PRODUCT_FLOAT_FULL_FUNC (gfloat);
714 INNER_PRODUCT_FLOAT_FULL_FUNC (gdouble);
715 
716 #define INNER_PRODUCT_FLOAT_LINEAR_FUNC(type)                   \
717 static inline void                                              \
718 inner_product_##type##_linear_1_c (type * o, const type * a,    \
719     const type * b, gint len, const type *ic, gint bstride)     \
720 {                                                               \
721   gint i;                                                       \
722   type res[4] = { 0.0, 0.0, 0.0, 0.0 };                         \
723   const type *c[2] = {(type*)((gint8*)b + 0*bstride),           \
724                       (type*)((gint8*)b + 1*bstride)};          \
725                                                                 \
726   for (i = 0; i < len; i += 2) {                                \
727     res[0] += a[i + 0] * c[0][i + 0];                           \
728     res[1] += a[i + 0] * c[1][i + 0];                           \
729     res[2] += a[i + 1] * c[0][i + 1];                           \
730     res[3] += a[i + 1] * c[1][i + 1];                           \
731   }                                                             \
732   res[0] += res[2];                                             \
733   res[1] += res[3];                                             \
734   *o = (res[0] - res[1]) * ic[0] + res[1];                      \
735 }
736 INNER_PRODUCT_FLOAT_LINEAR_FUNC (gfloat);
737 INNER_PRODUCT_FLOAT_LINEAR_FUNC (gdouble);
738 
739 #define INNER_PRODUCT_FLOAT_CUBIC_FUNC(type)                    \
740 static inline void                                              \
741 inner_product_##type##_cubic_1_c (type * o, const type * a,     \
742     const type * b, gint len, const type *ic, gint bstride)     \
743 {                                                               \
744   gint i;                                                       \
745   type res[4] = { 0.0, 0.0, 0.0, 0.0 };                         \
746   const type *c[4] = {(type*)((gint8*)b + 0*bstride),           \
747                       (type*)((gint8*)b + 1*bstride),           \
748                       (type*)((gint8*)b + 2*bstride),           \
749                       (type*)((gint8*)b + 3*bstride)};          \
750                                                                 \
751   for (i = 0; i < len; i++) {                                   \
752     res[0] += a[i] * c[0][i];                                   \
753     res[1] += a[i] * c[1][i];                                   \
754     res[2] += a[i] * c[2][i];                                   \
755     res[3] += a[i] * c[3][i];                                   \
756   }                                                             \
757   *o = res[0] * ic[0] + res[1] * ic[1] +                        \
758        res[2] * ic[2] + res[3] * ic[3];                         \
759 }
760 INNER_PRODUCT_FLOAT_CUBIC_FUNC (gfloat);
761 INNER_PRODUCT_FLOAT_CUBIC_FUNC (gdouble);
762 
763 MAKE_RESAMPLE_FUNC_STATIC (gint16, nearest, 1, c);
764 MAKE_RESAMPLE_FUNC_STATIC (gint32, nearest, 1, c);
765 MAKE_RESAMPLE_FUNC_STATIC (gfloat, nearest, 1, c);
766 MAKE_RESAMPLE_FUNC_STATIC (gdouble, nearest, 1, c);
767 
768 MAKE_RESAMPLE_FUNC_STATIC (gint16, full, 1, c);
769 MAKE_RESAMPLE_FUNC_STATIC (gint32, full, 1, c);
770 MAKE_RESAMPLE_FUNC_STATIC (gfloat, full, 1, c);
771 MAKE_RESAMPLE_FUNC_STATIC (gdouble, full, 1, c);
772 
773 MAKE_RESAMPLE_FUNC_STATIC (gint16, linear, 1, c);
774 MAKE_RESAMPLE_FUNC_STATIC (gint32, linear, 1, c);
775 MAKE_RESAMPLE_FUNC_STATIC (gfloat, linear, 1, c);
776 MAKE_RESAMPLE_FUNC_STATIC (gdouble, linear, 1, c);
777 
778 MAKE_RESAMPLE_FUNC_STATIC (gint16, cubic, 1, c);
779 MAKE_RESAMPLE_FUNC_STATIC (gint32, cubic, 1, c);
780 MAKE_RESAMPLE_FUNC_STATIC (gfloat, cubic, 1, c);
781 MAKE_RESAMPLE_FUNC_STATIC (gdouble, cubic, 1, c);
782 
783 static ResampleFunc resample_funcs[] = {
784   resample_gint16_nearest_1_c,
785   resample_gint32_nearest_1_c,
786   resample_gfloat_nearest_1_c,
787   resample_gdouble_nearest_1_c,
788 
789   resample_gint16_full_1_c,
790   resample_gint32_full_1_c,
791   resample_gfloat_full_1_c,
792   resample_gdouble_full_1_c,
793 
794   resample_gint16_linear_1_c,
795   resample_gint32_linear_1_c,
796   resample_gfloat_linear_1_c,
797   resample_gdouble_linear_1_c,
798 
799   resample_gint16_cubic_1_c,
800   resample_gint32_cubic_1_c,
801   resample_gfloat_cubic_1_c,
802   resample_gdouble_cubic_1_c,
803 };
804 
805 #define resample_gint16_nearest_1 resample_funcs[0]
806 #define resample_gint32_nearest_1 resample_funcs[1]
807 #define resample_gfloat_nearest_1 resample_funcs[2]
808 #define resample_gdouble_nearest_1 resample_funcs[3]
809 
810 #define resample_gint16_full_1 resample_funcs[4]
811 #define resample_gint32_full_1 resample_funcs[5]
812 #define resample_gfloat_full_1 resample_funcs[6]
813 #define resample_gdouble_full_1 resample_funcs[7]
814 
815 #define resample_gint16_linear_1 resample_funcs[8]
816 #define resample_gint32_linear_1 resample_funcs[9]
817 #define resample_gfloat_linear_1 resample_funcs[10]
818 #define resample_gdouble_linear_1 resample_funcs[11]
819 
820 #define resample_gint16_cubic_1 resample_funcs[12]
821 #define resample_gint32_cubic_1 resample_funcs[13]
822 #define resample_gfloat_cubic_1 resample_funcs[14]
823 #define resample_gdouble_cubic_1 resample_funcs[15]
824 
825 #if defined HAVE_ORC && !defined DISABLE_ORC
826 # if defined (HAVE_ARM_NEON)
827 #  define CHECK_NEON
828 #  include "audio-resampler-neon.h"
829 # endif
830 # if defined (__i386__) || defined (__x86_64__)
831 #  define CHECK_X86
832 #  include "audio-resampler-x86.h"
833 # endif
834 #endif
835 
836 static void
audio_resampler_init(void)837 audio_resampler_init (void)
838 {
839   static gsize init_gonce = 0;
840 
841   if (g_once_init_enter (&init_gonce)) {
842 
843     GST_DEBUG_CATEGORY_INIT (audio_resampler_debug, "audio-resampler", 0,
844         "audio-resampler object");
845 
846 #if defined HAVE_ORC && !defined DISABLE_ORC
847     orc_init ();
848     {
849       OrcTarget *target = orc_target_get_default ();
850       gint i;
851 
852       if (target) {
853         const gchar *name;
854         unsigned int flags = orc_target_get_default_flags (target);
855 
856         for (i = -1; i < 32; ++i) {
857           if (i == -1) {
858             name = orc_target_get_name (target);
859             GST_DEBUG ("target %s, default flags %08x", name, flags);
860           } else if (flags & (1U << i)) {
861             name = orc_target_get_flag_name (target, i);
862             GST_DEBUG ("target flag %s", name);
863           } else
864             name = NULL;
865 
866           if (name) {
867 #ifdef CHECK_X86
868             audio_resampler_check_x86 (name);
869 #endif
870 #ifdef CHECK_NEON
871             audio_resampler_check_neon (name);
872 #endif
873           }
874         }
875       }
876     }
877 #endif
878     g_once_init_leave (&init_gonce, 1);
879   }
880 }
881 
882 #define MAKE_DEINTERLEAVE_FUNC(type)                                    \
883 static void                                                             \
884 deinterleave_ ##type (GstAudioResampler * resampler, gpointer sbuf[],   \
885     gpointer in[], gsize in_frames)                                     \
886 {                                                                       \
887   gint i, c, channels = resampler->channels;                            \
888   gsize samples_avail = resampler->samples_avail;                       \
889   for (c = 0; c < channels; c++) {                                      \
890     type *s = (type *) sbuf[c] + samples_avail;                         \
891     if (G_UNLIKELY (in == NULL)) {                                      \
892       for (i = 0; i < in_frames; i++)                                   \
893         s[i] = 0;                                                       \
894     } else {                                                            \
895       type *ip = (type *) in[0] + c;                                    \
896       for (i = 0; i < in_frames; i++, ip += channels)                   \
897         s[i] = *ip;                                                     \
898     }                                                                   \
899   }                                                                     \
900 }
901 
902 MAKE_DEINTERLEAVE_FUNC (gint16);
903 MAKE_DEINTERLEAVE_FUNC (gint32);
904 MAKE_DEINTERLEAVE_FUNC (gfloat);
905 MAKE_DEINTERLEAVE_FUNC (gdouble);
906 
907 static DeinterleaveFunc deinterleave_funcs[] = {
908   deinterleave_gint16,
909   deinterleave_gint32,
910   deinterleave_gfloat,
911   deinterleave_gdouble
912 };
913 
914 static void
copy_func(GstAudioResampler * resampler,gpointer sbuf[],gpointer in[],gsize in_frames)915 copy_func (GstAudioResampler * resampler, gpointer sbuf[],
916     gpointer in[], gsize in_frames)
917 {
918   gint c, channels = resampler->channels;
919   gsize samples_avail = resampler->samples_avail;
920   for (c = 0; c < channels; c++) {
921     guint8 *s = ((guint8 *) sbuf[c]) + (samples_avail * resampler->bps);
922     if (G_UNLIKELY (in == NULL)) {
923       memset (s, 0, in_frames * resampler->bps);
924     } else {
925       memcpy (s, in[c], in_frames * resampler->bps);
926     }
927   }
928 }
929 
930 static void
calculate_kaiser_params(GstAudioResampler * resampler)931 calculate_kaiser_params (GstAudioResampler * resampler)
932 {
933   gdouble A, B, dw, tr_bw, Fc;
934   gint n;
935   const KaiserQualityMap *q = &kaiser_qualities[DEFAULT_QUALITY];
936 
937   /* default cutoff */
938   Fc = q->cutoff;
939   if (resampler->out_rate < resampler->in_rate)
940     Fc *= q->downsample_cutoff_factor;
941 
942   Fc = GET_OPT_CUTOFF (resampler->options, Fc);
943   A = GET_OPT_STOP_ATTENUATION (resampler->options, q->stopband_attenuation);
944   tr_bw =
945       GET_OPT_TRANSITION_BANDWIDTH (resampler->options,
946       q->transition_bandwidth);
947 
948   GST_LOG ("Fc %f, A %f, tr_bw %f", Fc, A, tr_bw);
949 
950   /* calculate Beta */
951   if (A > 50)
952     B = 0.1102 * (A - 8.7);
953   else if (A >= 21)
954     B = 0.5842 * pow (A - 21, 0.4) + 0.07886 * (A - 21);
955   else
956     B = 0.0;
957   /* calculate transition width in radians */
958   dw = 2 * G_PI * (tr_bw);
959   /* order of the filter */
960   n = (A - 8.0) / (2.285 * dw);
961 
962   resampler->kaiser_beta = B;
963   resampler->n_taps = n + 1;
964   resampler->cutoff = Fc;
965 
966   GST_LOG ("using Beta %f n_taps %d cutoff %f", resampler->kaiser_beta,
967       resampler->n_taps, resampler->cutoff);
968 }
969 
970 static void
alloc_taps_mem(GstAudioResampler * resampler,gint bps,gint n_taps,gint n_phases)971 alloc_taps_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
972     gint n_phases)
973 {
974   if (resampler->alloc_taps >= n_taps && resampler->alloc_phases >= n_phases)
975     return;
976 
977   GST_DEBUG ("allocate bps %d n_taps %d n_phases %d", bps, n_taps, n_phases);
978 
979   resampler->tmp_taps =
980       g_realloc_n (resampler->tmp_taps, n_taps, sizeof (gdouble));
981 
982   resampler->taps_stride = GST_ROUND_UP_32 (bps * (n_taps + TAPS_OVERREAD));
983 
984   g_free (resampler->taps_mem);
985   resampler->taps_mem =
986       g_malloc0 (n_phases * resampler->taps_stride + ALIGN - 1);
987   resampler->taps = MEM_ALIGN ((gint8 *) resampler->taps_mem, ALIGN);
988   resampler->alloc_taps = n_taps;
989   resampler->alloc_phases = n_phases;
990 }
991 
992 static void
alloc_cache_mem(GstAudioResampler * resampler,gint bps,gint n_taps,gint n_phases)993 alloc_cache_mem (GstAudioResampler * resampler, gint bps, gint n_taps,
994     gint n_phases)
995 {
996   gsize phases_size;
997 
998   resampler->tmp_taps =
999       g_realloc_n (resampler->tmp_taps, n_taps, sizeof (gdouble));
1000 
1001   resampler->cached_taps_stride =
1002       GST_ROUND_UP_32 (bps * (n_taps + TAPS_OVERREAD));
1003 
1004   phases_size = sizeof (gpointer) * n_phases;
1005 
1006   g_free (resampler->cached_taps_mem);
1007   resampler->cached_taps_mem =
1008       g_malloc0 (phases_size + n_phases * resampler->cached_taps_stride +
1009       ALIGN - 1);
1010   resampler->cached_taps =
1011       MEM_ALIGN ((gint8 *) resampler->cached_taps_mem + phases_size, ALIGN);
1012   resampler->cached_phases = resampler->cached_taps_mem;
1013 }
1014 
1015 static void
setup_functions(GstAudioResampler * resampler)1016 setup_functions (GstAudioResampler * resampler)
1017 {
1018   gint index, fidx;
1019 
1020   index = resampler->format_index;
1021 
1022   if (resampler->in_rate == resampler->out_rate)
1023     resampler->resample = resample_funcs[index];
1024   else {
1025     switch (resampler->filter_interpolation) {
1026       default:
1027       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE:
1028         fidx = 0;
1029         break;
1030       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1031         GST_DEBUG ("using linear interpolation for filter coefficients");
1032         fidx = 0;
1033         break;
1034       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:
1035         GST_DEBUG ("using cubic interpolation for filter coefficients");
1036         fidx = 4;
1037         break;
1038     }
1039     GST_DEBUG ("using filter interpolate function %d", index + fidx);
1040     resampler->interpolate = interpolate_funcs[index + fidx];
1041 
1042     switch (resampler->method) {
1043       case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
1044         GST_DEBUG ("using nearest filter function");
1045         break;
1046       default:
1047         index += 4;
1048         switch (resampler->filter_mode) {
1049           default:
1050           case GST_AUDIO_RESAMPLER_FILTER_MODE_FULL:
1051             GST_DEBUG ("using full filter function");
1052             break;
1053           case GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED:
1054             index += 4 + fidx;
1055             GST_DEBUG ("using interpolated filter function");
1056             break;
1057         }
1058         break;
1059     }
1060     GST_DEBUG ("using resample function %d", index);
1061     resampler->resample = resample_funcs[index];
1062   }
1063 }
1064 
1065 static void
resampler_calculate_taps(GstAudioResampler * resampler)1066 resampler_calculate_taps (GstAudioResampler * resampler)
1067 {
1068   gint bps;
1069   gint n_taps, oversample;
1070   gint in_rate, out_rate;
1071   gboolean scale = TRUE, sinc_table = FALSE;
1072   GstAudioResamplerFilterInterpolation filter_interpolation;
1073 
1074   switch (resampler->method) {
1075     case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
1076       resampler->n_taps = 2;
1077       scale = FALSE;
1078       break;
1079     case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
1080       resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 2);
1081       break;
1082     case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
1083       resampler->n_taps = GET_OPT_N_TAPS (resampler->options, 4);
1084       resampler->b = GET_OPT_CUBIC_B (resampler->options);
1085       resampler->c = GET_OPT_CUBIC_C (resampler->options);;
1086       break;
1087     case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
1088     {
1089       const BlackmanQualityMap *q = &blackman_qualities[DEFAULT_QUALITY];
1090       resampler->n_taps = GET_OPT_N_TAPS (resampler->options, q->n_taps);
1091       resampler->cutoff = GET_OPT_CUTOFF (resampler->options, q->cutoff);
1092       sinc_table = TRUE;
1093       break;
1094     }
1095     case GST_AUDIO_RESAMPLER_METHOD_KAISER:
1096       calculate_kaiser_params (resampler);
1097       sinc_table = TRUE;
1098       break;
1099   }
1100 
1101   in_rate = resampler->in_rate;
1102   out_rate = resampler->out_rate;
1103 
1104   if (out_rate < in_rate && scale) {
1105     resampler->cutoff = resampler->cutoff * out_rate / in_rate;
1106     resampler->n_taps =
1107         gst_util_uint64_scale_int (resampler->n_taps, in_rate, out_rate);
1108   }
1109 
1110   if (sinc_table) {
1111     resampler->n_taps = GST_ROUND_UP_8 (resampler->n_taps);
1112     resampler->filter_mode = GET_OPT_FILTER_MODE (resampler->options);
1113     resampler->filter_threshold =
1114         GET_OPT_FILTER_MODE_THRESHOLD (resampler->options);
1115     filter_interpolation = GET_OPT_FILTER_INTERPOLATION (resampler->options);
1116 
1117   } else {
1118     resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
1119     filter_interpolation = GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE;
1120   }
1121 
1122   /* calculate oversampling for interpolated filter */
1123   if (filter_interpolation != GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
1124     gint mult = 2;
1125 
1126     oversample = GET_OPT_FILTER_OVERSAMPLE (resampler->options);
1127     while (oversample > 1) {
1128       if (mult * out_rate >= in_rate)
1129         break;
1130 
1131       mult *= 2;
1132       oversample >>= 1;
1133     }
1134 
1135     switch (filter_interpolation) {
1136       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1137         oversample *= 11;
1138         break;
1139       default:
1140         break;
1141     }
1142   } else {
1143     oversample = 1;
1144   }
1145   resampler->oversample = oversample;
1146 
1147   n_taps = resampler->n_taps;
1148   bps = resampler->bps;
1149 
1150   GST_LOG ("using n_taps %d cutoff %f oversample %d", n_taps, resampler->cutoff,
1151       oversample);
1152 
1153   if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_AUTO) {
1154     if (out_rate <= oversample
1155         && !(resampler->flags & GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE)) {
1156       /* don't interpolate if we need to calculate at least the same amount
1157        * of filter coefficients than the full table case */
1158       resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
1159       GST_DEBUG ("automatically selected full filter, %d <= %d", out_rate,
1160           oversample);
1161     } else if (bps * n_taps * out_rate < resampler->filter_threshold) {
1162       /* switch to full filter when memory is below threshold */
1163       resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_FULL;
1164       GST_DEBUG ("automatically selected full filter, memory %d <= %d",
1165           bps * n_taps * out_rate, resampler->filter_threshold);
1166     } else {
1167       GST_DEBUG ("automatically selected interpolated filter");
1168       resampler->filter_mode = GST_AUDIO_RESAMPLER_FILTER_MODE_INTERPOLATED;
1169     }
1170   }
1171   /* interpolated table but no interpolation given, assume default */
1172   if (resampler->filter_mode != GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
1173       filter_interpolation == GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE)
1174     filter_interpolation = DEFAULT_OPT_FILTER_INTERPOLATION;
1175 
1176   resampler->filter_interpolation = filter_interpolation;
1177 
1178   if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL &&
1179       resampler->method != GST_AUDIO_RESAMPLER_METHOD_NEAREST) {
1180     GST_DEBUG ("setting up filter cache");
1181     resampler->n_phases = out_rate;
1182     alloc_cache_mem (resampler, bps, n_taps, out_rate);
1183   }
1184 
1185   if (resampler->filter_interpolation !=
1186       GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_NONE) {
1187     gint i, isize;
1188     gdouble x;
1189     gpointer taps;
1190 
1191     switch (resampler->filter_interpolation) {
1192       default:
1193       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_LINEAR:
1194         GST_DEBUG ("using linear interpolation to build filter");
1195         isize = 2;
1196         break;
1197       case GST_AUDIO_RESAMPLER_FILTER_INTERPOLATION_CUBIC:
1198         GST_DEBUG ("using cubic interpolation to build filter");
1199         isize = 4;
1200         break;
1201     }
1202 
1203     alloc_taps_mem (resampler, bps, n_taps, oversample + isize);
1204 
1205     for (i = 0; i < oversample + isize; i++) {
1206       x = -(n_taps / 2) + i / (gdouble) oversample;
1207       taps = (gint8 *) resampler->taps + i * resampler->taps_stride;
1208       make_taps (resampler, taps, x, n_taps);
1209     }
1210   }
1211 }
1212 
1213 #define PRINT_TAPS(type,print)                          \
1214 G_STMT_START {                                          \
1215   type sum = 0.0, *taps;                                \
1216   type icoeff[4];                                       \
1217   gint samp_index = 0, samp_phase = i;                  \
1218                                                         \
1219   taps = get_taps_##type##_full (resampler, &samp_index,\
1220       &samp_phase, icoeff);                             \
1221                                                         \
1222   for (j = 0; j < n_taps; j++) {                        \
1223     type tap = taps[j];                                 \
1224     fprintf (stderr, "\t%" print " ", tap);             \
1225     sum += tap;                                         \
1226   }                                                     \
1227   fprintf (stderr, "\t: sum %" print "\n", sum);        \
1228 } G_STMT_END
1229 
1230 static void
resampler_dump(GstAudioResampler * resampler)1231 resampler_dump (GstAudioResampler * resampler)
1232 {
1233 #if 0
1234   gint i, n_taps, out_rate;
1235   gint64 a;
1236 
1237   out_rate = resampler->out_rate;
1238   n_taps = resampler->n_taps;
1239 
1240   fprintf (stderr, "out size %d, max taps %d\n", out_rate, n_taps);
1241 
1242   a = g_get_monotonic_time ();
1243 
1244   for (i = 0; i < out_rate; i++) {
1245     gint j;
1246 
1247     //fprintf (stderr, "%u: %d %d\t ", i, t->sample_inc, t->next_phase);
1248     switch (resampler->format) {
1249       case GST_AUDIO_FORMAT_F64:
1250         PRINT_TAPS (gdouble, "f");
1251         break;
1252       case GST_AUDIO_FORMAT_F32:
1253         PRINT_TAPS (gfloat, "f");
1254         break;
1255       case GST_AUDIO_FORMAT_S32:
1256         PRINT_TAPS (gint32, "d");
1257         break;
1258       case GST_AUDIO_FORMAT_S16:
1259         PRINT_TAPS (gint16, "d");
1260         break;
1261       default:
1262         break;
1263     }
1264   }
1265   fprintf (stderr, "time %" G_GUINT64_FORMAT "\n", g_get_monotonic_time () - a);
1266 #endif
1267 }
1268 
1269 /**
1270  * gst_audio_resampler_options_set_quality:
1271  * @method: a #GstAudioResamplerMethod
1272  * @quality: the quality
1273  * @in_rate: the input rate
1274  * @out_rate: the output rate
1275  * @options: a #GstStructure
1276  *
1277  * Set the parameters for resampling from @in_rate to @out_rate using @method
1278  * for @quality in @options.
1279  */
1280 void
gst_audio_resampler_options_set_quality(GstAudioResamplerMethod method,guint quality,gint in_rate,gint out_rate,GstStructure * options)1281 gst_audio_resampler_options_set_quality (GstAudioResamplerMethod method,
1282     guint quality, gint in_rate, gint out_rate, GstStructure * options)
1283 {
1284   g_return_if_fail (options != NULL);
1285   g_return_if_fail (quality <= GST_AUDIO_RESAMPLER_QUALITY_MAX);
1286   g_return_if_fail (in_rate > 0 && out_rate > 0);
1287 
1288   switch (method) {
1289     case GST_AUDIO_RESAMPLER_METHOD_NEAREST:
1290       break;
1291     case GST_AUDIO_RESAMPLER_METHOD_LINEAR:
1292       gst_structure_set (options,
1293           GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 2, NULL);
1294       break;
1295     case GST_AUDIO_RESAMPLER_METHOD_CUBIC:
1296       gst_structure_set (options,
1297           GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, 4,
1298           GST_AUDIO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_B,
1299           GST_AUDIO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, DEFAULT_OPT_CUBIC_C,
1300           NULL);
1301       break;
1302     case GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL:
1303     {
1304       const BlackmanQualityMap *map = &blackman_qualities[quality];
1305       gst_structure_set (options,
1306           GST_AUDIO_RESAMPLER_OPT_N_TAPS, G_TYPE_INT, map->n_taps,
1307           GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, map->cutoff, NULL);
1308       break;
1309     }
1310     case GST_AUDIO_RESAMPLER_METHOD_KAISER:
1311     {
1312       const KaiserQualityMap *map = &kaiser_qualities[quality];
1313       gdouble cutoff;
1314 
1315       cutoff = map->cutoff;
1316       if (out_rate < in_rate)
1317         cutoff *= map->downsample_cutoff_factor;
1318 
1319       gst_structure_set (options,
1320           GST_AUDIO_RESAMPLER_OPT_CUTOFF, G_TYPE_DOUBLE, cutoff,
1321           GST_AUDIO_RESAMPLER_OPT_STOP_ATTENUATION, G_TYPE_DOUBLE,
1322           map->stopband_attenuation,
1323           GST_AUDIO_RESAMPLER_OPT_TRANSITION_BANDWIDTH, G_TYPE_DOUBLE,
1324           map->transition_bandwidth, NULL);
1325       break;
1326     }
1327   }
1328   gst_structure_set (options,
1329       GST_AUDIO_RESAMPLER_OPT_FILTER_OVERSAMPLE, G_TYPE_INT,
1330       oversample_qualities[quality], NULL);
1331 }
1332 
1333 /**
1334  * gst_audio_resampler_new:
1335  * @method: a #GstAudioResamplerMethod
1336  * @flags: #GstAudioResamplerFlags
1337  * @format: the #GstAudioFormat
1338  * @channels: the number of channels
1339  * @in_rate: input rate
1340  * @out_rate: output rate
1341  * @options: extra options
1342  *
1343  * Make a new resampler.
1344  *
1345  * Returns: (skip) (transfer full): The new #GstAudioResampler, or
1346  * %NULL on failure.
1347  */
1348 GstAudioResampler *
gst_audio_resampler_new(GstAudioResamplerMethod method,GstAudioResamplerFlags flags,GstAudioFormat format,gint channels,gint in_rate,gint out_rate,GstStructure * options)1349 gst_audio_resampler_new (GstAudioResamplerMethod method,
1350     GstAudioResamplerFlags flags,
1351     GstAudioFormat format, gint channels,
1352     gint in_rate, gint out_rate, GstStructure * options)
1353 {
1354   gboolean non_interleaved_in, non_interleaved_out;
1355   GstAudioResampler *resampler;
1356   const GstAudioFormatInfo *info;
1357   GstStructure *def_options = NULL;
1358 
1359   g_return_val_if_fail (method >= GST_AUDIO_RESAMPLER_METHOD_NEAREST
1360       && method <= GST_AUDIO_RESAMPLER_METHOD_KAISER, NULL);
1361   g_return_val_if_fail (format == GST_AUDIO_FORMAT_S16 ||
1362       format == GST_AUDIO_FORMAT_S32 || format == GST_AUDIO_FORMAT_F32 ||
1363       format == GST_AUDIO_FORMAT_F64, NULL);
1364   g_return_val_if_fail (channels > 0, NULL);
1365   g_return_val_if_fail (in_rate > 0, NULL);
1366   g_return_val_if_fail (out_rate > 0, NULL);
1367 
1368   audio_resampler_init ();
1369 
1370   resampler = g_slice_new0 (GstAudioResampler);
1371   resampler->method = method;
1372   resampler->flags = flags;
1373   resampler->format = format;
1374   resampler->channels = channels;
1375 
1376   switch (format) {
1377     case GST_AUDIO_FORMAT_S16:
1378       resampler->format_index = 0;
1379       break;
1380     case GST_AUDIO_FORMAT_S32:
1381       resampler->format_index = 1;
1382       break;
1383     case GST_AUDIO_FORMAT_F32:
1384       resampler->format_index = 2;
1385       break;
1386     case GST_AUDIO_FORMAT_F64:
1387       resampler->format_index = 3;
1388       break;
1389     default:
1390       g_assert_not_reached ();
1391       break;
1392   }
1393 
1394   info = gst_audio_format_get_info (format);
1395   resampler->bps = GST_AUDIO_FORMAT_INFO_WIDTH (info) / 8;
1396   resampler->sbuf = g_malloc0 (sizeof (gpointer) * channels);
1397 
1398   non_interleaved_in =
1399       (resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED_IN);
1400   non_interleaved_out =
1401       (resampler->flags & GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED_OUT);
1402 
1403   /* we resample each channel separately */
1404   resampler->blocks = resampler->channels;
1405   resampler->inc = 1;
1406   resampler->ostride = non_interleaved_out ? 1 : resampler->channels;
1407   resampler->deinterleave = non_interleaved_in ?
1408       copy_func : deinterleave_funcs[resampler->format_index];
1409   resampler->convert_taps = convert_taps_funcs[resampler->format_index];
1410 
1411   GST_DEBUG ("method %d, bps %d, channels %d", method, resampler->bps,
1412       resampler->channels);
1413 
1414   if (options == NULL) {
1415     options = def_options =
1416         gst_structure_new_empty ("GstAudioResampler.options");
1417     gst_audio_resampler_options_set_quality (DEFAULT_RESAMPLER_METHOD,
1418         GST_AUDIO_RESAMPLER_QUALITY_DEFAULT, in_rate, out_rate, options);
1419   }
1420 
1421   gst_audio_resampler_update (resampler, in_rate, out_rate, options);
1422   gst_audio_resampler_reset (resampler);
1423 
1424   if (def_options)
1425     gst_structure_free (def_options);
1426 
1427   return resampler;
1428 }
1429 
1430 /* make the buffers to hold the (deinterleaved) samples */
1431 static inline gpointer *
get_sample_bufs(GstAudioResampler * resampler,gsize need)1432 get_sample_bufs (GstAudioResampler * resampler, gsize need)
1433 {
1434   if (G_LIKELY (resampler->samples_len < need)) {
1435     gint c, blocks = resampler->blocks;
1436     gsize bytes, to_move = 0;
1437     gint8 *ptr, *samples;
1438 
1439     GST_LOG ("realloc %d -> %d", (gint) resampler->samples_len, (gint) need);
1440 
1441     bytes = GST_ROUND_UP_N (need * resampler->bps * resampler->inc, ALIGN);
1442 
1443     samples = g_malloc0 (blocks * bytes + ALIGN - 1);
1444     ptr = MEM_ALIGN (samples, ALIGN);
1445 
1446     /* if we had some data, move history */
1447     if (resampler->samples_len > 0)
1448       to_move = resampler->samples_avail * resampler->bps * resampler->inc;
1449 
1450     /* set up new pointers */
1451     for (c = 0; c < blocks; c++) {
1452       memcpy (ptr + (c * bytes), resampler->sbuf[c], to_move);
1453       resampler->sbuf[c] = ptr + (c * bytes);
1454     }
1455     g_free (resampler->samples);
1456     resampler->samples = samples;
1457     resampler->samples_len = need;
1458   }
1459   return resampler->sbuf;
1460 }
1461 
1462 /**
1463  * gst_audio_resampler_reset:
1464  * @resampler: a #GstAudioResampler
1465  *
1466  * Reset @resampler to the state it was when it was first created, discarding
1467  * all sample history.
1468  */
1469 void
gst_audio_resampler_reset(GstAudioResampler * resampler)1470 gst_audio_resampler_reset (GstAudioResampler * resampler)
1471 {
1472   g_return_if_fail (resampler != NULL);
1473 
1474   if (resampler->samples) {
1475     gsize bytes;
1476     gint c, blocks, bpf;
1477 
1478     bpf = resampler->bps * resampler->inc;
1479     bytes = (resampler->n_taps / 2) * bpf;
1480     blocks = resampler->blocks;
1481 
1482     for (c = 0; c < blocks; c++)
1483       memset (resampler->sbuf[c], 0, bytes);
1484   }
1485   /* half of the filter is filled with 0 */
1486   resampler->samp_index = 0;
1487   resampler->samples_avail = resampler->n_taps / 2 - 1;
1488 }
1489 
1490 /**
1491  * gst_audio_resampler_update:
1492  * @resampler: a #GstAudioResampler
1493  * @in_rate: new input rate
1494  * @out_rate: new output rate
1495  * @options: new options or %NULL
1496  *
1497  * Update the resampler parameters for @resampler. This function should
1498  * not be called concurrently with any other function on @resampler.
1499  *
1500  * When @in_rate or @out_rate is 0, its value is unchanged.
1501  *
1502  * When @options is %NULL, the previously configured options are reused.
1503  *
1504  * Returns: %TRUE if the new parameters could be set
1505  */
1506 gboolean
gst_audio_resampler_update(GstAudioResampler * resampler,gint in_rate,gint out_rate,GstStructure * options)1507 gst_audio_resampler_update (GstAudioResampler * resampler,
1508     gint in_rate, gint out_rate, GstStructure * options)
1509 {
1510   gint gcd, samp_phase, old_n_taps;
1511   gdouble max_error;
1512 
1513   g_return_val_if_fail (resampler != NULL, FALSE);
1514 
1515   if (in_rate <= 0)
1516     in_rate = resampler->in_rate;
1517   if (out_rate <= 0)
1518     out_rate = resampler->out_rate;
1519 
1520   if (resampler->out_rate > 0) {
1521     GST_INFO ("old phase %d/%d", resampler->samp_phase, resampler->out_rate);
1522     samp_phase =
1523         gst_util_uint64_scale_int (resampler->samp_phase, out_rate,
1524         resampler->out_rate);
1525   } else
1526     samp_phase = 0;
1527 
1528   gcd = gst_util_greatest_common_divisor (in_rate, out_rate);
1529 
1530   max_error = GET_OPT_MAX_PHASE_ERROR (resampler->options);
1531 
1532   if (max_error < 1.0e-8) {
1533     GST_INFO ("using exact phase divider");
1534     gcd = gst_util_greatest_common_divisor (gcd, samp_phase);
1535   } else {
1536     while (gcd > 1) {
1537       gdouble ph1 = (gdouble) samp_phase / out_rate;
1538       gint factor = 2;
1539 
1540       /* reduce the factor until we have a phase error of less than 10% */
1541       gdouble ph2 = (gdouble) (samp_phase / gcd) / (out_rate / gcd);
1542 
1543       if (fabs (ph1 - ph2) < max_error)
1544         break;
1545 
1546       while (gcd % factor != 0)
1547         factor++;
1548       gcd /= factor;
1549 
1550       GST_INFO ("divide by factor %d, gcd %d", factor, gcd);
1551     }
1552   }
1553 
1554   GST_INFO ("phase %d out_rate %d, in_rate %d, gcd %d", samp_phase, out_rate,
1555       in_rate, gcd);
1556 
1557   resampler->samp_phase = samp_phase /= gcd;
1558   resampler->in_rate = in_rate /= gcd;
1559   resampler->out_rate = out_rate /= gcd;
1560 
1561   GST_INFO ("new phase %d/%d", resampler->samp_phase, resampler->out_rate);
1562 
1563   resampler->samp_inc = in_rate / out_rate;
1564   resampler->samp_frac = in_rate % out_rate;
1565 
1566   if (options) {
1567     GST_INFO ("have new options, reconfigure filter");
1568 
1569     if (resampler->options)
1570       gst_structure_free (resampler->options);
1571     resampler->options = gst_structure_copy (options);
1572 
1573     old_n_taps = resampler->n_taps;
1574 
1575     resampler_calculate_taps (resampler);
1576     resampler_dump (resampler);
1577 
1578     if (old_n_taps > 0 && old_n_taps != resampler->n_taps) {
1579       gpointer *sbuf;
1580       gint i, bpf, bytes, soff, doff, diff;
1581 
1582       sbuf = get_sample_bufs (resampler, resampler->n_taps);
1583 
1584       bpf = resampler->bps * resampler->inc;
1585       bytes = resampler->samples_avail * bpf;
1586       soff = doff = resampler->samp_index * bpf;
1587 
1588       diff = ((gint) resampler->n_taps - old_n_taps) / 2;
1589 
1590       GST_DEBUG ("taps %d->%d, %d", old_n_taps, resampler->n_taps, diff);
1591 
1592       if (diff < 0) {
1593         /* diff < 0, decrease taps, adjust source */
1594         soff += -diff * bpf;
1595         bytes -= -diff * bpf;
1596       } else {
1597         /* diff > 0, increase taps, adjust dest */
1598         doff += diff * bpf;
1599       }
1600 
1601       /* now shrink or enlarge the history buffer, when we enlarge we
1602        * just leave the old samples in there. FIXME, probably do something better
1603        * like mirror or fill with zeroes. */
1604       for (i = 0; i < resampler->blocks; i++)
1605         memmove ((gint8 *) sbuf[i] + doff, (gint8 *) sbuf[i] + soff, bytes);
1606 
1607       resampler->samples_avail += diff;
1608     }
1609   } else if (resampler->filter_mode == GST_AUDIO_RESAMPLER_FILTER_MODE_FULL) {
1610     GST_DEBUG ("setting up filter cache");
1611     resampler->n_phases = resampler->out_rate;
1612     alloc_cache_mem (resampler, resampler->bps, resampler->n_taps,
1613         resampler->n_phases);
1614   }
1615   setup_functions (resampler);
1616 
1617   return TRUE;
1618 }
1619 
1620 /**
1621  * gst_audio_resampler_free:
1622  * @resampler: a #GstAudioResampler
1623  *
1624  * Free a previously allocated #GstAudioResampler @resampler.
1625  */
1626 void
gst_audio_resampler_free(GstAudioResampler * resampler)1627 gst_audio_resampler_free (GstAudioResampler * resampler)
1628 {
1629   g_return_if_fail (resampler != NULL);
1630 
1631   g_free (resampler->cached_taps_mem);
1632   g_free (resampler->taps_mem);
1633   g_free (resampler->tmp_taps);
1634   g_free (resampler->samples);
1635   g_free (resampler->sbuf);
1636   if (resampler->options)
1637     gst_structure_free (resampler->options);
1638   g_slice_free (GstAudioResampler, resampler);
1639 }
1640 
1641 /**
1642  * gst_audio_resampler_get_out_frames:
1643  * @resampler: a #GstAudioResampler
1644  * @in_frames: number of input frames
1645  *
1646  * Get the number of output frames that would be currently available when
1647  * @in_frames are given to @resampler.
1648  *
1649  * Returns: The number of frames that would be available after giving
1650  * @in_frames as input to @resampler.
1651  */
1652 gsize
gst_audio_resampler_get_out_frames(GstAudioResampler * resampler,gsize in_frames)1653 gst_audio_resampler_get_out_frames (GstAudioResampler * resampler,
1654     gsize in_frames)
1655 {
1656   gsize need, avail, out;
1657 
1658   g_return_val_if_fail (resampler != NULL, 0);
1659 
1660   need = resampler->n_taps + resampler->samp_index + resampler->skip;
1661   avail = resampler->samples_avail + in_frames;
1662   GST_LOG ("need %d = %d + %d + %d, avail %d = %d + %d", (gint) need,
1663       resampler->n_taps, resampler->samp_index, resampler->skip,
1664       (gint) avail, (gint) resampler->samples_avail, (gint) in_frames);
1665   if (avail < need) {
1666     GST_LOG ("avail %d < need %d", (int) avail, (int) need);
1667     return 0;
1668   }
1669 
1670   out = (avail - need) * resampler->out_rate;
1671   if (out < resampler->samp_phase) {
1672     GST_LOG ("out %d < samp_phase %d", (int) out, (int) resampler->samp_phase);
1673     return 0;
1674   }
1675 
1676   out = ((out - resampler->samp_phase) / resampler->in_rate) + 1;
1677   GST_LOG ("out %d = ((%d * %d - %d) / %d) + 1", (gint) out,
1678       (gint) (avail - need), resampler->out_rate, resampler->samp_phase,
1679       resampler->in_rate);
1680 
1681   return out;
1682 }
1683 
1684 /**
1685  * gst_audio_resampler_get_in_frames:
1686  * @resampler: a #GstAudioResampler
1687  * @out_frames: number of input frames
1688  *
1689  * Get the number of input frames that would currently be needed
1690  * to produce @out_frames from @resampler.
1691  *
1692  * Returns: The number of input frames needed for producing
1693  * @out_frames of data from @resampler.
1694  */
1695 gsize
gst_audio_resampler_get_in_frames(GstAudioResampler * resampler,gsize out_frames)1696 gst_audio_resampler_get_in_frames (GstAudioResampler * resampler,
1697     gsize out_frames)
1698 {
1699   gsize in_frames;
1700 
1701   g_return_val_if_fail (resampler != NULL, 0);
1702 
1703   in_frames =
1704       (resampler->samp_phase +
1705       out_frames * resampler->samp_frac) / resampler->out_rate;
1706   in_frames += out_frames * resampler->samp_inc;
1707 
1708   return in_frames;
1709 }
1710 
1711 /**
1712  * gst_audio_resampler_get_max_latency:
1713  * @resampler: a #GstAudioResampler
1714  *
1715  * Get the maximum number of input samples that the resampler would
1716  * need before producing output.
1717  *
1718  * Returns: the latency of @resampler as expressed in the number of
1719  * frames.
1720  */
1721 gsize
gst_audio_resampler_get_max_latency(GstAudioResampler * resampler)1722 gst_audio_resampler_get_max_latency (GstAudioResampler * resampler)
1723 {
1724   g_return_val_if_fail (resampler != NULL, 0);
1725 
1726   return resampler->n_taps / 2;
1727 }
1728 
1729 /**
1730  * gst_audio_resampler_resample:
1731  * @resampler: a #GstAudioResampler
1732  * @in: input samples
1733  * @in_frames: number of input frames
1734  * @out: output samples
1735  * @out_frames: number of output frames
1736  *
1737  * Perform resampling on @in_frames frames in @in and write @out_frames to @out.
1738  *
1739  * In case the samples are interleaved, @in and @out must point to an
1740  * array with a single element pointing to a block of interleaved samples.
1741  *
1742  * If non-interleaved samples are used, @in and @out must point to an
1743  * array with pointers to memory blocks, one for each channel.
1744  *
1745  * @in may be %NULL, in which case @in_frames of silence samples are pushed
1746  * into the resampler.
1747  *
1748  * This function always produces @out_frames of output and consumes @in_frames of
1749  * input. Use gst_audio_resampler_get_out_frames() and
1750  * gst_audio_resampler_get_in_frames() to make sure @in_frames and @out_frames
1751  * are matching and @in and @out point to enough memory.
1752  */
1753 void
gst_audio_resampler_resample(GstAudioResampler * resampler,gpointer in[],gsize in_frames,gpointer out[],gsize out_frames)1754 gst_audio_resampler_resample (GstAudioResampler * resampler,
1755     gpointer in[], gsize in_frames, gpointer out[], gsize out_frames)
1756 {
1757   gsize samples_avail;
1758   gsize need, consumed;
1759   gpointer *sbuf;
1760 
1761   /* do sample skipping */
1762   if (G_UNLIKELY (resampler->skip >= in_frames)) {
1763     /* we need tp skip all input */
1764     resampler->skip -= in_frames;
1765     return;
1766   }
1767   /* skip the last samples by advancing the sample index */
1768   resampler->samp_index += resampler->skip;
1769 
1770   samples_avail = resampler->samples_avail;
1771 
1772   /* make sure we have enough space to copy our samples */
1773   sbuf = get_sample_bufs (resampler, in_frames + samples_avail);
1774 
1775   /* copy/deinterleave the samples */
1776   resampler->deinterleave (resampler, sbuf, in, in_frames);
1777 
1778   /* update new amount of samples in our buffer */
1779   resampler->samples_avail = samples_avail += in_frames;
1780 
1781   need = resampler->n_taps + resampler->samp_index;
1782   if (G_UNLIKELY (samples_avail < need || out_frames == 0)) {
1783     GST_LOG ("not enough samples to start: need %" G_GSIZE_FORMAT ", avail %"
1784         G_GSIZE_FORMAT ", out %" G_GSIZE_FORMAT, need, samples_avail,
1785         out_frames);
1786     /* not enough samples to start */
1787     return;
1788   }
1789 
1790   /* resample all channels */
1791   resampler->resample (resampler, sbuf, samples_avail, out, out_frames,
1792       &consumed);
1793 
1794   GST_LOG ("in %" G_GSIZE_FORMAT ", avail %" G_GSIZE_FORMAT ", consumed %"
1795       G_GSIZE_FORMAT, in_frames, samples_avail, consumed);
1796 
1797   /* update pointers */
1798   if (G_LIKELY (consumed > 0)) {
1799     gssize left = samples_avail - consumed;
1800     if (left > 0) {
1801       /* we consumed part of our samples */
1802       resampler->samples_avail = left;
1803     } else {
1804       /* we consumed all our samples, empty our buffers */
1805       resampler->samples_avail = 0;
1806       resampler->skip = -left;
1807     }
1808   }
1809 }
1810