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