6359337946815f2f86006805aecbbbfc45497c60
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / audio-converter.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
3  *           (C) 2015 Wim Taymans <wim.taymans@gmail.com>
4  *
5  * audioconverter.c: Convert audio to different audio formats automatically
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <math.h>
28 #include <string.h>
29
30 #include "audio-converter.h"
31 #include "gstaudiopack.h"
32
33 /**
34  * SECTION:audioconverter
35  * @short_description: Generic audio conversion
36  *
37  * <refsect2>
38  * <para>
39  * This object is used to convert audio samples from one format to another.
40  * The object can perform conversion of:
41  * <itemizedlist>
42  *  <listitem><para>
43  *    audio format with optional dithering and noise shaping
44  *  </para></listitem>
45  *  <listitem><para>
46  *    audio samplerate
47  *  </para></listitem>
48  *  <listitem><para>
49  *    audio channels and channel layout
50  *  </para></listitem>
51  * </para>
52  * </refsect2>
53  */
54
55 #ifndef GST_DISABLE_GST_DEBUG
56 #define GST_CAT_DEFAULT ensure_debug_category()
57 static GstDebugCategory *
58 ensure_debug_category (void)
59 {
60   static gsize cat_gonce = 0;
61
62   if (g_once_init_enter (&cat_gonce)) {
63     gsize cat_done;
64
65     cat_done = (gsize) _gst_debug_category_new ("audio-converter", 0,
66         "audio-converter object");
67
68     g_once_init_leave (&cat_gonce, cat_done);
69   }
70
71   return (GstDebugCategory *) cat_gonce;
72 }
73 #else
74 #define ensure_debug_category() /* NOOP */
75 #endif /* GST_DISABLE_GST_DEBUG */
76
77 typedef struct _AudioChain AudioChain;
78
79 typedef void (*AudioConvertFunc) (gpointer dst, const gpointer src, gint count);
80 typedef gboolean (*AudioConvertSamplesFunc) (GstAudioConverter * convert,
81     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
82     gpointer out[], gsize out_frames);
83
84 /*                           int/int    int/float  float/int float/float
85  *
86  *  unpack                     S32          S32         F64       F64
87  *  convert                               S32->F64
88  *  channel mix                S32          F64         F64       F64
89  *  convert                                           F64->S32
90  *  quantize                   S32                      S32
91  *  pack                       S32          F64         S32       F64
92  *
93  *
94  *  interleave
95  *  deinterleave
96  *  resample
97  */
98 struct _GstAudioConverter
99 {
100   GstAudioInfo in;
101   GstAudioInfo out;
102
103   GstStructure *config;
104
105   GstAudioConverterFlags flags;
106   GstAudioFormat current_format;
107   GstAudioLayout current_layout;
108   gint current_channels;
109
110   gboolean in_writable;
111   gpointer *in_data;
112   gsize in_frames;
113   gpointer *out_data;
114   gsize out_frames;
115
116   /* unpack */
117   gboolean in_default;
118   gboolean unpack_ip;
119   AudioChain *unpack_chain;
120
121   /* convert in */
122   AudioConvertFunc convert_in;
123   AudioChain *convert_in_chain;
124
125   /* channel mix */
126   gboolean mix_passthrough;
127   GstAudioChannelMixer *mix;
128   AudioChain *mix_chain;
129
130   /* resample */
131   GstAudioResampler *resampler;
132   AudioChain *resample_chain;
133
134   /* convert out */
135   AudioConvertFunc convert_out;
136   AudioChain *convert_out_chain;
137
138   /* quant */
139   GstAudioQuantize *quant;
140   AudioChain *quant_chain;
141
142   /* pack */
143   gboolean out_default;
144   AudioChain *pack_chain;
145
146   AudioConvertSamplesFunc convert;
147 };
148
149 typedef gboolean (*AudioChainFunc) (AudioChain * chain, gpointer user_data);
150 typedef gpointer *(*AudioChainAllocFunc) (AudioChain * chain, gsize num_samples,
151     gpointer user_data);
152
153 struct _AudioChain
154 {
155   AudioChain *prev;
156
157   AudioChainFunc make_func;
158   gpointer make_func_data;
159   GDestroyNotify make_func_notify;
160
161   const GstAudioFormatInfo *finfo;
162   gint stride;
163   gint inc;
164   gint blocks;
165
166   gboolean pass_alloc;
167   gboolean allow_ip;
168
169   AudioChainAllocFunc alloc_func;
170   gpointer alloc_data;
171
172   gpointer *tmp;
173   gsize allocated_samples;
174
175   gpointer *samples;
176   gsize num_samples;
177 };
178
179 static AudioChain *
180 audio_chain_new (AudioChain * prev, GstAudioConverter * convert)
181 {
182   AudioChain *chain;
183
184   chain = g_slice_new0 (AudioChain);
185   chain->prev = prev;
186
187   if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
188     chain->inc = 1;
189     chain->blocks = convert->current_channels;
190   } else {
191     chain->inc = convert->current_channels;
192     chain->blocks = 1;
193   }
194   chain->finfo = gst_audio_format_get_info (convert->current_format);
195   chain->stride = (chain->finfo->width * chain->inc) / 8;
196
197   return chain;
198 }
199
200 static void
201 audio_chain_set_make_func (AudioChain * chain,
202     AudioChainFunc make_func, gpointer user_data, GDestroyNotify notify)
203 {
204   chain->make_func = make_func;
205   chain->make_func_data = user_data;
206   chain->make_func_notify = notify;
207 }
208
209 static void
210 audio_chain_free (AudioChain * chain)
211 {
212   GST_LOG ("free chain %p", chain);
213   if (chain->make_func_notify)
214     chain->make_func_notify (chain->make_func_data);
215   g_free (chain->tmp);
216   g_slice_free (AudioChain, chain);
217 }
218
219 static gpointer *
220 audio_chain_alloc_samples (AudioChain * chain, gsize num_samples)
221 {
222   return chain->alloc_func (chain, num_samples, chain->alloc_data);
223 }
224
225 static void
226 audio_chain_set_samples (AudioChain * chain, gpointer * samples,
227     gsize num_samples)
228 {
229   GST_LOG ("set samples %p %" G_GSIZE_FORMAT, samples, num_samples);
230
231   chain->samples = samples;
232   chain->num_samples = num_samples;
233 }
234
235 static gpointer *
236 audio_chain_get_samples (AudioChain * chain, gsize * avail)
237 {
238   gpointer *res;
239
240   while (!chain->samples)
241     chain->make_func (chain, chain->make_func_data);
242
243   res = chain->samples;
244   *avail = chain->num_samples;
245   chain->samples = NULL;
246
247   return res;
248 }
249
250 /*
251 static guint
252 get_opt_uint (GstAudioConverter * convert, const gchar * opt, guint def)
253 {
254   guint res;
255   if (!gst_structure_get_uint (convert->config, opt, &res))
256     res = def;
257   return res;
258 }
259 */
260
261 static gint
262 get_opt_enum (GstAudioConverter * convert, const gchar * opt, GType type,
263     gint def)
264 {
265   gint res;
266   if (!gst_structure_get_enum (convert->config, opt, type, &res))
267     res = def;
268   return res;
269 }
270
271 #define DEFAULT_OPT_RESAMPLER_METHOD GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL
272 #define DEFAULT_OPT_DITHER_METHOD GST_AUDIO_DITHER_NONE
273 #define DEFAULT_OPT_NOISE_SHAPING_METHOD GST_AUDIO_NOISE_SHAPING_NONE
274 #define DEFAULT_OPT_QUANTIZATION 1
275
276 #define GET_OPT_RESAMPLER_METHOD(c) get_opt_enum(c, \
277     GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_AUDIO_RESAMPLER_METHOD, \
278     DEFAULT_OPT_RESAMPLER_METHOD)
279 #define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \
280     GST_AUDIO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_AUDIO_DITHER_METHOD, \
281     DEFAULT_OPT_DITHER_METHOD)
282 #define GET_OPT_NOISE_SHAPING_METHOD(c) get_opt_enum(c, \
283     GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, \
284     DEFAULT_OPT_NOISE_SHAPING_METHOD)
285 #define GET_OPT_QUANTIZATION(c) get_opt_uint(c, \
286     GST_AUDIO_CONVERTER_OPT_QUANTIZATION, DEFAULT_OPT_QUANTIZATION)
287
288 static gboolean
289 copy_config (GQuark field_id, const GValue * value, gpointer user_data)
290 {
291   GstAudioConverter *convert = user_data;
292
293   gst_structure_id_set_value (convert->config, field_id, value);
294
295   return TRUE;
296 }
297
298 /**
299  * gst_audio_converter_update_config:
300  * @convert: a #GstAudioConverter
301  * @in_rate: input rate
302  * @out_rate: output rate
303  * @config: (transfer full) (allow-none): a #GstStructure or %NULL
304  *
305  * Set @in_rate, @out_rate and @config as extra configuration for @convert.
306  *
307  * @in_rate and @out_rate specify the new sample rates of input and output
308  * formats. A value of 0 leaves the sample rate unchanged.
309  *
310  * @config can be %NULL, in which case, the current configuration is not
311  * changed.
312  *
313  * If the parameters in @config can not be set exactly, this function returns
314  * %FALSE and will try to update as much state as possible. The new state can
315  * then be retrieved and refined with gst_audio_converter_get_config().
316  *
317  * Look at the #GST_AUDIO_CONVERTER_OPT_* fields to check valid configuration
318  * option and values.
319  *
320  * Returns: %TRUE when the new parameters could be set
321  */
322 gboolean
323 gst_audio_converter_update_config (GstAudioConverter * convert,
324     gint in_rate, gint out_rate, GstStructure * config)
325 {
326   g_return_val_if_fail (convert != NULL, FALSE);
327   g_return_val_if_fail ((in_rate == 0 && out_rate == 0) ||
328       convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE, FALSE);
329
330   GST_LOG ("new rate %d -> %d", in_rate, out_rate);
331
332   if (in_rate <= 0)
333     in_rate = convert->in.rate;
334   if (out_rate <= 0)
335     out_rate = convert->out.rate;
336
337   convert->in.rate = in_rate;
338   convert->out.rate = out_rate;
339
340   if (convert->resampler)
341     gst_audio_resampler_update (convert->resampler, in_rate, out_rate, config);
342
343   if (config) {
344     gst_structure_foreach (config, copy_config, convert);
345     gst_structure_free (config);
346   }
347
348   return TRUE;
349 }
350
351 /**
352  * gst_audio_converter_get_config:
353  * @convert: a #GstAudioConverter
354  * @in_rate: result input rate
355  * @out_rate: result output rate
356  *
357  * Get the current configuration of @convert.
358  *
359  * Returns: a #GstStructure that remains valid for as long as @convert is valid
360  *   or until gst_audio_converter_update_config() is called.
361  */
362 const GstStructure *
363 gst_audio_converter_get_config (GstAudioConverter * convert,
364     gint * in_rate, gint * out_rate)
365 {
366   g_return_val_if_fail (convert != NULL, NULL);
367
368   if (in_rate)
369     *in_rate = convert->in.rate;
370   if (out_rate)
371     *out_rate = convert->out.rate;
372
373   return convert->config;
374 }
375
376 static gpointer *
377 get_output_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
378 {
379   GstAudioConverter *convert = user_data;
380
381   GST_LOG ("output samples %p %" G_GSIZE_FORMAT, convert->out_data,
382       num_samples);
383
384   return convert->out_data;
385 }
386
387 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
388 #define ALIGN 16
389
390 static gpointer *
391 get_temp_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
392 {
393   if (num_samples > chain->allocated_samples) {
394     gint i;
395     gint8 *s;
396     gsize stride = GST_ROUND_UP_N (num_samples * chain->stride, ALIGN);
397     /* first part contains the pointers, second part the data, add some extra bytes
398      * for alignement */
399     gsize needed = (stride + sizeof (gpointer)) * chain->blocks + ALIGN - 1;
400
401     GST_DEBUG ("alloc samples %d %" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT,
402         chain->stride, num_samples, needed);
403     chain->tmp = g_realloc (chain->tmp, needed);
404     chain->allocated_samples = num_samples;
405
406     /* pointer to the data, make sure it's 16 bytes aligned */
407     s = MEM_ALIGN (&chain->tmp[chain->blocks], ALIGN);
408
409     /* set up the pointers */
410     for (i = 0; i < chain->blocks; i++)
411       chain->tmp[i] = s + i * stride;
412   }
413   GST_LOG ("temp samples %p %" G_GSIZE_FORMAT, chain->tmp, num_samples);
414
415   return chain->tmp;
416 }
417
418 static gboolean
419 do_unpack (AudioChain * chain, gpointer user_data)
420 {
421   GstAudioConverter *convert = user_data;
422   gsize num_samples;
423   gpointer *tmp;
424   gboolean in_writable;
425
426   in_writable = convert->in_writable;
427   num_samples = convert->in_frames;
428
429   if (!chain->allow_ip || !in_writable || !convert->in_default) {
430     gint i;
431
432     if (in_writable && chain->allow_ip) {
433       tmp = convert->in_data;
434       GST_LOG ("unpack in-place %p, %" G_GSIZE_FORMAT, tmp, num_samples);
435     } else {
436       tmp = audio_chain_alloc_samples (chain, num_samples);
437       GST_LOG ("unpack to tmp %p, %" G_GSIZE_FORMAT, tmp, num_samples);
438     }
439
440     if (convert->in_data) {
441       for (i = 0; i < chain->blocks; i++) {
442         if (convert->in_default) {
443           GST_LOG ("copy %p, %p, %" G_GSIZE_FORMAT, tmp[i], convert->in_data[i],
444               num_samples);
445           memcpy (tmp[i], convert->in_data[i], num_samples * chain->stride);
446         } else {
447           GST_LOG ("unpack %p, %p, %" G_GSIZE_FORMAT, tmp[i],
448               convert->in_data[i], num_samples);
449           convert->in.finfo->unpack_func (convert->in.finfo,
450               GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE, tmp[i], convert->in_data[i],
451               num_samples * chain->inc);
452         }
453       }
454     } else {
455       for (i = 0; i < chain->blocks; i++) {
456         gst_audio_format_fill_silence (chain->finfo, tmp[i],
457             num_samples * chain->inc);
458       }
459     }
460   } else {
461     tmp = convert->in_data;
462     GST_LOG ("get in samples %p", tmp);
463   }
464   audio_chain_set_samples (chain, tmp, num_samples);
465
466   return TRUE;
467 }
468
469 static gboolean
470 do_convert_in (AudioChain * chain, gpointer user_data)
471 {
472   gsize num_samples;
473   GstAudioConverter *convert = user_data;
474   gpointer *in, *out;
475   gint i;
476
477   in = audio_chain_get_samples (chain->prev, &num_samples);
478   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
479   GST_LOG ("convert in %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
480
481   for (i = 0; i < chain->blocks; i++)
482     convert->convert_in (out[i], in[i], num_samples * chain->inc);
483
484   audio_chain_set_samples (chain, out, num_samples);
485
486   return TRUE;
487 }
488
489 static gboolean
490 do_mix (AudioChain * chain, gpointer user_data)
491 {
492   gsize num_samples;
493   GstAudioConverter *convert = user_data;
494   gpointer *in, *out;
495
496   in = audio_chain_get_samples (chain->prev, &num_samples);
497   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
498   GST_LOG ("mix %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
499
500   gst_audio_channel_mixer_samples (convert->mix, in, out, num_samples);
501
502   audio_chain_set_samples (chain, out, num_samples);
503
504   return TRUE;
505 }
506
507 static gboolean
508 do_resample (AudioChain * chain, gpointer user_data)
509 {
510   GstAudioConverter *convert = user_data;
511   gpointer *in, *out;
512   gsize in_frames, out_frames;
513
514   in = audio_chain_get_samples (chain->prev, &in_frames);
515   out_frames = convert->out_frames;
516   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, out_frames));
517
518   GST_LOG ("resample %p %p,%" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT, in,
519       out, in_frames, out_frames);
520
521   gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
522       out_frames);
523
524   audio_chain_set_samples (chain, out, out_frames);
525
526   return TRUE;
527 }
528
529 static gboolean
530 do_convert_out (AudioChain * chain, gpointer user_data)
531 {
532   GstAudioConverter *convert = user_data;
533   gsize num_samples;
534   gpointer *in, *out;
535   gint i;
536
537   in = audio_chain_get_samples (chain->prev, &num_samples);
538   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
539   GST_LOG ("convert out %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
540
541   for (i = 0; i < chain->blocks; i++)
542     convert->convert_out (out[i], in[i], num_samples * chain->inc);
543
544   audio_chain_set_samples (chain, out, num_samples);
545
546   return TRUE;
547 }
548
549 static gboolean
550 do_quantize (AudioChain * chain, gpointer user_data)
551 {
552   GstAudioConverter *convert = user_data;
553   gsize num_samples;
554   gpointer *in, *out;
555
556   in = audio_chain_get_samples (chain->prev, &num_samples);
557   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
558   GST_LOG ("quantize %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
559
560   gst_audio_quantize_samples (convert->quant, in, out, num_samples);
561
562   audio_chain_set_samples (chain, out, num_samples);
563
564   return TRUE;
565 }
566
567 static gboolean
568 is_intermediate_format (GstAudioFormat format)
569 {
570   return (format == GST_AUDIO_FORMAT_S16 ||
571       format == GST_AUDIO_FORMAT_S32 ||
572       format == GST_AUDIO_FORMAT_F32 || format == GST_AUDIO_FORMAT_F64);
573 }
574
575 static AudioChain *
576 chain_unpack (GstAudioConverter * convert)
577 {
578   AudioChain *prev;
579   GstAudioInfo *in = &convert->in;
580   GstAudioInfo *out = &convert->out;
581   gboolean same_format;
582
583   same_format = in->finfo->format == out->finfo->format;
584
585   /* do not unpack if we have the same input format as the output format
586    * and it is a possible intermediate format */
587   if (same_format && is_intermediate_format (in->finfo->format)) {
588     convert->current_format = in->finfo->format;
589   } else {
590     convert->current_format = in->finfo->unpack_format;
591   }
592   convert->current_layout = in->layout;
593   convert->current_channels = in->channels;
594
595   convert->in_default = convert->current_format == in->finfo->format;
596
597   GST_INFO ("unpack format %s to %s",
598       gst_audio_format_to_string (in->finfo->format),
599       gst_audio_format_to_string (convert->current_format));
600
601   prev = convert->unpack_chain = audio_chain_new (NULL, convert);
602   prev->allow_ip = prev->finfo->width <= in->finfo->width;
603   prev->pass_alloc = FALSE;
604   audio_chain_set_make_func (prev, do_unpack, convert, NULL);
605
606   return prev;
607 }
608
609 static AudioChain *
610 chain_convert_in (GstAudioConverter * convert, AudioChain * prev)
611 {
612   gboolean in_int, out_int;
613   GstAudioInfo *in = &convert->in;
614   GstAudioInfo *out = &convert->out;
615
616   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
617   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
618
619   if (in_int && !out_int) {
620     GST_INFO ("convert S32 to F64");
621     convert->convert_in = (AudioConvertFunc) audio_orc_s32_to_double;
622     convert->current_format = GST_AUDIO_FORMAT_F64;
623
624     prev = convert->convert_in_chain = audio_chain_new (prev, convert);
625     prev->allow_ip = FALSE;
626     prev->pass_alloc = FALSE;
627     audio_chain_set_make_func (prev, do_convert_in, convert, NULL);
628   }
629   return prev;
630 }
631
632 static AudioChain *
633 chain_mix (GstAudioConverter * convert, AudioChain * prev)
634 {
635   GstAudioChannelMixerFlags flags;
636   GstAudioInfo *in = &convert->in;
637   GstAudioInfo *out = &convert->out;
638   GstAudioFormat format = convert->current_format;
639
640   flags =
641       GST_AUDIO_INFO_IS_UNPOSITIONED (in) ?
642       GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_IN : 0;
643   flags |=
644       GST_AUDIO_INFO_IS_UNPOSITIONED (out) ?
645       GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_OUT : 0;
646
647   convert->current_channels = out->channels;
648
649   convert->mix =
650       gst_audio_channel_mixer_new (flags, format, in->channels, in->position,
651       out->channels, out->position);
652   convert->mix_passthrough =
653       gst_audio_channel_mixer_is_passthrough (convert->mix);
654   GST_INFO ("mix format %s, passthrough %d, in_channels %d, out_channels %d",
655       gst_audio_format_to_string (format), convert->mix_passthrough,
656       in->channels, out->channels);
657
658   if (!convert->mix_passthrough) {
659     prev = convert->mix_chain = audio_chain_new (prev, convert);
660     prev->allow_ip = FALSE;
661     prev->pass_alloc = FALSE;
662     audio_chain_set_make_func (prev, do_mix, convert, NULL);
663   }
664   return prev;
665 }
666
667 static AudioChain *
668 chain_resample (GstAudioConverter * convert, AudioChain * prev)
669 {
670   GstAudioInfo *in = &convert->in;
671   GstAudioInfo *out = &convert->out;
672   GstAudioResamplerMethod method;
673   GstAudioResamplerFlags flags;
674   GstAudioFormat format = convert->current_format;
675   gint channels = convert->current_channels;
676   gboolean variable_rate;
677
678   variable_rate = convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE;
679
680   if (in->rate != out->rate || variable_rate) {
681     method = GET_OPT_RESAMPLER_METHOD (convert);
682
683     flags = 0;
684     if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
685       flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED;
686     if (variable_rate)
687       flags |= GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE;
688
689     convert->resampler =
690         gst_audio_resampler_new (method, flags, format, channels, in->rate,
691         out->rate, convert->config);
692
693     prev = convert->resample_chain = audio_chain_new (prev, convert);
694     prev->allow_ip = FALSE;
695     prev->pass_alloc = FALSE;
696     audio_chain_set_make_func (prev, do_resample, convert, NULL);
697   }
698   return prev;
699 }
700
701 static AudioChain *
702 chain_convert_out (GstAudioConverter * convert, AudioChain * prev)
703 {
704   gboolean in_int, out_int;
705   GstAudioInfo *in = &convert->in;
706   GstAudioInfo *out = &convert->out;
707
708   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
709   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
710
711   if (!in_int && out_int) {
712     convert->convert_out = (AudioConvertFunc) audio_orc_double_to_s32;
713     convert->current_format = GST_AUDIO_FORMAT_S32;
714
715     GST_INFO ("convert F64 to S32");
716     prev = convert->convert_out_chain = audio_chain_new (prev, convert);
717     prev->allow_ip = TRUE;
718     prev->pass_alloc = FALSE;
719     audio_chain_set_make_func (prev, do_convert_out, convert, NULL);
720   }
721   return prev;
722 }
723
724 static AudioChain *
725 chain_quantize (GstAudioConverter * convert, AudioChain * prev)
726 {
727   const GstAudioFormatInfo *cur_finfo;
728   GstAudioInfo *out = &convert->out;
729   gint in_depth, out_depth;
730   gboolean in_int, out_int;
731   GstAudioDitherMethod dither;
732   GstAudioNoiseShapingMethod ns;
733
734   dither = GET_OPT_DITHER_METHOD (convert);
735   ns = GET_OPT_NOISE_SHAPING_METHOD (convert);
736
737   cur_finfo = gst_audio_format_get_info (convert->current_format);
738
739   in_depth = GST_AUDIO_FORMAT_INFO_DEPTH (cur_finfo);
740   out_depth = GST_AUDIO_FORMAT_INFO_DEPTH (out->finfo);
741   GST_INFO ("depth in %d, out %d", in_depth, out_depth);
742
743   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (cur_finfo);
744   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
745
746   /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
747    * as DA converters only can do a SNR up to 20 bits in reality.
748    * Also don't dither or apply noise shaping if target depth is larger than
749    * source depth. */
750   if (out_depth > 20 || (in_int && out_depth >= in_depth)) {
751     dither = GST_AUDIO_DITHER_NONE;
752     ns = GST_AUDIO_NOISE_SHAPING_NONE;
753     GST_INFO ("using no dither and noise shaping");
754   } else {
755     GST_INFO ("using dither %d and noise shaping %d", dither, ns);
756     /* Use simple error feedback when output sample rate is smaller than
757      * 32000 as the other methods might move the noise to audible ranges */
758     if (ns > GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
759       ns = GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK;
760   }
761   /* we still want to run the quantization step when reducing bits to get
762    * the rounding correct */
763   if (out_int && out_depth < 32
764       && convert->current_format == GST_AUDIO_FORMAT_S32) {
765     GST_INFO ("quantize to %d bits, dither %d, ns %d", out_depth, dither, ns);
766     convert->quant =
767         gst_audio_quantize_new (dither, ns, 0, convert->current_format,
768         out->channels, 1U << (32 - out_depth));
769
770     prev = convert->quant_chain = audio_chain_new (prev, convert);
771     prev->allow_ip = TRUE;
772     prev->pass_alloc = TRUE;
773     audio_chain_set_make_func (prev, do_quantize, convert, NULL);
774   }
775   return prev;
776 }
777
778 static AudioChain *
779 chain_pack (GstAudioConverter * convert, AudioChain * prev)
780 {
781   GstAudioInfo *out = &convert->out;
782   GstAudioFormat format = convert->current_format;
783
784   convert->current_format = out->finfo->format;
785
786   convert->out_default = format == out->finfo->format;
787   GST_INFO ("pack format %s to %s", gst_audio_format_to_string (format),
788       gst_audio_format_to_string (out->finfo->format));
789
790   return prev;
791 }
792
793 static void
794 setup_allocators (GstAudioConverter * convert)
795 {
796   AudioChain *chain;
797   AudioChainAllocFunc alloc_func;
798   gboolean allow_ip;
799
800   /* start with using dest if we can directly write into it */
801   if (convert->out_default) {
802     alloc_func = get_output_samples;
803     allow_ip = FALSE;
804   } else {
805     alloc_func = get_temp_samples;
806     allow_ip = TRUE;
807   }
808   /* now walk backwards, we try to write into the dest samples directly
809    * and keep track if the source needs to be writable */
810   for (chain = convert->pack_chain; chain; chain = chain->prev) {
811     chain->alloc_func = alloc_func;
812     chain->alloc_data = convert;
813     chain->allow_ip = allow_ip && chain->allow_ip;
814     GST_LOG ("chain %p: %d %d", chain, allow_ip, chain->allow_ip);
815
816     if (!chain->pass_alloc) {
817       /* can't pass allocator, make new temp line allocator */
818       alloc_func = get_temp_samples;
819       allow_ip = TRUE;
820     }
821   }
822 }
823
824 static gboolean
825 converter_passthrough (GstAudioConverter * convert,
826     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
827     gpointer out[], gsize out_frames)
828 {
829   gint i;
830   AudioChain *chain;
831   gsize samples;
832
833   chain = convert->pack_chain;
834
835   samples = in_frames * chain->inc;
836
837   GST_LOG ("passthrough: %" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " samples",
838       in_frames, samples);
839
840   if (in) {
841     gsize bytes;
842
843     bytes = samples * (convert->in.bpf / convert->in.channels);
844
845     for (i = 0; i < chain->blocks; i++)
846       memcpy (out[i], in[i], bytes);
847   } else {
848     for (i = 0; i < chain->blocks; i++)
849       gst_audio_format_fill_silence (convert->in.finfo, out[i], samples);
850   }
851   return TRUE;
852 }
853
854 static gboolean
855 converter_generic (GstAudioConverter * convert,
856     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
857     gpointer out[], gsize out_frames)
858 {
859   AudioChain *chain;
860   gpointer *tmp;
861   gint i;
862   gsize produced;
863
864   chain = convert->pack_chain;
865
866   convert->in_writable = flags & GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE;
867   convert->in_data = in;
868   convert->in_frames = in_frames;
869   convert->out_data = out;
870   convert->out_frames = out_frames;
871
872   /* get frames to pack */
873   tmp = audio_chain_get_samples (chain, &produced);
874
875   if (!convert->out_default) {
876     GST_LOG ("pack %p, %p %" G_GSIZE_FORMAT, tmp, out, produced);
877     /* and pack if needed */
878     for (i = 0; i < chain->blocks; i++)
879       convert->out.finfo->pack_func (convert->out.finfo, 0, tmp[i], out[i],
880           produced * chain->inc);
881   }
882   return TRUE;
883 }
884
885 static gboolean
886 converter_resample (GstAudioConverter * convert,
887     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
888     gpointer out[], gsize out_frames)
889 {
890   gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
891       out_frames);
892
893   return TRUE;
894 }
895
896 /**
897  * gst_audio_converter_new: (skip)
898  * @flags: extra #GstAudioConverterFlags
899  * @in_info: a source #GstAudioInfo
900  * @out_info: a destination #GstAudioInfo
901  * @config: (transfer full): a #GstStructure with configuration options
902  *
903  * Create a new #GstAudioConverter that is able to convert between @in and @out
904  * audio formats.
905  *
906  * @config contains extra configuration options, see #GST_VIDEO_CONVERTER_OPT_*
907  * parameters for details about the options and values.
908  *
909  * Returns: a #GstAudioConverter or %NULL if conversion is not possible.
910  */
911 GstAudioConverter *
912 gst_audio_converter_new (GstAudioConverterFlags flags, GstAudioInfo * in_info,
913     GstAudioInfo * out_info, GstStructure * config)
914 {
915   GstAudioConverter *convert;
916   AudioChain *prev;
917
918   g_return_val_if_fail (in_info != NULL, FALSE);
919   g_return_val_if_fail (out_info != NULL, FALSE);
920   g_return_val_if_fail (in_info->layout == GST_AUDIO_LAYOUT_INTERLEAVED, FALSE);
921   g_return_val_if_fail (in_info->layout == out_info->layout, FALSE);
922
923   if ((GST_AUDIO_INFO_CHANNELS (in_info) != GST_AUDIO_INFO_CHANNELS (out_info))
924       && (GST_AUDIO_INFO_IS_UNPOSITIONED (in_info)
925           || GST_AUDIO_INFO_IS_UNPOSITIONED (out_info)))
926     goto unpositioned;
927
928   convert = g_slice_new0 (GstAudioConverter);
929
930   convert->flags = flags;
931   convert->in = *in_info;
932   convert->out = *out_info;
933
934   /* default config */
935   convert->config = gst_structure_new_empty ("GstAudioConverter");
936   if (config)
937     gst_audio_converter_update_config (convert, 0, 0, config);
938
939   GST_INFO ("unitsizes: %d -> %d", in_info->bpf, out_info->bpf);
940
941   /* step 1, unpack */
942   prev = chain_unpack (convert);
943   /* step 2, optional convert from S32 to F64 for channel mix */
944   prev = chain_convert_in (convert, prev);
945   /* step 3, channel mix */
946   prev = chain_mix (convert, prev);
947   /* step 4, resample */
948   prev = chain_resample (convert, prev);
949   /* step 5, optional convert for quantize */
950   prev = chain_convert_out (convert, prev);
951   /* step 6, optional quantize */
952   prev = chain_quantize (convert, prev);
953   /* step 7, pack */
954   convert->pack_chain = chain_pack (convert, prev);
955
956   convert->convert = converter_generic;
957
958   /* optimize */
959   if (out_info->finfo->format == in_info->finfo->format
960       && convert->mix_passthrough) {
961     if (convert->resampler == NULL) {
962       GST_INFO
963           ("same formats, no resampler and passthrough mixing -> passthrough");
964       convert->convert = converter_passthrough;
965     } else {
966       if (is_intermediate_format (in_info->finfo->format)) {
967         GST_INFO ("same formats, and passthrough mixing -> only resampling");
968         convert->convert = converter_resample;
969       }
970     }
971   }
972
973   setup_allocators (convert);
974
975   return convert;
976
977   /* ERRORS */
978 unpositioned:
979   {
980     GST_WARNING ("unpositioned channels");
981     return NULL;
982   }
983 }
984
985 /**
986  * gst_audio_converter_free:
987  * @convert: a #GstAudioConverter
988  *
989  * Free a previously allocated @convert instance.
990  */
991 void
992 gst_audio_converter_free (GstAudioConverter * convert)
993 {
994   g_return_if_fail (convert != NULL);
995
996   if (convert->unpack_chain)
997     audio_chain_free (convert->unpack_chain);
998   if (convert->convert_in_chain)
999     audio_chain_free (convert->convert_in_chain);
1000   if (convert->mix_chain)
1001     audio_chain_free (convert->mix_chain);
1002   if (convert->resample_chain)
1003     audio_chain_free (convert->resample_chain);
1004   if (convert->convert_out_chain)
1005     audio_chain_free (convert->convert_out_chain);
1006   if (convert->quant_chain)
1007     audio_chain_free (convert->quant_chain);
1008   if (convert->quant)
1009     gst_audio_quantize_free (convert->quant);
1010   if (convert->mix)
1011     gst_audio_channel_mixer_free (convert->mix);
1012   if (convert->resampler)
1013     gst_audio_resampler_free (convert->resampler);
1014   gst_audio_info_init (&convert->in);
1015   gst_audio_info_init (&convert->out);
1016
1017   gst_structure_free (convert->config);
1018
1019   g_slice_free (GstAudioConverter, convert);
1020 }
1021
1022 /**
1023  * gst_audio_converter_get_out_frames:
1024  * @convert: a #GstAudioConverter
1025  * @in_frames: number of input frames
1026  *
1027  * Calculate how many output frames can be produced when @in_frames input
1028  * frames are given to @convert.
1029  *
1030  * Returns: the number of output frames
1031  */
1032 gsize
1033 gst_audio_converter_get_out_frames (GstAudioConverter * convert,
1034     gsize in_frames)
1035 {
1036   if (convert->resampler)
1037     return gst_audio_resampler_get_out_frames (convert->resampler, in_frames);
1038   else
1039     return in_frames;
1040 }
1041
1042 /**
1043  * gst_audio_converter_get_in_frames:
1044  * @convert: a #GstAudioConverter
1045  * @out_frames: number of output frames
1046  *
1047  * Calculate how many input frames are currently needed by @convert to produce
1048  * @out_frames of output frames.
1049  *
1050  * Returns: the number of input frames
1051  */
1052 gsize
1053 gst_audio_converter_get_in_frames (GstAudioConverter * convert,
1054     gsize out_frames)
1055 {
1056   if (convert->resampler)
1057     return gst_audio_resampler_get_in_frames (convert->resampler, out_frames);
1058   else
1059     return out_frames;
1060 }
1061
1062 /**
1063  * gst_audio_converter_get_max_latency:
1064  * @convert: a #GstAudioConverter
1065  *
1066  * Get the maximum number of input frames that the converter would
1067  * need before producing output.
1068  *
1069  * Returns: the latency of @convert as expressed in the number of
1070  * frames.
1071  */
1072 gsize
1073 gst_audio_converter_get_max_latency (GstAudioConverter * convert)
1074 {
1075   if (convert->resampler)
1076     return gst_audio_resampler_get_max_latency (convert->resampler);
1077   else
1078     return 0;
1079 }
1080
1081 /**
1082  * gst_audio_converter_reset:
1083  * @convert: a #GstAudioConverter
1084  *
1085  * Reset @convert to the state it was when it was first created, clearing
1086  * any history it might currently have.
1087  */
1088 void
1089 gst_audio_converter_reset (GstAudioConverter * convert)
1090 {
1091   if (convert->resampler)
1092     gst_audio_resampler_reset (convert->resampler);
1093   if (convert->quant)
1094     gst_audio_quantize_reset (convert->quant);
1095 }
1096
1097 /**
1098  * gst_audio_converter_samples:
1099  * @convert: a #GstAudioConverter
1100  * @flags: extra #GstAudioConverterFlags
1101  * @in: input frames
1102  * @in_frames: number of input frames
1103  * @out: output frames
1104  * @out_frames: number of output frames
1105  *
1106  * Perform the conversion with @in_frames in @in to @out_frames in @out
1107  * using @convert.
1108  *
1109  * In case the samples are interleaved, @in and @out must point to an
1110  * array with a single element pointing to a block of interleaved samples.
1111  *
1112  * If non-interleaved samples are used, @in and @out must point to an
1113  * array with pointers to memory blocks, one for each channel.
1114  *
1115  * @in may be %NULL, in which case @in_frames of silence samples are processed
1116  * by the converter.
1117  *
1118  * This function always produces @out_frames of output and consumes @in_frames of
1119  * input. Use gst_audio_converter_get_out_frames() and
1120  * gst_audio_converter_get_in_frames() to make sure @in_frames and @out_frames
1121  * are matching and @in and @out point to enough memory.
1122  *
1123  * Returns: %TRUE is the conversion could be performed.
1124  */
1125 gboolean
1126 gst_audio_converter_samples (GstAudioConverter * convert,
1127     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1128     gpointer out[], gsize out_frames)
1129 {
1130   g_return_val_if_fail (convert != NULL, FALSE);
1131   g_return_val_if_fail (out != NULL, FALSE);
1132
1133   if (in_frames == 0) {
1134     GST_LOG ("skipping empty buffer");
1135     return TRUE;
1136   }
1137   return convert->convert (convert, flags, in, in_frames, out, out_frames);
1138 }