From f5a3f705716323c8b667bc1b593bd73227c99f78 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 10 Dec 2015 17:46:26 +0100 Subject: [PATCH] audio: adapt API for non-interleaved formats Allow an array of sample blocks to be passed to the channel mix and quantizer functions to support non-interleaved formats. --- gst-libs/gst/audio/audio-channel-mix.c | 14 +++-- gst-libs/gst/audio/audio-channel-mix.h | 4 +- gst-libs/gst/audio/audio-converter.c | 4 +- gst-libs/gst/audio/audio-quantize.c | 84 +++++++++++++++----------- gst-libs/gst/audio/audio-quantize.h | 4 +- gst/audioconvert/gstaudioconvert.c | 5 +- 6 files changed, 69 insertions(+), 46 deletions(-) diff --git a/gst-libs/gst/audio/audio-channel-mix.c b/gst-libs/gst/audio/audio-channel-mix.c index 58f5198149..e7a8d296c3 100644 --- a/gst-libs/gst/audio/audio-channel-mix.c +++ b/gst-libs/gst/audio/audio-channel-mix.c @@ -882,19 +882,25 @@ gst_audio_channel_mix_is_passthrough (GstAudioChannelMix * mix) * @mix: a #GstAudioChannelMix * @format: a #GstAudioFormat * @layout: a #GstAudioLayout - * @in_data: input samples - * @out_data: output samples + * @in: input samples + * @out: output samples * @samples: number of samples * + * In case the samples are interleaved, @in and @out must point to an + * array with a single element pointing to a block of interleaved samples. + * + * If non-interleaved samples are used, @in and @out must point to an + * array with pointers to memory blocks, one for each channel. + * * Perform channel mixing on @in_data and write the result to @out_data. * @in_data and @out_data need to be in @format and @layout. */ void gst_audio_channel_mix_samples (GstAudioChannelMix * mix, - const gpointer in_data, gpointer out_data, gint samples) + const gpointer in[], gpointer out[], gint samples) { g_return_if_fail (mix != NULL); g_return_if_fail (mix->matrix != NULL); - mix->func (mix, in_data, out_data, samples); + mix->func (mix, in[0], out[0], samples); } diff --git a/gst-libs/gst/audio/audio-channel-mix.h b/gst-libs/gst/audio/audio-channel-mix.h index caf08a2180..5222c200ac 100644 --- a/gst-libs/gst/audio/audio-channel-mix.h +++ b/gst-libs/gst/audio/audio-channel-mix.h @@ -61,8 +61,8 @@ gboolean gst_audio_channel_mix_is_passthrough (GstAudioChannelMix *mix); * Do actual mixing. */ void gst_audio_channel_mix_samples (GstAudioChannelMix * mix, - const gpointer in_data, - gpointer out_data, + const gpointer in[], + gpointer out[], gint samples); #endif /* __GST_AUDIO_CHANNEL_MIX_H__ */ diff --git a/gst-libs/gst/audio/audio-converter.c b/gst-libs/gst/audio/audio-converter.c index 9d789f7bb6..91367329fc 100644 --- a/gst-libs/gst/audio/audio-converter.c +++ b/gst-libs/gst/audio/audio-converter.c @@ -476,7 +476,7 @@ gst_audio_converter_samples (GstAudioConverter * convert, else outbuf = tmpbuf; - gst_audio_channel_mix_samples (convert->mix, inp, outbuf, in_samples); + gst_audio_channel_mix_samples (convert->mix, &inp, &outbuf, in_samples); inp = outbuf; } /* step 4, optional convert F64 -> S32 for quantize */ @@ -497,7 +497,7 @@ gst_audio_converter_samples (GstAudioConverter * convert, else outbuf = tmpbuf; - gst_audio_quantize_samples (convert->quant, outbuf, inp, in_samples); + gst_audio_quantize_samples (convert->quant, &inp, &outbuf, in_samples); inp = outbuf; } diff --git a/gst-libs/gst/audio/audio-quantize.c b/gst-libs/gst/audio/audio-quantize.c index ad2c00945b..49dfb26e32 100644 --- a/gst-libs/gst/audio/audio-quantize.c +++ b/gst-libs/gst/audio/audio-quantize.c @@ -42,15 +42,16 @@ struct _GstAudioQuantize GstAudioNoiseShapingMethod ns; GstAudioQuantizeFlags flags; GstAudioFormat format; - guint channels; guint quantizer; + guint stride; + guint blocks; guint shift; guint32 mask, bias; /* last random number generated per channel for hifreq TPDF dither */ gpointer last_random; - /* contains the past quantization errors, error[out_channels][count] */ + /* contains the past quantization errors, error[channels][count] */ guint error_size; gpointer error_buf; /* buffer with dither values */ @@ -76,7 +77,7 @@ gst_audio_quantize_quantize_memcpy (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint samples) { if (src != dst) - memcpy (dst, src, samples * sizeof (gint32) * quant->channels); + memcpy (dst, src, samples * sizeof (gint32) * quant->stride); } /* Quantize functions for gint32 as intermediate format */ @@ -85,7 +86,7 @@ gst_audio_quantize_quantize_int_none_none (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint samples) { audio_orc_int_bias (dst, src, quant->bias, ~quant->mask, - samples * quant->channels); + samples * quant->stride); } /* This is the base function, implementing a linear congruential generator @@ -114,8 +115,8 @@ static void setup_dither_buf (GstAudioQuantize * quant, gint samples) { gboolean need_init = FALSE; - gint channels = quant->channels; - gint i, len = samples * channels; + gint stride = quant->stride; + gint i, len = samples * stride; guint shift = quant->shift; guint32 bias; gint32 dither, *d; @@ -156,8 +157,8 @@ setup_dither_buf (GstAudioQuantize * quant, gint samples) dither = 1 << (shift - 1); for (i = 0; i < len; i++) { tmp = RANDOM_INT_DITHER (dither); - d[i] = bias + tmp - last_random[i % channels]; - last_random[i % channels] = tmp; + d[i] = bias + tmp - last_random[i % stride]; + last_random[i % stride] = tmp; } break; } @@ -171,20 +172,20 @@ gst_audio_quantize_quantize_int_dither_none (GstAudioQuantize * quant, setup_dither_buf (quant, samples); audio_orc_int_dither (dst, src, quant->dither_buf, ~quant->mask, - samples * quant->channels); + samples * quant->stride); } static void setup_error_buf (GstAudioQuantize * quant, gint samples) { - gint channels = quant->channels; - gint len = (samples + quant->n_coeffs) * channels; + gint stride = quant->stride; + gint len = (samples + quant->n_coeffs) * stride; if (quant->error_size < len) { quant->error_buf = g_realloc (quant->error_buf, len * sizeof (gint32)); if (quant->error_size == 0) memset ((gint32 *) quant->error_buf, 0, - channels * quant->n_coeffs * sizeof (gint32)); + stride * quant->n_coeffs * sizeof (gint32)); quant->error_size = len; } } @@ -194,15 +195,15 @@ gst_audio_quantize_quantize_int_dither_feedback (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint samples) { guint32 mask; - gint i, len, channels; + gint i, len, stride; const gint32 *s = src; gint32 *dith, *d = dst, v, o, *e, err; setup_dither_buf (quant, samples); setup_error_buf (quant, samples); - channels = quant->channels; - len = samples * channels; + stride = quant->stride; + len = samples * stride; dith = quant->dither_buf; e = quant->error_buf; mask = ~quant->mask; @@ -216,11 +217,11 @@ gst_audio_quantize_quantize_int_dither_feedback (GstAudioQuantize * quant, ADDSS (v, err); v &= mask; /* store new error */ - e[i + channels] = e[i] + (v - o); + e[i + stride] = e[i] + (v - o); /* store result */ d[i] = v; } - memmove (e, &e[len], sizeof (gint32) * channels); + memmove (e, &e[len], sizeof (gint32) * stride); } #define SHIFT 10 @@ -234,15 +235,15 @@ gst_audio_quantize_quantize_int_dither_noise_shape (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint samples) { guint32 mask; - gint i, j, k, len, channels, nc; + gint i, j, k, len, stride, nc; const gint32 *s = src; gint32 *c, *dith, *d = dst, v, o, *e, err; setup_dither_buf (quant, samples); setup_error_buf (quant, samples); - channels = quant->channels; - len = samples * channels; + stride = quant->stride; + len = samples * stride; dith = quant->dither_buf; e = quant->error_buf; c = quant->coeffs; @@ -253,7 +254,7 @@ gst_audio_quantize_quantize_int_dither_noise_shape (GstAudioQuantize * quant, v = s[i]; /* combine and remove error */ err = 0; - for (j = 0, k = i; j < nc; j++, k += channels) + for (j = 0, k = i; j < nc; j++, k += stride) err -= e[k] * c[j]; err = (err + SROUND) >> (SREDUCE); ADDSS (v, err); @@ -268,7 +269,7 @@ gst_audio_quantize_quantize_int_dither_noise_shape (GstAudioQuantize * quant, /* store result */ d[i] = v; } - memmove (e, &e[len], sizeof (gint32) * channels * nc); + memmove (e, &e[len], sizeof (gint32) * stride * nc); } #define MAKE_QUANTIZE_FUNC_NAME(name) \ @@ -355,7 +356,7 @@ gst_audio_quantize_setup_noise_shaping (GstAudioQuantize * quant) if (n_coeffs) { quant->n_coeffs = n_coeffs; - q = quant->coeffs = g_new0 (gint32, quant->channels * n_coeffs); + q = quant->coeffs = g_new0 (gint32, n_coeffs); for (i = 0; i < n_coeffs; i++) q[i] = floor (coeffs[i] * (1 << SHIFT) + 0.5); } @@ -367,7 +368,7 @@ gst_audio_quantize_setup_dither (GstAudioQuantize * quant) { switch (quant->dither) { case GST_AUDIO_DITHER_TPDF_HF: - quant->last_random = g_new0 (gint32, quant->channels); + quant->last_random = g_new0 (gint32, quant->stride); break; case GST_AUDIO_DITHER_RPDF: case GST_AUDIO_DITHER_TPDF: @@ -440,7 +441,13 @@ gst_audio_quantize_new (GstAudioDitherMethod dither, quant->ns = ns; quant->flags = flags; quant->format = format; - quant->channels = channels; + if (flags & GST_AUDIO_QUANTIZE_FLAG_NON_INTERLEAVED) { + quant->stride = 1; + quant->blocks = channels; + } else { + quant->stride = channels; + quant->blocks = 1; + } quant->quantizer = quantizer; quant->shift = count_power (quantizer); @@ -479,22 +486,31 @@ gst_audio_quantize_free (GstAudioQuantize * quant) /** * gst_audio_quantize_samples: * @quant: a #GstAudioQuantize - * @src: source samples - * @dst: output samples + * @in: input samples + * @out: output samples * @samples: number of samples * - * Perform quantization on @samples in @src and write the result to @dst. + * Perform quantization on @samples in @in and write the result to @out. * - * @src and @dst may point to the same memory location, in which case samples will be + * In case the samples are interleaved, @in and @out must point to an + * array with a single element pointing to a block of interleaved samples. + * + * If non-interleaved samples are used, @in and @out must point to an + * array with pointers to memory blocks, one for each channel. + * + * @in and @out may point to the same memory location, in which case samples will be * modified in-place. */ void gst_audio_quantize_samples (GstAudioQuantize * quant, - const gpointer src, gpointer dst, guint samples) + const gpointer in[], gpointer out[], guint samples) { - g_return_if_fail (quant != NULL); - g_return_if_fail (dst != NULL || samples == 0); - g_return_if_fail (src != NULL || samples == 0); + guint i; - quant->quantize (quant, dst, src, samples); + g_return_if_fail (quant != NULL); + g_return_if_fail (out != NULL || samples == 0); + g_return_if_fail (in != NULL || samples == 0); + + for (i = 0; i < quant->blocks; i++) + quant->quantize (quant, in[i], out[i], samples); } diff --git a/gst-libs/gst/audio/audio-quantize.h b/gst-libs/gst/audio/audio-quantize.h index bc1c79359c..0c70237f26 100644 --- a/gst-libs/gst/audio/audio-quantize.h +++ b/gst-libs/gst/audio/audio-quantize.h @@ -91,7 +91,7 @@ GstAudioQuantize * gst_audio_quantize_new (GstAudioDitherMethod dither, void gst_audio_quantize_free (GstAudioQuantize * quant); void gst_audio_quantize_samples (GstAudioQuantize * quant, - const gpointer src, - gpointer dst, guint samples); + const gpointer in[], + gpointer out[], guint samples); #endif /* __GST_AUDIO_QUANTIZE_H__ */ diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index c3b871b9b3..72a39f339a 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -735,8 +735,9 @@ gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf, flags |= GST_AUDIO_CONVERTER_FLAG_SOURCE_WRITABLE; if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { - if (!gst_audio_converter_samples (this->convert, flags, srcmap.data, - samples, dstmap.data, samples, &consumed, &produced)) + if (!gst_audio_converter_samples (this->convert, flags, + (gpointer *) & srcmap.data, samples, (gpointer *) & dstmap.data, + samples, &consumed, &produced)) goto convert_error; } else { /* Create silence buffer */