mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
channelmix: simplify API a little
Remove the format and layout from the mix_samples function and use the format when creating the channel mixer object. Also use a flag to handle the unlikely case of non-interleaved samples like we do elsewhere.
This commit is contained in:
parent
7f5104f52f
commit
9fbe0386d0
3 changed files with 102 additions and 92 deletions
|
@ -76,7 +76,6 @@ struct _GstAudioConverter
|
||||||
|
|
||||||
AudioConvertFunc convert_in;
|
AudioConvertFunc convert_in;
|
||||||
|
|
||||||
GstAudioFormat mix_format;
|
|
||||||
gboolean mix_passthrough;
|
gboolean mix_passthrough;
|
||||||
GstAudioChannelMix *mix;
|
GstAudioChannelMix *mix;
|
||||||
|
|
||||||
|
@ -263,8 +262,8 @@ gst_audio_converter_new (GstAudioInfo * in, GstAudioInfo * out,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* step 3, channel mix */
|
/* step 3, channel mix */
|
||||||
convert->mix_format = format;
|
convert->mix =
|
||||||
convert->mix = gst_audio_channel_mix_new (flags, in->channels, in->position,
|
gst_audio_channel_mix_new (flags, format, in->channels, in->position,
|
||||||
out->channels, out->position);
|
out->channels, out->position);
|
||||||
convert->mix_passthrough =
|
convert->mix_passthrough =
|
||||||
gst_audio_channel_mix_is_passthrough (convert->mix);
|
gst_audio_channel_mix_is_passthrough (convert->mix);
|
||||||
|
@ -427,8 +426,7 @@ gst_audio_converter_samples (GstAudioConverter * convert,
|
||||||
else
|
else
|
||||||
outbuf = tmpbuf;
|
outbuf = tmpbuf;
|
||||||
|
|
||||||
gst_audio_channel_mix_samples (convert->mix, convert->mix_format,
|
gst_audio_channel_mix_samples (convert->mix, src, outbuf, samples);
|
||||||
convert->in.layout, src, outbuf, samples);
|
|
||||||
src = outbuf;
|
src = outbuf;
|
||||||
}
|
}
|
||||||
/* step 4, optional convert F64 -> S32 for quantize */
|
/* step 4, optional convert F64 -> S32 for quantize */
|
||||||
|
|
|
@ -31,9 +31,13 @@
|
||||||
|
|
||||||
#define INT_MATRIX_FACTOR_EXPONENT 10
|
#define INT_MATRIX_FACTOR_EXPONENT 10
|
||||||
|
|
||||||
|
typedef void (*MixFunc) (GstAudioChannelMix * mix, const gpointer src,
|
||||||
|
gpointer dst, gint samples);
|
||||||
|
|
||||||
struct _GstAudioChannelMix
|
struct _GstAudioChannelMix
|
||||||
{
|
{
|
||||||
GstAudioChannelMixFlags flags;
|
GstAudioChannelMixFlags flags;
|
||||||
|
GstAudioFormat format;
|
||||||
|
|
||||||
gint in_channels;
|
gint in_channels;
|
||||||
gint out_channels;
|
gint out_channels;
|
||||||
|
@ -49,6 +53,8 @@ struct _GstAudioChannelMix
|
||||||
* this is matrix * (2^10) as integers */
|
* this is matrix * (2^10) as integers */
|
||||||
gint **matrix_int;
|
gint **matrix_int;
|
||||||
|
|
||||||
|
MixFunc func;
|
||||||
|
|
||||||
gpointer tmp;
|
gpointer tmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -681,72 +687,6 @@ gst_audio_channel_mix_setup_matrix (GstAudioChannelMix * mix)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_audio_channel_mix_new:
|
|
||||||
* @flags:
|
|
||||||
* @in_channels:
|
|
||||||
* @in_position:
|
|
||||||
* @out_channels:
|
|
||||||
* @out_position:
|
|
||||||
*
|
|
||||||
* Create a new channel mixer object.
|
|
||||||
*
|
|
||||||
* Returns: a new #GstAudioChannelMix object. Free with gst_audio_channel_mix_free()
|
|
||||||
* after usage.
|
|
||||||
*/
|
|
||||||
GstAudioChannelMix *
|
|
||||||
gst_audio_channel_mix_new (GstAudioChannelMixFlags flags,
|
|
||||||
gint in_channels,
|
|
||||||
GstAudioChannelPosition in_position[64],
|
|
||||||
gint out_channels, GstAudioChannelPosition out_position[64])
|
|
||||||
{
|
|
||||||
GstAudioChannelMix *mix;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
mix = g_slice_new0 (GstAudioChannelMix);
|
|
||||||
mix->flags = flags;
|
|
||||||
mix->in_channels = in_channels;
|
|
||||||
mix->out_channels = out_channels;
|
|
||||||
for (i = 0; i < 64; i++) {
|
|
||||||
mix->in_position[i] = in_position[i];
|
|
||||||
mix->out_position[i] = out_position[i];
|
|
||||||
}
|
|
||||||
gst_audio_channel_mix_setup_matrix (mix);
|
|
||||||
|
|
||||||
return mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gst_audio_channel_mix_is_passthrough:
|
|
||||||
* @mix: a #GstAudioChannelMix
|
|
||||||
*
|
|
||||||
* Check if @mix is in passthrough.
|
|
||||||
*
|
|
||||||
* Returns: %TRUE is @mix is passthrough.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
gst_audio_channel_mix_is_passthrough (GstAudioChannelMix * mix)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
guint64 in_mask, out_mask;
|
|
||||||
|
|
||||||
/* only NxN matrices can be identities */
|
|
||||||
if (mix->in_channels != mix->out_channels)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* passthrough for 1->1 channels (MONO and NONE position are the same here) */
|
|
||||||
if (mix->in_channels == 1 && mix->out_channels == 1)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* passthrough if both channel masks are the same */
|
|
||||||
in_mask = out_mask = 0;
|
|
||||||
for (i = 0; i < mix->in_channels; i++) {
|
|
||||||
in_mask |= mix->in_position[i];
|
|
||||||
out_mask |= mix->out_position[i];
|
|
||||||
}
|
|
||||||
return in_mask == out_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IMPORTANT: out_data == in_data is possible, make sure to not overwrite data
|
/* IMPORTANT: out_data == in_data is possible, make sure to not overwrite data
|
||||||
* you might need later on! */
|
* you might need later on! */
|
||||||
static void
|
static void
|
||||||
|
@ -828,6 +768,91 @@ gst_audio_channel_mix_mix_double (GstAudioChannelMix * mix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_audio_channel_mix_new:
|
||||||
|
* @flags:
|
||||||
|
* @in_channels:
|
||||||
|
* @in_position:
|
||||||
|
* @out_channels:
|
||||||
|
* @out_position:
|
||||||
|
*
|
||||||
|
* Create a new channel mixer object.
|
||||||
|
*
|
||||||
|
* Returns: a new #GstAudioChannelMix object. Free with gst_audio_channel_mix_free()
|
||||||
|
* after usage.
|
||||||
|
*/
|
||||||
|
GstAudioChannelMix *
|
||||||
|
gst_audio_channel_mix_new (GstAudioChannelMixFlags flags,
|
||||||
|
GstAudioFormat format,
|
||||||
|
gint in_channels,
|
||||||
|
GstAudioChannelPosition in_position[64],
|
||||||
|
gint out_channels, GstAudioChannelPosition out_position[64])
|
||||||
|
{
|
||||||
|
GstAudioChannelMix *mix;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (format == GST_AUDIO_FORMAT_S32
|
||||||
|
|| format == GST_AUDIO_FORMAT_F64, NULL);
|
||||||
|
g_return_val_if_fail (in_channels > 0, NULL);
|
||||||
|
g_return_val_if_fail (out_channels > 0, NULL);
|
||||||
|
|
||||||
|
mix = g_slice_new0 (GstAudioChannelMix);
|
||||||
|
mix->flags = flags;
|
||||||
|
mix->format = format;
|
||||||
|
mix->in_channels = in_channels;
|
||||||
|
mix->out_channels = out_channels;
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
mix->in_position[i] = in_position[i];
|
||||||
|
mix->out_position[i] = out_position[i];
|
||||||
|
}
|
||||||
|
gst_audio_channel_mix_setup_matrix (mix);
|
||||||
|
|
||||||
|
switch (mix->format) {
|
||||||
|
case GST_AUDIO_FORMAT_S32:
|
||||||
|
mix->func = (MixFunc) gst_audio_channel_mix_mix_int;
|
||||||
|
break;
|
||||||
|
case GST_AUDIO_FORMAT_F64:
|
||||||
|
mix->func = (MixFunc) gst_audio_channel_mix_mix_double;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return mix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_audio_channel_mix_is_passthrough:
|
||||||
|
* @mix: a #GstAudioChannelMix
|
||||||
|
*
|
||||||
|
* Check if @mix is in passthrough.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE is @mix is passthrough.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_audio_channel_mix_is_passthrough (GstAudioChannelMix * mix)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
guint64 in_mask, out_mask;
|
||||||
|
|
||||||
|
/* only NxN matrices can be identities */
|
||||||
|
if (mix->in_channels != mix->out_channels)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* passthrough for 1->1 channels (MONO and NONE position are the same here) */
|
||||||
|
if (mix->in_channels == 1 && mix->out_channels == 1)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* passthrough if both channel masks are the same */
|
||||||
|
in_mask = out_mask = 0;
|
||||||
|
for (i = 0; i < mix->in_channels; i++) {
|
||||||
|
in_mask |= mix->in_position[i];
|
||||||
|
out_mask |= mix->out_position[i];
|
||||||
|
}
|
||||||
|
return in_mask == out_mask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_audio_channel_mix_samples:
|
* gst_audio_channel_mix_samples:
|
||||||
* @mix: a #GstAudioChannelMix
|
* @mix: a #GstAudioChannelMix
|
||||||
|
@ -841,25 +866,11 @@ gst_audio_channel_mix_mix_double (GstAudioChannelMix * mix,
|
||||||
* @in_data and @out_data need to be in @format and @layout.
|
* @in_data and @out_data need to be in @format and @layout.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_audio_channel_mix_samples (GstAudioChannelMix * mix, GstAudioFormat format,
|
gst_audio_channel_mix_samples (GstAudioChannelMix * mix,
|
||||||
GstAudioLayout layout, const gpointer in_data, gpointer out_data,
|
const gpointer in_data, gpointer out_data, gint samples)
|
||||||
gint samples)
|
|
||||||
{
|
{
|
||||||
g_return_if_fail (mix != NULL);
|
g_return_if_fail (mix != NULL);
|
||||||
g_return_if_fail (mix->matrix != NULL);
|
g_return_if_fail (mix->matrix != NULL);
|
||||||
g_return_if_fail (layout == GST_AUDIO_LAYOUT_INTERLEAVED);
|
|
||||||
|
|
||||||
switch (format) {
|
mix->func (mix, in_data, out_data, samples);
|
||||||
case GST_AUDIO_FORMAT_S32:
|
|
||||||
gst_audio_channel_mix_mix_int (mix, (const gint32 *) in_data,
|
|
||||||
(gint32 *) out_data, samples);
|
|
||||||
break;
|
|
||||||
case GST_AUDIO_FORMAT_F64:
|
|
||||||
gst_audio_channel_mix_mix_double (mix, (const gdouble *) in_data,
|
|
||||||
(gdouble *) out_data, samples);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix;
|
||||||
/**
|
/**
|
||||||
* GstAudioChannelMixFlags:
|
* GstAudioChannelMixFlags:
|
||||||
* @GST_AUDIO_CHANNEL_MIX_FLAGS_NONE: no flag
|
* @GST_AUDIO_CHANNEL_MIX_FLAGS_NONE: no flag
|
||||||
|
* @GST_AUDIO_CHANNEL_MIX_FLAGS_NON_INTERLEAVED: channels are not interleaved
|
||||||
* @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN: input channels are explicitly unpositioned
|
* @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN: input channels are explicitly unpositioned
|
||||||
* @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT: output channels are explicitly unpositioned
|
* @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT: output channels are explicitly unpositioned
|
||||||
*
|
*
|
||||||
|
@ -38,11 +39,13 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix;
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_AUDIO_CHANNEL_MIX_FLAGS_NONE = 0,
|
GST_AUDIO_CHANNEL_MIX_FLAGS_NONE = 0,
|
||||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 0),
|
GST_AUDIO_CHANNEL_MIX_FLAGS_NON_INTERLEAVED = (1 << 0),
|
||||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 1)
|
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 1),
|
||||||
|
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 2)
|
||||||
} GstAudioChannelMixFlags;
|
} GstAudioChannelMixFlags;
|
||||||
|
|
||||||
GstAudioChannelMix * gst_audio_channel_mix_new (GstAudioChannelMixFlags flags,
|
GstAudioChannelMix * gst_audio_channel_mix_new (GstAudioChannelMixFlags flags,
|
||||||
|
GstAudioFormat format,
|
||||||
gint in_channels,
|
gint in_channels,
|
||||||
GstAudioChannelPosition in_position[64],
|
GstAudioChannelPosition in_position[64],
|
||||||
gint out_channels,
|
gint out_channels,
|
||||||
|
@ -58,8 +61,6 @@ gboolean gst_audio_channel_mix_is_passthrough (GstAudioChannelMix *mix);
|
||||||
* Do actual mixing.
|
* Do actual mixing.
|
||||||
*/
|
*/
|
||||||
void gst_audio_channel_mix_samples (GstAudioChannelMix * mix,
|
void gst_audio_channel_mix_samples (GstAudioChannelMix * mix,
|
||||||
GstAudioFormat format,
|
|
||||||
GstAudioLayout layout,
|
|
||||||
const gpointer in_data,
|
const gpointer in_data,
|
||||||
gpointer out_data,
|
gpointer out_data,
|
||||||
gint samples);
|
gint samples);
|
||||||
|
|
Loading…
Reference in a new issue