mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 19:20:35 +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;
|
||||
|
||||
GstAudioFormat mix_format;
|
||||
gboolean mix_passthrough;
|
||||
GstAudioChannelMix *mix;
|
||||
|
||||
|
@ -263,8 +262,8 @@ gst_audio_converter_new (GstAudioInfo * in, GstAudioInfo * out,
|
|||
}
|
||||
|
||||
/* step 3, channel mix */
|
||||
convert->mix_format = format;
|
||||
convert->mix = gst_audio_channel_mix_new (flags, in->channels, in->position,
|
||||
convert->mix =
|
||||
gst_audio_channel_mix_new (flags, format, in->channels, in->position,
|
||||
out->channels, out->position);
|
||||
convert->mix_passthrough =
|
||||
gst_audio_channel_mix_is_passthrough (convert->mix);
|
||||
|
@ -427,8 +426,7 @@ gst_audio_converter_samples (GstAudioConverter * convert,
|
|||
else
|
||||
outbuf = tmpbuf;
|
||||
|
||||
gst_audio_channel_mix_samples (convert->mix, convert->mix_format,
|
||||
convert->in.layout, src, outbuf, samples);
|
||||
gst_audio_channel_mix_samples (convert->mix, src, outbuf, samples);
|
||||
src = outbuf;
|
||||
}
|
||||
/* step 4, optional convert F64 -> S32 for quantize */
|
||||
|
|
|
@ -31,9 +31,13 @@
|
|||
|
||||
#define INT_MATRIX_FACTOR_EXPONENT 10
|
||||
|
||||
typedef void (*MixFunc) (GstAudioChannelMix * mix, const gpointer src,
|
||||
gpointer dst, gint samples);
|
||||
|
||||
struct _GstAudioChannelMix
|
||||
{
|
||||
GstAudioChannelMixFlags flags;
|
||||
GstAudioFormat format;
|
||||
|
||||
gint in_channels;
|
||||
gint out_channels;
|
||||
|
@ -49,6 +53,8 @@ struct _GstAudioChannelMix
|
|||
* this is matrix * (2^10) as integers */
|
||||
gint **matrix_int;
|
||||
|
||||
MixFunc func;
|
||||
|
||||
gpointer tmp;
|
||||
};
|
||||
|
||||
|
@ -681,72 +687,6 @@ gst_audio_channel_mix_setup_matrix (GstAudioChannelMix * mix)
|
|||
#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
|
||||
* you might need later on! */
|
||||
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:
|
||||
* @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.
|
||||
*/
|
||||
void
|
||||
gst_audio_channel_mix_samples (GstAudioChannelMix * mix, GstAudioFormat format,
|
||||
GstAudioLayout layout, const gpointer in_data, gpointer out_data,
|
||||
gint samples)
|
||||
gst_audio_channel_mix_samples (GstAudioChannelMix * mix,
|
||||
const gpointer in_data, gpointer out_data, gint samples)
|
||||
{
|
||||
g_return_if_fail (mix != NULL);
|
||||
g_return_if_fail (mix->matrix != NULL);
|
||||
g_return_if_fail (layout == GST_AUDIO_LAYOUT_INTERLEAVED);
|
||||
|
||||
switch (format) {
|
||||
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;
|
||||
}
|
||||
mix->func (mix, in_data, out_data, samples);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix;
|
|||
/**
|
||||
* GstAudioChannelMixFlags:
|
||||
* @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_OUT: output channels are explicitly unpositioned
|
||||
*
|
||||
|
@ -38,11 +39,13 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix;
|
|||
*/
|
||||
typedef enum {
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_NONE = 0,
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 0),
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 1)
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_NON_INTERLEAVED = (1 << 0),
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 1),
|
||||
GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 2)
|
||||
} GstAudioChannelMixFlags;
|
||||
|
||||
GstAudioChannelMix * gst_audio_channel_mix_new (GstAudioChannelMixFlags flags,
|
||||
GstAudioFormat format,
|
||||
gint in_channels,
|
||||
GstAudioChannelPosition in_position[64],
|
||||
gint out_channels,
|
||||
|
@ -58,8 +61,6 @@ gboolean gst_audio_channel_mix_is_passthrough (GstAudioChannelMix *mix);
|
|||
* Do actual mixing.
|
||||
*/
|
||||
void gst_audio_channel_mix_samples (GstAudioChannelMix * mix,
|
||||
GstAudioFormat format,
|
||||
GstAudioLayout layout,
|
||||
const gpointer in_data,
|
||||
gpointer out_data,
|
||||
gint samples);
|
||||
|
|
Loading…
Reference in a new issue