audio-converter: perform dithering on the current format
[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   /* convert out */
131   AudioConvertFunc convert_out;
132   AudioChain *convert_out_chain;
133
134   /* quant */
135   GstAudioQuantize *quant;
136   AudioChain *quant_chain;
137
138   /* pack */
139   gboolean out_default;
140   AudioChain *pack_chain;
141
142   AudioConvertSamplesFunc convert;
143 };
144
145 typedef gboolean (*AudioChainFunc) (AudioChain * chain, gpointer user_data);
146 typedef gpointer *(*AudioChainAllocFunc) (AudioChain * chain, gsize num_samples,
147     gpointer user_data);
148
149 struct _AudioChain
150 {
151   AudioChain *prev;
152
153   AudioChainFunc make_func;
154   gpointer make_func_data;
155   GDestroyNotify make_func_notify;
156
157   const GstAudioFormatInfo *finfo;
158   gint stride;
159   gint inc;
160   gint blocks;
161
162   gboolean pass_alloc;
163   gboolean allow_ip;
164
165   AudioChainAllocFunc alloc_func;
166   gpointer alloc_data;
167
168   gpointer *tmp;
169   gsize allocated_samples;
170
171   gpointer *samples;
172   gsize num_samples;
173 };
174
175 static AudioChain *
176 audio_chain_new (AudioChain * prev, GstAudioConverter * convert)
177 {
178   AudioChain *chain;
179
180   chain = g_slice_new0 (AudioChain);
181   chain->prev = prev;
182
183   if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
184     chain->inc = 1;
185     chain->blocks = convert->current_channels;
186   } else {
187     chain->inc = convert->current_channels;
188     chain->blocks = 1;
189   }
190   chain->finfo = gst_audio_format_get_info (convert->current_format);
191   chain->stride = (chain->finfo->width * chain->inc) / 8;
192
193   return chain;
194 }
195
196 static void
197 audio_chain_set_make_func (AudioChain * chain,
198     AudioChainFunc make_func, gpointer user_data, GDestroyNotify notify)
199 {
200   chain->make_func = make_func;
201   chain->make_func_data = user_data;
202   chain->make_func_notify = notify;
203 }
204
205 static void
206 audio_chain_free (AudioChain * chain)
207 {
208   GST_LOG ("free chain %p", chain);
209   if (chain->make_func_notify)
210     chain->make_func_notify (chain->make_func_data);
211   g_free (chain->tmp);
212   g_slice_free (AudioChain, chain);
213 }
214
215 static gpointer *
216 audio_chain_alloc_samples (AudioChain * chain, gsize num_samples)
217 {
218   return chain->alloc_func (chain, num_samples, chain->alloc_data);
219 }
220
221 static void
222 audio_chain_set_samples (AudioChain * chain, gpointer * samples,
223     gsize num_samples)
224 {
225   GST_LOG ("set samples %p %" G_GSIZE_FORMAT, samples, num_samples);
226
227   chain->samples = samples;
228   chain->num_samples = num_samples;
229 }
230
231 static gpointer *
232 audio_chain_get_samples (AudioChain * chain, gsize * avail)
233 {
234   gpointer *res;
235
236   while (!chain->samples)
237     chain->make_func (chain, chain->make_func_data);
238
239   res = chain->samples;
240   *avail = chain->num_samples;
241   chain->samples = NULL;
242
243   return res;
244 }
245
246 /*
247 static guint
248 get_opt_uint (GstAudioConverter * convert, const gchar * opt, guint def)
249 {
250   guint res;
251   if (!gst_structure_get_uint (convert->config, opt, &res))
252     res = def;
253   return res;
254 }
255 */
256
257 static gint
258 get_opt_enum (GstAudioConverter * convert, const gchar * opt, GType type,
259     gint def)
260 {
261   gint res;
262   if (!gst_structure_get_enum (convert->config, opt, type, &res))
263     res = def;
264   return res;
265 }
266
267 #define DEFAULT_OPT_DITHER_METHOD GST_AUDIO_DITHER_NONE
268 #define DEFAULT_OPT_NOISE_SHAPING_METHOD GST_AUDIO_NOISE_SHAPING_NONE
269 #define DEFAULT_OPT_QUANTIZATION 1
270
271 #define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \
272     GST_AUDIO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_AUDIO_DITHER_METHOD, \
273     DEFAULT_OPT_DITHER_METHOD)
274 #define GET_OPT_NOISE_SHAPING_METHOD(c) get_opt_enum(c, \
275     GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, \
276     DEFAULT_OPT_NOISE_SHAPING_METHOD)
277 #define GET_OPT_QUANTIZATION(c) get_opt_uint(c, \
278     GST_AUDIO_CONVERTER_OPT_QUANTIZATION, DEFAULT_OPT_QUANTIZATION)
279
280 static gboolean
281 copy_config (GQuark field_id, const GValue * value, gpointer user_data)
282 {
283   GstAudioConverter *convert = user_data;
284
285   gst_structure_id_set_value (convert->config, field_id, value);
286
287   return TRUE;
288 }
289
290 /**
291  * gst_audio_converter_update_config:
292  * @convert: a #GstAudioConverter
293  * @in_rate: input rate
294  * @out_rate: output rate
295  * @config: (transfer full) (allow-none): a #GstStructure or %NULL
296  *
297  * Set @in_rate, @out_rate and @config as extra configuration for @convert.
298  *
299  * in_rate and @out_rate specify the new sample rates of input and output
300  * formats. A value of 0 leaves the sample rate unchanged.
301  *
302  * @config can be %NULL, in which case, the current configuration is not
303  * changed.
304  *
305  * If the parameters in @config can not be set exactly, this function returns
306  * %FALSE and will try to update as much state as possible. The new state can
307  * then be retrieved and refined with gst_audio_converter_get_config().
308  *
309  * Look at the #GST_AUDIO_CONVERTER_OPT_* fields to check valid configuration
310  * option and values.
311  *
312  * Returns: %TRUE when the new parameters could be set
313  */
314 gboolean
315 gst_audio_converter_update_config (GstAudioConverter * convert,
316     gint in_rate, gint out_rate, GstStructure * config)
317 {
318   g_return_val_if_fail (convert != NULL, FALSE);
319   g_return_val_if_fail ((in_rate == 0 && out_rate == 0) ||
320       convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE, FALSE);
321
322   GST_LOG ("new rate %d -> %d", in_rate, out_rate);
323
324   if (in_rate <= 0)
325     in_rate = convert->in.rate;
326   if (out_rate <= 0)
327     out_rate = convert->out.rate;
328
329   convert->in.rate = in_rate;
330   convert->out.rate = out_rate;
331
332   if (config) {
333     gst_structure_foreach (config, copy_config, convert);
334     gst_structure_free (config);
335   }
336
337   return TRUE;
338 }
339
340 /**
341  * gst_audio_converter_get_config:
342  * @convert: a #GstAudioConverter
343  * @in_rate: result input rate
344  * @out_rate: result output rate
345  *
346  * Get the current configuration of @convert.
347  *
348  * Returns: a #GstStructure that remains valid for as long as @convert is valid
349  *   or until gst_audio_converter_update_config() is called.
350  */
351 const GstStructure *
352 gst_audio_converter_get_config (GstAudioConverter * convert,
353     gint * in_rate, gint * out_rate)
354 {
355   g_return_val_if_fail (convert != NULL, NULL);
356
357   if (in_rate)
358     *in_rate = convert->in.rate;
359   if (out_rate)
360     *out_rate = convert->out.rate;
361
362   return convert->config;
363 }
364
365 static gpointer *
366 get_output_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
367 {
368   GstAudioConverter *convert = user_data;
369
370   GST_LOG ("output samples %p %" G_GSIZE_FORMAT, convert->out_data,
371       num_samples);
372
373   return convert->out_data;
374 }
375
376 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
377 #define ALIGN 16
378
379 static gpointer *
380 get_temp_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
381 {
382   if (num_samples > chain->allocated_samples) {
383     gint i;
384     gint8 *s;
385     gsize stride = GST_ROUND_UP_N (num_samples * chain->stride, ALIGN);
386     /* first part contains the pointers, second part the data, add some extra bytes
387      * for alignement */
388     gsize needed = (stride + sizeof (gpointer)) * chain->blocks + ALIGN;
389
390     GST_DEBUG ("alloc samples %d %" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT,
391         chain->stride, num_samples, needed);
392     chain->tmp = g_realloc (chain->tmp, needed);
393     chain->allocated_samples = num_samples;
394
395     /* pointer to the data, make sure it's 16 bytes aligned */
396     s = MEM_ALIGN (&chain->tmp[chain->blocks], ALIGN);
397
398     /* set up the pointers */
399     for (i = 0; i < chain->blocks; i++)
400       chain->tmp[i] = s + i * stride;
401   }
402   GST_LOG ("temp samples %p %" G_GSIZE_FORMAT, chain->tmp, num_samples);
403
404   return chain->tmp;
405 }
406
407 static gboolean
408 do_unpack (AudioChain * chain, gpointer user_data)
409 {
410   GstAudioConverter *convert = user_data;
411   gsize num_samples;
412   gpointer *tmp;
413   gboolean in_writable;
414
415   in_writable = convert->in_writable;
416   num_samples = convert->in_frames;
417
418   if (!chain->allow_ip || !in_writable || !convert->in_default) {
419     gint i;
420
421     if (in_writable && chain->allow_ip) {
422       tmp = convert->in_data;
423       GST_LOG ("unpack in-place %p, %" G_GSIZE_FORMAT, tmp, num_samples);
424     } else {
425       tmp = audio_chain_alloc_samples (chain, num_samples);
426       GST_LOG ("unpack to tmp %p, %" G_GSIZE_FORMAT, tmp, num_samples);
427     }
428
429     if (convert->in_data) {
430       for (i = 0; i < chain->blocks; i++) {
431         if (convert->in_default) {
432           GST_LOG ("copy %p, %p, %" G_GSIZE_FORMAT, tmp[i], convert->in_data[i],
433               num_samples);
434           memcpy (tmp[i], convert->in_data[i], num_samples * chain->stride);
435         } else {
436           GST_LOG ("unpack %p, %p, %" G_GSIZE_FORMAT, tmp[i],
437               convert->in_data[i], num_samples);
438           convert->in.finfo->unpack_func (convert->in.finfo,
439               GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE, tmp[i], convert->in_data[i],
440               num_samples * chain->inc);
441         }
442       }
443     } else {
444       for (i = 0; i < chain->blocks; i++) {
445         gst_audio_format_fill_silence (chain->finfo, tmp[i],
446             num_samples * chain->inc);
447       }
448     }
449   } else {
450     tmp = convert->in_data;
451     GST_LOG ("get in samples %p", tmp);
452   }
453   audio_chain_set_samples (chain, tmp, num_samples);
454
455   return TRUE;
456 }
457
458 static gboolean
459 do_convert_in (AudioChain * chain, gpointer user_data)
460 {
461   GstAudioConverter *convert = user_data;
462   gsize num_samples;
463   gpointer *in, *out;
464   gint i;
465
466   in = audio_chain_get_samples (chain->prev, &num_samples);
467   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
468   GST_LOG ("convert in %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
469
470   for (i = 0; i < chain->blocks; i++)
471     convert->convert_in (out[i], in[i], num_samples * chain->inc);
472
473   audio_chain_set_samples (chain, out, num_samples);
474
475   return TRUE;
476 }
477
478 static gboolean
479 do_mix (AudioChain * chain, gpointer user_data)
480 {
481   GstAudioConverter *convert = user_data;
482   gsize num_samples;
483   gpointer *in, *out;
484
485   in = audio_chain_get_samples (chain->prev, &num_samples);
486   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
487   GST_LOG ("mix %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
488
489   gst_audio_channel_mixer_samples (convert->mix, in, out, num_samples);
490
491   audio_chain_set_samples (chain, out, num_samples);
492
493   return TRUE;
494 }
495
496 static gboolean
497 do_convert_out (AudioChain * chain, gpointer user_data)
498 {
499   GstAudioConverter *convert = user_data;
500   gsize num_samples;
501   gpointer *in, *out;
502   gint i;
503
504   in = audio_chain_get_samples (chain->prev, &num_samples);
505   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
506   GST_LOG ("convert out %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
507
508   for (i = 0; i < chain->blocks; i++)
509     convert->convert_out (out[i], in[i], num_samples * chain->inc);
510
511   audio_chain_set_samples (chain, out, num_samples);
512
513   return TRUE;
514 }
515
516 static gboolean
517 do_quantize (AudioChain * chain, gpointer user_data)
518 {
519   GstAudioConverter *convert = user_data;
520   gsize num_samples;
521   gpointer *in, *out;
522
523   in = audio_chain_get_samples (chain->prev, &num_samples);
524   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
525   GST_LOG ("quantize %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
526
527   gst_audio_quantize_samples (convert->quant, in, out, num_samples);
528
529   audio_chain_set_samples (chain, out, num_samples);
530
531   return TRUE;
532 }
533
534 static gboolean
535 is_intermediate_format (GstAudioFormat format)
536 {
537   return (format == GST_AUDIO_FORMAT_S16 ||
538       format == GST_AUDIO_FORMAT_S32 ||
539       format == GST_AUDIO_FORMAT_F32 || format == GST_AUDIO_FORMAT_F64);
540 }
541
542 static AudioChain *
543 chain_unpack (GstAudioConverter * convert)
544 {
545   AudioChain *prev;
546   GstAudioInfo *in = &convert->in;
547   GstAudioInfo *out = &convert->out;
548   gboolean same_format;
549
550   same_format = in->finfo->format == out->finfo->format;
551
552   /* do not unpack if we have the same input format as the output format
553    * and it is a possible intermediate format */
554   if (same_format && is_intermediate_format (in->finfo->format)) {
555     convert->current_format = in->finfo->format;
556   } else {
557     convert->current_format = in->finfo->unpack_format;
558   }
559   convert->current_layout = in->layout;
560   convert->current_channels = in->channels;
561
562   convert->in_default = convert->current_format == in->finfo->format;
563
564   GST_INFO ("unpack format %s to %s",
565       gst_audio_format_to_string (in->finfo->format),
566       gst_audio_format_to_string (convert->current_format));
567
568   prev = convert->unpack_chain = audio_chain_new (NULL, convert);
569   prev->allow_ip = prev->finfo->width <= in->finfo->width;
570   prev->pass_alloc = FALSE;
571   audio_chain_set_make_func (prev, do_unpack, convert, NULL);
572
573   return prev;
574 }
575
576 static AudioChain *
577 chain_convert_in (GstAudioConverter * convert, AudioChain * prev)
578 {
579   gboolean in_int, out_int;
580   GstAudioInfo *in = &convert->in;
581   GstAudioInfo *out = &convert->out;
582
583   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
584   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
585
586   if (in_int && !out_int) {
587     GST_INFO ("convert S32 to F64");
588     convert->convert_in = (AudioConvertFunc) audio_orc_s32_to_double;
589     convert->current_format = GST_AUDIO_FORMAT_F64;
590
591     prev = convert->convert_in_chain = audio_chain_new (prev, convert);
592     prev->allow_ip = FALSE;
593     prev->pass_alloc = FALSE;
594     audio_chain_set_make_func (prev, do_convert_in, convert, NULL);
595   }
596   return prev;
597 }
598
599 static AudioChain *
600 chain_mix (GstAudioConverter * convert, AudioChain * prev)
601 {
602   GstAudioChannelMixerFlags flags;
603   GstAudioInfo *in = &convert->in;
604   GstAudioInfo *out = &convert->out;
605   GstAudioFormat format = convert->current_format;
606
607   flags =
608       GST_AUDIO_INFO_IS_UNPOSITIONED (in) ?
609       GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_IN : 0;
610   flags |=
611       GST_AUDIO_INFO_IS_UNPOSITIONED (out) ?
612       GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_OUT : 0;
613
614   convert->current_channels = out->channels;
615
616   convert->mix =
617       gst_audio_channel_mixer_new (flags, format, in->channels, in->position,
618       out->channels, out->position);
619   convert->mix_passthrough =
620       gst_audio_channel_mixer_is_passthrough (convert->mix);
621   GST_INFO ("mix format %s, passthrough %d, in_channels %d, out_channels %d",
622       gst_audio_format_to_string (format), convert->mix_passthrough,
623       in->channels, out->channels);
624
625   if (!convert->mix_passthrough) {
626     prev = convert->mix_chain = audio_chain_new (prev, convert);
627     prev->allow_ip = FALSE;
628     prev->pass_alloc = FALSE;
629     audio_chain_set_make_func (prev, do_mix, convert, NULL);
630   }
631   return prev;
632 }
633
634 static AudioChain *
635 chain_convert_out (GstAudioConverter * convert, AudioChain * prev)
636 {
637   gboolean in_int, out_int;
638   GstAudioInfo *in = &convert->in;
639   GstAudioInfo *out = &convert->out;
640
641   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
642   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
643
644   if (!in_int && out_int) {
645     convert->convert_out = (AudioConvertFunc) audio_orc_double_to_s32;
646     convert->current_format = GST_AUDIO_FORMAT_S32;
647
648     GST_INFO ("convert F64 to S32");
649     prev = convert->convert_out_chain = audio_chain_new (prev, convert);
650     prev->allow_ip = TRUE;
651     prev->pass_alloc = FALSE;
652     audio_chain_set_make_func (prev, do_convert_out, convert, NULL);
653   }
654   return prev;
655 }
656
657 static AudioChain *
658 chain_quantize (GstAudioConverter * convert, AudioChain * prev)
659 {
660   const GstAudioFormatInfo *cur_finfo;
661   GstAudioInfo *out = &convert->out;
662   gint in_depth, out_depth;
663   gboolean in_int, out_int;
664   GstAudioDitherMethod dither;
665   GstAudioNoiseShapingMethod ns;
666
667   dither = GET_OPT_DITHER_METHOD (convert);
668   ns = GET_OPT_NOISE_SHAPING_METHOD (convert);
669
670   cur_finfo = gst_audio_format_get_info (convert->current_format);
671
672   in_depth = GST_AUDIO_FORMAT_INFO_DEPTH (cur_finfo);
673   out_depth = GST_AUDIO_FORMAT_INFO_DEPTH (out->finfo);
674   GST_INFO ("depth in %d, out %d", in_depth, out_depth);
675
676   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (cur_finfo);
677   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
678
679   /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
680    * as DA converters only can do a SNR up to 20 bits in reality.
681    * Also don't dither or apply noise shaping if target depth is larger than
682    * source depth. */
683   if (out_depth > 20 || (in_int && out_depth >= in_depth)) {
684     dither = GST_AUDIO_DITHER_NONE;
685     ns = GST_AUDIO_NOISE_SHAPING_NONE;
686     GST_INFO ("using no dither and noise shaping");
687   } else {
688     GST_INFO ("using dither %d and noise shaping %d", dither, ns);
689     /* Use simple error feedback when output sample rate is smaller than
690      * 32000 as the other methods might move the noise to audible ranges */
691     if (ns > GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
692       ns = GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK;
693   }
694   /* we still want to run the quantization step when reducing bits to get
695    * the rounding correct */
696   if (out_int && out_depth < 32
697       && convert->current_format == GST_AUDIO_FORMAT_S32) {
698     GST_INFO ("quantize to %d bits, dither %d, ns %d", out_depth, dither, ns);
699     convert->quant =
700         gst_audio_quantize_new (dither, ns, 0, convert->current_format,
701         out->channels, 1U << (32 - out_depth));
702
703     prev = convert->quant_chain = audio_chain_new (prev, convert);
704     prev->allow_ip = TRUE;
705     prev->pass_alloc = TRUE;
706     audio_chain_set_make_func (prev, do_quantize, convert, NULL);
707   }
708   return prev;
709 }
710
711 static AudioChain *
712 chain_pack (GstAudioConverter * convert, AudioChain * prev)
713 {
714   GstAudioInfo *out = &convert->out;
715   GstAudioFormat format = convert->current_format;
716
717   convert->current_format = out->finfo->format;
718
719   convert->out_default = format == out->finfo->format;
720   GST_INFO ("pack format %s to %s", gst_audio_format_to_string (format),
721       gst_audio_format_to_string (out->finfo->format));
722
723   return prev;
724 }
725
726 static void
727 setup_allocators (GstAudioConverter * convert)
728 {
729   AudioChain *chain;
730   AudioChainAllocFunc alloc_func;
731   gboolean allow_ip;
732
733   /* start with using dest if we can directly write into it */
734   if (convert->out_default) {
735     alloc_func = get_output_samples;
736     allow_ip = FALSE;
737   } else {
738     alloc_func = get_temp_samples;
739     allow_ip = TRUE;
740   }
741   /* now walk backwards, we try to write into the dest samples directly
742    * and keep track if the source needs to be writable */
743   for (chain = convert->pack_chain; chain; chain = chain->prev) {
744     chain->alloc_func = alloc_func;
745     chain->alloc_data = convert;
746     chain->allow_ip = allow_ip && chain->allow_ip;
747     GST_LOG ("chain %p: %d %d", chain, allow_ip, chain->allow_ip);
748
749     if (!chain->pass_alloc) {
750       /* can't pass allocator, make new temp line allocator */
751       alloc_func = get_temp_samples;
752       allow_ip = TRUE;
753     }
754   }
755 }
756
757 static gboolean
758 converter_passthrough (GstAudioConverter * convert,
759     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
760     gpointer out[], gsize out_frames)
761 {
762   gint i;
763   AudioChain *chain;
764   gsize samples;
765
766   chain = convert->pack_chain;
767
768   samples = in_frames * chain->inc;
769
770   GST_LOG ("passthrough: %" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " samples",
771       in_frames, samples);
772
773   if (in) {
774     gsize bytes;
775
776     bytes = samples * (convert->in.bpf / convert->in.channels);
777
778     for (i = 0; i < chain->blocks; i++)
779       memcpy (out[i], in[i], bytes);
780   } else {
781     for (i = 0; i < chain->blocks; i++)
782       gst_audio_format_fill_silence (convert->in.finfo, out[i], samples);
783   }
784
785   return TRUE;
786 }
787
788 static gboolean
789 converter_generic (GstAudioConverter * convert,
790     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
791     gpointer out[], gsize out_frames)
792 {
793   AudioChain *chain;
794   gpointer *tmp;
795   gint i;
796   gsize produced;
797
798   chain = convert->pack_chain;
799
800   convert->in_writable = flags & GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE;
801   convert->in_data = in;
802   convert->in_frames = in_frames;
803   convert->out_data = out;
804   convert->out_frames = out_frames;
805
806   /* get frames to pack */
807   tmp = audio_chain_get_samples (chain, &produced);
808
809   if (!convert->out_default) {
810     GST_LOG ("pack %p, %p %" G_GSIZE_FORMAT, tmp, out, produced);
811     /* and pack if needed */
812     for (i = 0; i < chain->blocks; i++)
813       convert->out.finfo->pack_func (convert->out.finfo, 0, tmp[i], out[i],
814           produced * chain->inc);
815   }
816   return TRUE;
817 }
818
819 /**
820  * gst_audio_converter_new: (skip)
821  * @flags: #GstAudioConverterFlags
822  * @in_info: a source #GstAudioInfo
823  * @out_info: a destination #GstAudioInfo
824  * @config: (transfer full): a #GstStructure with configuration options
825  *
826  * Create a new #GstAudioConverter that is able to convert between @in and @out
827  * audio formats.
828  *
829  * @config contains extra configuration options, see #GST_VIDEO_CONVERTER_OPT_*
830  * parameters for details about the options and values.
831  *
832  * Returns: a #GstAudioConverter or %NULL if conversion is not possible.
833  */
834 GstAudioConverter *
835 gst_audio_converter_new (GstAudioConverterFlags flags, GstAudioInfo * in_info,
836     GstAudioInfo * out_info, GstStructure * config)
837 {
838   GstAudioConverter *convert;
839   AudioChain *prev;
840
841   g_return_val_if_fail (in_info != NULL, FALSE);
842   g_return_val_if_fail (out_info != NULL, FALSE);
843   g_return_val_if_fail (in_info->rate == out_info->rate, FALSE);
844   g_return_val_if_fail (in_info->layout == GST_AUDIO_LAYOUT_INTERLEAVED, FALSE);
845   g_return_val_if_fail (in_info->layout == out_info->layout, FALSE);
846
847   if ((GST_AUDIO_INFO_CHANNELS (in_info) != GST_AUDIO_INFO_CHANNELS (out_info))
848       && (GST_AUDIO_INFO_IS_UNPOSITIONED (in_info)
849           || GST_AUDIO_INFO_IS_UNPOSITIONED (out_info)))
850     goto unpositioned;
851
852   convert = g_slice_new0 (GstAudioConverter);
853
854   convert->flags = flags;
855   convert->in = *in_info;
856   convert->out = *out_info;
857
858   /* default config */
859   convert->config = gst_structure_new_empty ("GstAudioConverter");
860   if (config)
861     gst_audio_converter_update_config (convert, 0, 0, config);
862
863   GST_INFO ("unitsizes: %d -> %d", in_info->bpf, out_info->bpf);
864
865   /* step 1, unpack */
866   prev = chain_unpack (convert);
867   /* step 2, optional convert from S32 to F64 for channel mix */
868   prev = chain_convert_in (convert, prev);
869   /* step 3, channel mix */
870   prev = chain_mix (convert, prev);
871   /* step 4, optional convert for quantize */
872   prev = chain_convert_out (convert, prev);
873   /* step 5, optional quantize */
874   prev = chain_quantize (convert, prev);
875   /* step 6, pack */
876   convert->pack_chain = chain_pack (convert, prev);
877
878   /* optimize */
879   if (out_info->finfo->format == in_info->finfo->format
880       && convert->mix_passthrough) {
881     GST_INFO ("same formats and passthrough mixing -> passthrough");
882     convert->convert = converter_passthrough;
883   } else {
884     GST_INFO ("do full conversion");
885     convert->convert = converter_generic;
886   }
887
888   setup_allocators (convert);
889
890   return convert;
891
892   /* ERRORS */
893 unpositioned:
894   {
895     GST_WARNING ("unpositioned channels");
896     return NULL;
897   }
898 }
899
900 /**
901  * gst_audio_converter_free:
902  * @convert: a #GstAudioConverter
903  *
904  * Free a previously allocated @convert instance.
905  */
906 void
907 gst_audio_converter_free (GstAudioConverter * convert)
908 {
909   g_return_if_fail (convert != NULL);
910
911   if (convert->unpack_chain)
912     audio_chain_free (convert->unpack_chain);
913   if (convert->convert_in_chain)
914     audio_chain_free (convert->convert_in_chain);
915   if (convert->mix_chain)
916     audio_chain_free (convert->mix_chain);
917   if (convert->convert_out_chain)
918     audio_chain_free (convert->convert_out_chain);
919   if (convert->quant_chain)
920     audio_chain_free (convert->quant_chain);
921
922   if (convert->quant)
923     gst_audio_quantize_free (convert->quant);
924   if (convert->mix)
925     gst_audio_channel_mixer_free (convert->mix);
926   gst_audio_info_init (&convert->in);
927   gst_audio_info_init (&convert->out);
928
929   gst_structure_free (convert->config);
930
931   g_slice_free (GstAudioConverter, convert);
932 }
933
934 /**
935  * gst_audio_converter_get_out_frames:
936  * @convert: a #GstAudioConverter
937  * @in_frames: number of input frames
938  *
939  * Calculate how many output frames can be produced when @in_frames input
940  * frames are given to @convert.
941  *
942  * Returns: the number of output frames
943  */
944 gsize
945 gst_audio_converter_get_out_frames (GstAudioConverter * convert,
946     gsize in_frames)
947 {
948   return in_frames;
949 }
950
951 /**
952  * gst_audio_converter_get_in_frames:
953  * @convert: a #GstAudioConverter
954  * @out_frames: number of output frames
955  *
956  * Calculate how many input frames are currently needed by @convert to produce
957  * @out_frames of output frames.
958  *
959  * Returns: the number of input frames
960  */
961 gsize
962 gst_audio_converter_get_in_frames (GstAudioConverter * convert,
963     gsize out_frames)
964 {
965   return out_frames;
966 }
967
968 /**
969  * gst_audio_converter_get_max_latency:
970  * @convert: a #GstAudioConverter
971  *
972  * Get the maximum number of input frames that the converter would
973  * need before producing output.
974  *
975  * Returns: the latency of @convert as expressed in the number of
976  * frames.
977  */
978 gsize
979 gst_audio_converter_get_max_latency (GstAudioConverter * convert)
980 {
981   return 0;
982 }
983
984 /**
985  * gst_audio_converter_reset:
986  * @convert: a #GstAudioConverter
987  *
988  * Reset @convert to the state it was when it was first created, clearing
989  * any history it might currently have.
990  */
991 void
992 gst_audio_converter_reset (GstAudioConverter * convert)
993 {
994   if (convert->quant)
995     gst_audio_quantize_reset (convert->quant);
996 }
997
998 /**
999  * gst_audio_converter_samples:
1000  * @convert: a #GstAudioConverter
1001  * @flags: extra #GstAudioConverterFlags
1002  * @in: input frames
1003  * @in_frames: number of input frames
1004  * @out: output frames
1005  * @out_frames: number of output frames
1006  *
1007  * Perform the conversion with @in_frames in @in to @out_frames in @out
1008  * using @convert.
1009  *
1010  * In case the samples are interleaved, @in and @out must point to an
1011  * array with a single element pointing to a block of interleaved samples.
1012  *
1013  * If non-interleaved samples are used, @in and @out must point to an
1014  * array with pointers to memory blocks, one for each channel.
1015  *
1016  * @in may be %NULL, in which case @in_frames of silence samples are processed
1017  * by the converter.
1018  *
1019  * This function always produces @out_frames of output and consumes @in_frames of
1020  * input. Use gst_audio_converter_get_out_frames() and
1021  * gst_audio_converter_get_in_frames() to make sure @in_frames and @out_frames
1022  * are matching and @in and @out point to enough memory.
1023  *
1024  * Returns: %TRUE is the conversion could be performed.
1025  */
1026 gboolean
1027 gst_audio_converter_samples (GstAudioConverter * convert,
1028     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1029     gpointer out[], gsize out_frames)
1030 {
1031   g_return_val_if_fail (convert != NULL, FALSE);
1032   g_return_val_if_fail (out != NULL, FALSE);
1033
1034   in_frames = MIN (in_frames, out_frames);
1035
1036   if (in_frames == 0) {
1037     GST_LOG ("skipping empty buffer");
1038     return TRUE;
1039   }
1040   return convert->convert (convert, flags, in, in_frames, out, out_frames);
1041 }