2 * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
3 * (C) 2015 Wim Taymans <wim.taymans@gmail.com>
5 * audioconverter.c: Convert audio to different audio formats automatically
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.
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.
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.
30 #include "audio-converter.h"
31 #include "gstaudiopack.h"
34 * SECTION:audioconverter
35 * @short_description: Generic audio conversion
39 * This object is used to convert audio samples from one format to another.
40 * The object can perform conversion of:
43 * audio format with optional dithering and noise shaping
49 * audio channels and channel layout
55 #ifndef GST_DISABLE_GST_DEBUG
56 #define GST_CAT_DEFAULT ensure_debug_category()
57 static GstDebugCategory *
58 ensure_debug_category (void)
60 static gsize cat_gonce = 0;
62 if (g_once_init_enter (&cat_gonce)) {
65 cat_done = (gsize) _gst_debug_category_new ("audio-converter", 0,
66 "audio-converter object");
68 g_once_init_leave (&cat_gonce, cat_done);
71 return (GstDebugCategory *) cat_gonce;
74 #define ensure_debug_category() /* NOOP */
75 #endif /* GST_DISABLE_GST_DEBUG */
77 typedef struct _AudioChain AudioChain;
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);
84 /* int/int int/float float/int float/float
86 * unpack S32 S32 F64 F64
88 * channel mix S32 F64 F64 F64
91 * pack S32 F64 S32 F64
98 struct _GstAudioConverter
103 GstStructure *config;
105 GstAudioConverterFlags flags;
106 GstAudioFormat current_format;
107 GstAudioLayout current_layout;
108 gint current_channels;
110 gboolean in_writable;
119 AudioChain *unpack_chain;
122 AudioConvertFunc convert_in;
123 AudioChain *convert_in_chain;
126 gboolean mix_passthrough;
127 GstAudioChannelMixer *mix;
128 AudioChain *mix_chain;
131 GstAudioResampler *resampler;
132 AudioChain *resample_chain;
135 AudioConvertFunc convert_out;
136 AudioChain *convert_out_chain;
139 GstAudioQuantize *quant;
140 AudioChain *quant_chain;
143 gboolean out_default;
144 AudioChain *pack_chain;
146 AudioConvertSamplesFunc convert;
149 typedef gboolean (*AudioChainFunc) (AudioChain * chain, gpointer user_data);
150 typedef gpointer *(*AudioChainAllocFunc) (AudioChain * chain, gsize num_samples,
157 AudioChainFunc make_func;
158 gpointer make_func_data;
159 GDestroyNotify make_func_notify;
161 const GstAudioFormatInfo *finfo;
169 AudioChainAllocFunc alloc_func;
173 gsize allocated_samples;
180 audio_chain_new (AudioChain * prev, GstAudioConverter * convert)
184 chain = g_slice_new0 (AudioChain);
187 if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
189 chain->blocks = convert->current_channels;
191 chain->inc = convert->current_channels;
194 chain->finfo = gst_audio_format_get_info (convert->current_format);
195 chain->stride = (chain->finfo->width * chain->inc) / 8;
201 audio_chain_set_make_func (AudioChain * chain,
202 AudioChainFunc make_func, gpointer user_data, GDestroyNotify notify)
204 chain->make_func = make_func;
205 chain->make_func_data = user_data;
206 chain->make_func_notify = notify;
210 audio_chain_free (AudioChain * chain)
212 GST_LOG ("free chain %p", chain);
213 if (chain->make_func_notify)
214 chain->make_func_notify (chain->make_func_data);
216 g_slice_free (AudioChain, chain);
220 audio_chain_alloc_samples (AudioChain * chain, gsize num_samples)
222 return chain->alloc_func (chain, num_samples, chain->alloc_data);
226 audio_chain_set_samples (AudioChain * chain, gpointer * samples,
229 GST_LOG ("set samples %p %" G_GSIZE_FORMAT, samples, num_samples);
231 chain->samples = samples;
232 chain->num_samples = num_samples;
236 audio_chain_get_samples (AudioChain * chain, gsize * avail)
240 while (!chain->samples)
241 chain->make_func (chain, chain->make_func_data);
243 res = chain->samples;
244 *avail = chain->num_samples;
245 chain->samples = NULL;
252 get_opt_uint (GstAudioConverter * convert, const gchar * opt, guint def)
255 if (!gst_structure_get_uint (convert->config, opt, &res))
262 get_opt_enum (GstAudioConverter * convert, const gchar * opt, GType type,
266 if (!gst_structure_get_enum (convert->config, opt, type, &res))
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
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)
289 copy_config (GQuark field_id, const GValue * value, gpointer user_data)
291 GstAudioConverter *convert = user_data;
293 gst_structure_id_set_value (convert->config, field_id, value);
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
305 * Set @in_rate, @out_rate and @config as extra configuration for @convert.
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.
310 * @config can be %NULL, in which case, the current configuration is not
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().
317 * Look at the #GST_AUDIO_CONVERTER_OPT_* fields to check valid configuration
320 * Returns: %TRUE when the new parameters could be set
323 gst_audio_converter_update_config (GstAudioConverter * convert,
324 gint in_rate, gint out_rate, GstStructure * config)
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);
330 GST_LOG ("new rate %d -> %d", in_rate, out_rate);
333 in_rate = convert->in.rate;
335 out_rate = convert->out.rate;
337 convert->in.rate = in_rate;
338 convert->out.rate = out_rate;
340 if (convert->resampler)
341 gst_audio_resampler_update (convert->resampler, in_rate, out_rate, config);
344 gst_structure_foreach (config, copy_config, convert);
345 gst_structure_free (config);
352 * gst_audio_converter_get_config:
353 * @convert: a #GstAudioConverter
354 * @in_rate: result input rate
355 * @out_rate: result output rate
357 * Get the current configuration of @convert.
359 * Returns: a #GstStructure that remains valid for as long as @convert is valid
360 * or until gst_audio_converter_update_config() is called.
363 gst_audio_converter_get_config (GstAudioConverter * convert,
364 gint * in_rate, gint * out_rate)
366 g_return_val_if_fail (convert != NULL, NULL);
369 *in_rate = convert->in.rate;
371 *out_rate = convert->out.rate;
373 return convert->config;
377 get_output_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
379 GstAudioConverter *convert = user_data;
381 GST_LOG ("output samples %p %" G_GSIZE_FORMAT, convert->out_data,
384 return convert->out_data;
387 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
391 get_temp_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
393 if (num_samples > chain->allocated_samples) {
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
399 gsize needed = (stride + sizeof (gpointer)) * chain->blocks + ALIGN - 1;
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;
406 /* pointer to the data, make sure it's 16 bytes aligned */
407 s = MEM_ALIGN (&chain->tmp[chain->blocks], ALIGN);
409 /* set up the pointers */
410 for (i = 0; i < chain->blocks; i++)
411 chain->tmp[i] = s + i * stride;
413 GST_LOG ("temp samples %p %" G_GSIZE_FORMAT, chain->tmp, num_samples);
419 do_unpack (AudioChain * chain, gpointer user_data)
421 GstAudioConverter *convert = user_data;
424 gboolean in_writable;
426 in_writable = convert->in_writable;
427 num_samples = convert->in_frames;
429 if (!chain->allow_ip || !in_writable || !convert->in_default) {
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);
436 tmp = audio_chain_alloc_samples (chain, num_samples);
437 GST_LOG ("unpack to tmp %p, %" G_GSIZE_FORMAT, tmp, num_samples);
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],
445 memcpy (tmp[i], convert->in_data[i], num_samples * chain->stride);
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);
455 for (i = 0; i < chain->blocks; i++) {
456 gst_audio_format_fill_silence (chain->finfo, tmp[i],
457 num_samples * chain->inc);
461 tmp = convert->in_data;
462 GST_LOG ("get in samples %p", tmp);
464 audio_chain_set_samples (chain, tmp, num_samples);
470 do_convert_in (AudioChain * chain, gpointer user_data)
473 GstAudioConverter *convert = user_data;
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);
481 for (i = 0; i < chain->blocks; i++)
482 convert->convert_in (out[i], in[i], num_samples * chain->inc);
484 audio_chain_set_samples (chain, out, num_samples);
490 do_mix (AudioChain * chain, gpointer user_data)
493 GstAudioConverter *convert = user_data;
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);
500 gst_audio_channel_mixer_samples (convert->mix, in, out, num_samples);
502 audio_chain_set_samples (chain, out, num_samples);
508 do_resample (AudioChain * chain, gpointer user_data)
510 GstAudioConverter *convert = user_data;
512 gsize in_frames, out_frames;
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));
518 GST_LOG ("resample %p %p,%" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT, in,
519 out, in_frames, out_frames);
521 gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
524 audio_chain_set_samples (chain, out, out_frames);
530 do_convert_out (AudioChain * chain, gpointer user_data)
532 GstAudioConverter *convert = user_data;
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);
541 for (i = 0; i < chain->blocks; i++)
542 convert->convert_out (out[i], in[i], num_samples * chain->inc);
544 audio_chain_set_samples (chain, out, num_samples);
550 do_quantize (AudioChain * chain, gpointer user_data)
552 GstAudioConverter *convert = user_data;
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);
560 gst_audio_quantize_samples (convert->quant, in, out, num_samples);
562 audio_chain_set_samples (chain, out, num_samples);
568 is_intermediate_format (GstAudioFormat format)
570 return (format == GST_AUDIO_FORMAT_S16 ||
571 format == GST_AUDIO_FORMAT_S32 ||
572 format == GST_AUDIO_FORMAT_F32 || format == GST_AUDIO_FORMAT_F64);
576 chain_unpack (GstAudioConverter * convert)
579 GstAudioInfo *in = &convert->in;
580 GstAudioInfo *out = &convert->out;
581 gboolean same_format;
583 same_format = in->finfo->format == out->finfo->format;
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;
590 convert->current_format = in->finfo->unpack_format;
592 convert->current_layout = in->layout;
593 convert->current_channels = in->channels;
595 convert->in_default = convert->current_format == in->finfo->format;
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));
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);
610 chain_convert_in (GstAudioConverter * convert, AudioChain * prev)
612 gboolean in_int, out_int;
613 GstAudioInfo *in = &convert->in;
614 GstAudioInfo *out = &convert->out;
616 in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
617 out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
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;
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);
633 chain_mix (GstAudioConverter * convert, AudioChain * prev)
635 GstAudioChannelMixerFlags flags;
636 GstAudioInfo *in = &convert->in;
637 GstAudioInfo *out = &convert->out;
638 GstAudioFormat format = convert->current_format;
641 GST_AUDIO_INFO_IS_UNPOSITIONED (in) ?
642 GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_IN : 0;
644 GST_AUDIO_INFO_IS_UNPOSITIONED (out) ?
645 GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_OUT : 0;
647 convert->current_channels = out->channels;
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);
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);
668 chain_resample (GstAudioConverter * convert, AudioChain * prev)
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;
678 variable_rate = convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE;
680 if (in->rate != out->rate || variable_rate) {
681 method = GET_OPT_RESAMPLER_METHOD (convert);
684 if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED)
685 flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED;
687 flags |= GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE;
690 gst_audio_resampler_new (method, flags, format, channels, in->rate,
691 out->rate, convert->config);
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);
702 chain_convert_out (GstAudioConverter * convert, AudioChain * prev)
704 gboolean in_int, out_int;
705 GstAudioInfo *in = &convert->in;
706 GstAudioInfo *out = &convert->out;
708 in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
709 out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
711 if (!in_int && out_int) {
712 convert->convert_out = (AudioConvertFunc) audio_orc_double_to_s32;
713 convert->current_format = GST_AUDIO_FORMAT_S32;
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);
725 chain_quantize (GstAudioConverter * convert, AudioChain * prev)
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;
734 dither = GET_OPT_DITHER_METHOD (convert);
735 ns = GET_OPT_NOISE_SHAPING_METHOD (convert);
737 cur_finfo = gst_audio_format_get_info (convert->current_format);
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);
743 in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (cur_finfo);
744 out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
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
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");
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;
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);
767 gst_audio_quantize_new (dither, ns, 0, convert->current_format,
768 out->channels, 1U << (32 - out_depth));
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);
779 chain_pack (GstAudioConverter * convert, AudioChain * prev)
781 GstAudioInfo *out = &convert->out;
782 GstAudioFormat format = convert->current_format;
784 convert->current_format = out->finfo->format;
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));
794 setup_allocators (GstAudioConverter * convert)
797 AudioChainAllocFunc alloc_func;
800 /* start with using dest if we can directly write into it */
801 if (convert->out_default) {
802 alloc_func = get_output_samples;
805 alloc_func = get_temp_samples;
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);
816 if (!chain->pass_alloc) {
817 /* can't pass allocator, make new temp line allocator */
818 alloc_func = get_temp_samples;
825 converter_passthrough (GstAudioConverter * convert,
826 GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
827 gpointer out[], gsize out_frames)
833 chain = convert->pack_chain;
835 samples = in_frames * chain->inc;
837 GST_LOG ("passthrough: %" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " samples",
843 bytes = samples * (convert->in.bpf / convert->in.channels);
845 for (i = 0; i < chain->blocks; i++)
846 memcpy (out[i], in[i], bytes);
848 for (i = 0; i < chain->blocks; i++)
849 gst_audio_format_fill_silence (convert->in.finfo, out[i], samples);
855 converter_generic (GstAudioConverter * convert,
856 GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
857 gpointer out[], gsize out_frames)
864 chain = convert->pack_chain;
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;
872 /* get frames to pack */
873 tmp = audio_chain_get_samples (chain, &produced);
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);
886 converter_resample (GstAudioConverter * convert,
887 GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
888 gpointer out[], gsize out_frames)
890 gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
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
903 * Create a new #GstAudioConverter that is able to convert between @in and @out
906 * @config contains extra configuration options, see #GST_VIDEO_CONVERTER_OPT_*
907 * parameters for details about the options and values.
909 * Returns: a #GstAudioConverter or %NULL if conversion is not possible.
912 gst_audio_converter_new (GstAudioConverterFlags flags, GstAudioInfo * in_info,
913 GstAudioInfo * out_info, GstStructure * config)
915 GstAudioConverter *convert;
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);
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)))
928 convert = g_slice_new0 (GstAudioConverter);
930 convert->flags = flags;
931 convert->in = *in_info;
932 convert->out = *out_info;
935 convert->config = gst_structure_new_empty ("GstAudioConverter");
937 gst_audio_converter_update_config (convert, 0, 0, config);
939 GST_INFO ("unitsizes: %d -> %d", in_info->bpf, out_info->bpf);
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);
954 convert->pack_chain = chain_pack (convert, prev);
956 convert->convert = converter_generic;
959 if (out_info->finfo->format == in_info->finfo->format
960 && convert->mix_passthrough) {
961 if (convert->resampler == NULL) {
963 ("same formats, no resampler and passthrough mixing -> passthrough");
964 convert->convert = converter_passthrough;
966 if (is_intermediate_format (in_info->finfo->format)) {
967 GST_INFO ("same formats, and passthrough mixing -> only resampling");
968 convert->convert = converter_resample;
973 setup_allocators (convert);
980 GST_WARNING ("unpositioned channels");
986 * gst_audio_converter_free:
987 * @convert: a #GstAudioConverter
989 * Free a previously allocated @convert instance.
992 gst_audio_converter_free (GstAudioConverter * convert)
994 g_return_if_fail (convert != NULL);
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);
1009 gst_audio_quantize_free (convert->quant);
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);
1017 gst_structure_free (convert->config);
1019 g_slice_free (GstAudioConverter, convert);
1023 * gst_audio_converter_get_out_frames:
1024 * @convert: a #GstAudioConverter
1025 * @in_frames: number of input frames
1027 * Calculate how many output frames can be produced when @in_frames input
1028 * frames are given to @convert.
1030 * Returns: the number of output frames
1033 gst_audio_converter_get_out_frames (GstAudioConverter * convert,
1036 if (convert->resampler)
1037 return gst_audio_resampler_get_out_frames (convert->resampler, in_frames);
1043 * gst_audio_converter_get_in_frames:
1044 * @convert: a #GstAudioConverter
1045 * @out_frames: number of output frames
1047 * Calculate how many input frames are currently needed by @convert to produce
1048 * @out_frames of output frames.
1050 * Returns: the number of input frames
1053 gst_audio_converter_get_in_frames (GstAudioConverter * convert,
1056 if (convert->resampler)
1057 return gst_audio_resampler_get_in_frames (convert->resampler, out_frames);
1063 * gst_audio_converter_get_max_latency:
1064 * @convert: a #GstAudioConverter
1066 * Get the maximum number of input frames that the converter would
1067 * need before producing output.
1069 * Returns: the latency of @convert as expressed in the number of
1073 gst_audio_converter_get_max_latency (GstAudioConverter * convert)
1075 if (convert->resampler)
1076 return gst_audio_resampler_get_max_latency (convert->resampler);
1082 * gst_audio_converter_reset:
1083 * @convert: a #GstAudioConverter
1085 * Reset @convert to the state it was when it was first created, clearing
1086 * any history it might currently have.
1089 gst_audio_converter_reset (GstAudioConverter * convert)
1091 if (convert->resampler)
1092 gst_audio_resampler_reset (convert->resampler);
1094 gst_audio_quantize_reset (convert->quant);
1098 * gst_audio_converter_samples:
1099 * @convert: a #GstAudioConverter
1100 * @flags: extra #GstAudioConverterFlags
1102 * @in_frames: number of input frames
1103 * @out: output frames
1104 * @out_frames: number of output frames
1106 * Perform the conversion with @in_frames in @in to @out_frames in @out
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.
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.
1115 * @in may be %NULL, in which case @in_frames of silence samples are processed
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.
1123 * Returns: %TRUE is the conversion could be performed.
1126 gst_audio_converter_samples (GstAudioConverter * convert,
1127 GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1128 gpointer out[], gsize out_frames)
1130 g_return_val_if_fail (convert != NULL, FALSE);
1131 g_return_val_if_fail (out != NULL, FALSE);
1133 if (in_frames == 0) {
1134 GST_LOG ("skipping empty buffer");
1137 return convert->convert (convert, flags, in, in_frames, out, out_frames);