adder: Add support for per-stream volumes

This commit is contained in:
Sebastian Dröge 2013-05-30 12:46:56 +02:00
parent addb07bc58
commit a76ade2d78
5 changed files with 2849 additions and 5 deletions

View file

@ -49,9 +49,25 @@
#include <string.h> /* strcmp */
#include "gstadderorc.h"
#define GST_CAT_DEFAULT gst_adder_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define DEFAULT_PAD_VOLUME (1.0)
#define DEFAULT_PAD_MUTE (FALSE)
/* some defines for audio processing */
/* the volume factor is a range from 0.0 to (arbitrary) VOLUME_MAX_DOUBLE = 10.0
* we map 1.0 to VOLUME_UNITY_INT*
*/
#define VOLUME_UNITY_INT8 8 /* internal int for unity 2^(8-5) */
#define VOLUME_UNITY_INT8_BIT_SHIFT 3 /* number of bits to shift for unity */
#define VOLUME_UNITY_INT16 2048 /* internal int for unity 2^(16-5) */
#define VOLUME_UNITY_INT16_BIT_SHIFT 11 /* number of bits to shift for unity */
#define VOLUME_UNITY_INT24 524288 /* internal int for unity 2^(24-5) */
#define VOLUME_UNITY_INT24_BIT_SHIFT 19 /* number of bits to shift for unity */
#define VOLUME_UNITY_INT32 134217728 /* internal int for unity 2^(32-5) */
#define VOLUME_UNITY_INT32_BIT_SHIFT 27
enum
{
PROP_PAD_0,
@ -90,6 +106,9 @@ gst_adder_pad_set_property (GObject * object, guint prop_id,
case PROP_PAD_VOLUME:
GST_OBJECT_LOCK (pad);
pad->volume = g_value_get_double (value);
pad->volume_i8 = pad->volume * VOLUME_UNITY_INT8;
pad->volume_i16 = pad->volume * VOLUME_UNITY_INT16;
pad->volume_i32 = pad->volume * VOLUME_UNITY_INT32;
GST_OBJECT_UNLOCK (pad);
break;
case PROP_PAD_MUTE:
@ -134,9 +153,6 @@ enum
PROP_FILTER_CAPS
};
#define GST_CAT_DEFAULT gst_adder_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
/* elementfactory information */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
@ -1274,10 +1290,12 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data)
if (GST_CLOCK_TIME_IS_VALID (stream_time))
gst_object_sync_values (GST_OBJECT (pad), stream_time);
GST_OBJECT_LOCK (pad);
if (pad->mute || pad->volume < G_MINDOUBLE) {
had_mute = TRUE;
GST_DEBUG_OBJECT (adder, "channel %p: skipping muted pad", collect_data);
gst_buffer_unref (inbuf);
GST_OBJECT_UNLOCK (pad);
continue;
}
@ -1296,6 +1314,7 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data)
gapbuf = inbuf;
else
gst_buffer_unref (inbuf);
GST_OBJECT_UNLOCK (pad);
continue;
}
@ -1307,6 +1326,46 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data)
* only) GAP buffer, it will automatically copy the GAP flag. */
outbuf = gst_buffer_make_writable (inbuf);
gst_buffer_map (outbuf, &outmap, GST_MAP_READWRITE);
if (pad->volume != 1.0) {
switch (adder->info.finfo->format) {
case GST_AUDIO_FORMAT_U8:
adder_orc_volume_u8 ((gpointer) outmap.data, pad->volume_i8,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_S8:
adder_orc_volume_s8 ((gpointer) outmap.data, pad->volume_i8,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_U16:
adder_orc_volume_u16 ((gpointer) outmap.data, pad->volume_i16,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_S16:
adder_orc_volume_s16 ((gpointer) outmap.data, pad->volume_i16,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_U32:
adder_orc_volume_u32 ((gpointer) outmap.data, pad->volume_i32,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_S32:
adder_orc_volume_s32 ((gpointer) outmap.data, pad->volume_i32,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_F32:
adder_orc_volume_f32 ((gpointer) outmap.data, pad->volume,
outmap.size / bps);
break;
case GST_AUDIO_FORMAT_F64:
adder_orc_volume_f64 ((gpointer) outmap.data, pad->volume,
outmap.size / bps);
break;
default:
g_assert_not_reached ();
break;
}
}
} else {
if (!is_gap) {
/* we had a previous output buffer, mix this non-GAP buffer */
@ -1322,8 +1381,48 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data)
" from data %p", collect_data, inmap.size, inmap.data);
/* further buffers, need to add them */
adder->func ((gpointer) outmap.data, (gpointer) inmap.data,
inmap.size / bps);
if (pad->volume == 1.0) {
adder->func ((gpointer) outmap.data, (gpointer) inmap.data,
inmap.size / bps);
} else {
switch (adder->info.finfo->format) {
case GST_AUDIO_FORMAT_U8:
adder_orc_add_volume_u8 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i8, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_S8:
adder_orc_add_volume_s8 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i8, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_U16:
adder_orc_add_volume_u16 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i16, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_S16:
adder_orc_add_volume_s16 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i16, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_U32:
adder_orc_add_volume_u32 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i32, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_S32:
adder_orc_add_volume_s32 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume_i32, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_F32:
adder_orc_add_volume_f32 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume, inmap.size / bps);
break;
case GST_AUDIO_FORMAT_F64:
adder_orc_add_volume_f64 ((gpointer) outmap.data,
(gpointer) inmap.data, pad->volume, inmap.size / bps);
break;
default:
g_assert_not_reached ();
break;
}
}
gst_buffer_unmap (inbuf, &inmap);
} else {
/* skip gap buffer */
@ -1331,6 +1430,7 @@ gst_adder_collected (GstCollectPads * pads, gpointer user_data)
}
gst_buffer_unref (inbuf);
}
GST_OBJECT_UNLOCK (pad);
}
if (outbuf)
gst_buffer_unmap (outbuf, &outmap);

View file

@ -104,6 +104,9 @@ struct _GstAdderPad {
GstPad parent;
gdouble volume;
gint volume_i32;
gint volume_i16;
gint volume_i8;
gboolean mute;
};

File diff suppressed because it is too large Load diff

View file

@ -88,6 +88,22 @@ void adder_orc_add_uint16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRI
void adder_orc_add_uint8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n);
void adder_orc_add_float32 (float * ORC_RESTRICT d1, const float * ORC_RESTRICT s1, int n);
void adder_orc_add_float64 (double * ORC_RESTRICT d1, const double * ORC_RESTRICT s1, int n);
void adder_orc_volume_u8 (guint8 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_s8 (gint8 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_u16 (guint16 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_s16 (gint16 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_u32 (guint32 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_s32 (gint32 * ORC_RESTRICT d1, int p1, int n);
void adder_orc_volume_f32 (float * ORC_RESTRICT d1, float p1, int n);
void adder_orc_volume_f64 (double * ORC_RESTRICT d1, double p1, int n);
void adder_orc_add_volume_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_s8 (gint8 * ORC_RESTRICT d1, const gint8 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_u16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_s16 (gint16 * ORC_RESTRICT d1, const gint16 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_u32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_s32 (gint32 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n);
void adder_orc_add_volume_f32 (float * ORC_RESTRICT d1, const float * ORC_RESTRICT s1, float p1, int n);
void adder_orc_add_volume_f64 (double * ORC_RESTRICT d1, const double * ORC_RESTRICT s1, double p1, int n);
#ifdef __cplusplus
}

View file

@ -54,3 +54,195 @@ addf d1, d1, s1
addd d1, d1, s1
.function adder_orc_volume_u8
.dest 1 d1 guint8
.param 1 p1
.const 1 c1 0x80
.temp 2 t1
.temp 1 t2
xorb t2, d1, c1
mulsbw t1, t2, p1
shrsw t1, t1, 3
convssswb t2, t1
xorb d1, t2, c1
.function adder_orc_volume_s8
.dest 1 d1 gint8
.param 1 p1
.temp 2 t1
mulsbw t1, d1, p1
shrsw t1, t1, 3
convssswb d1, t1
.function adder_orc_volume_u16
.dest 2 d1 guint16
.param 2 p1
.const 2 c1 0x8000
.temp 4 t1
.temp 2 t2
xorw t2, d1, c1
mulswl t1, t2, p1
shrsl t1, t1, 11
convssslw t2, t1
xorw d1, t2, c1
.function adder_orc_volume_s16
.dest 2 d1 gint16
.param 2 p1
.temp 4 t1
mulswl t1, d1, p1
shrsl t1, t1, 11
convssslw d1, t1
.function adder_orc_volume_u32
.dest 4 d1 guint32
.param 4 p1
.const 4 c1 0x80000000
.temp 8 t1
.temp 4 t2
xorl t2, d1, c1
mulslq t1, t2, p1
shrsq t1, t1, 27
convsssql t2, t1
xorl d1, t2, c1
.function adder_orc_volume_s32
.dest 4 d1 gint32
.param 4 p1
.temp 8 t1
mulslq t1, d1, p1
shrsq t1, t1, 27
convsssql d1, t1
.function adder_orc_volume_f32
.dest 4 d1 float
.floatparam 4 p1
mulf d1, d1, p1
.function adder_orc_volume_f64
.dest 8 d1 double
.doubleparam 8 p1
muld d1, d1, p1
.function adder_orc_add_volume_u8
.dest 1 d1 guint8
.source 1 s1 guint8
.param 1 p1
.const 1 c1 0x80
.temp 2 t1
.temp 1 t2
xorb t2, s1, c1
mulsbw t1, t2, p1
shrsw t1, t1, 3
convssswb t2, t1
xorb t2, t2, c1
addusb d1, d1, t2
.function adder_orc_add_volume_s8
.dest 1 d1 gint8
.source 1 s1 gint8
.param 1 p1
.temp 2 t1
.temp 1 t2
mulsbw t1, s1, p1
shrsw t1, t1, 3
convssswb t2, t1
addssb d1, d1, t2
.function adder_orc_add_volume_u16
.dest 2 d1 guint16
.source 2 s1 guint16
.param 2 p1
.const 2 c1 0x8000
.temp 4 t1
.temp 2 t2
xorw t2, s1, c1
mulswl t1, t2, p1
shrsl t1, t1, 11
convssslw t2, t1
xorw t2, t2, c1
addusw d1, d1, t2
.function adder_orc_add_volume_s16
.dest 2 d1 gint16
.source 2 s1 gint16
.param 2 p1
.temp 4 t1
.temp 2 t2
mulswl t1, s1, p1
shrsl t1, t1, 11
convssslw t2, t1
addssw d1, d1, t2
.function adder_orc_add_volume_u32
.dest 4 d1 guint32
.source 4 s1 guint32
.param 4 p1
.const 4 c1 0x80000000
.temp 8 t1
.temp 4 t2
xorl t2, s1, c1
mulslq t1, t2, p1
shrsq t1, t1, 27
convsssql t2, t1
xorl t2, t2, c1
addusl d1, d1, t2
.function adder_orc_add_volume_s32
.dest 4 d1 gint32
.source 4 s1 gint32
.param 4 p1
.temp 8 t1
.temp 4 t2
mulslq t1, s1, p1
shrsq t1, t1, 27
convsssql t2, t1
addssl d1, d1, t2
.function adder_orc_add_volume_f32
.dest 4 d1 float
.source 4 s1 float
.floatparam 4 p1
.temp 4 t1
mulf t1, s1, p1
addf d1, d1, t1
.function adder_orc_add_volume_f64
.dest 8 d1 double
.source 8 s1 double
.doubleparam 8 p1
.temp 8 t1
muld t1, s1, p1
addd d1, d1, t1