gst/cutter/gstcutter.c: copy calculation code from level; remove use of some audio functions

Original commit message from CVS:

* gst/cutter/gstcutter.c: (gst_cutter_chain),
(gst_cutter_set_property), (gst_cutter_get_caps):
copy calculation code from level; remove use of some audio
functions
This commit is contained in:
Thomas Vander Stichele 2005-11-22 13:13:21 +00:00
parent 8f0c1ebdb2
commit baba27fb18
2 changed files with 69 additions and 32 deletions

View file

@ -1,3 +1,10 @@
2005-11-22 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/cutter/gstcutter.c: (gst_cutter_chain),
(gst_cutter_set_property), (gst_cutter_get_caps):
copy calculation code from level; remove use of some audio
functions
2005-11-22 Andy Wingo <wingo@pobox.com> 2005-11-22 Andy Wingo <wingo@pobox.com>
* Update for gst_tag_setter API changes. * Update for gst_tag_setter API changes.

View file

@ -30,7 +30,6 @@
GST_DEBUG_CATEGORY (cutter_debug); GST_DEBUG_CATEGORY (cutter_debug);
#define GST_CAT_DEFAULT cutter_debug #define GST_CAT_DEFAULT cutter_debug
#define CUTTER_DEFAULT_THRESHOLD_LEVEL 0.1 #define CUTTER_DEFAULT_THRESHOLD_LEVEL 0.1
#define CUTTER_DEFAULT_THRESHOLD_LENGTH (500 * GST_MSECOND) #define CUTTER_DEFAULT_THRESHOLD_LENGTH (500 * GST_MSECOND)
#define CUTTER_DEFAULT_PRE_LENGTH (200 * GST_MSECOND) #define CUTTER_DEFAULT_PRE_LENGTH (200 * GST_MSECOND)
@ -45,16 +44,24 @@ static GstElementDetails cutter_details = {
static GstStaticPadTemplate cutter_src_factory = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate cutter_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; " GST_STATIC_CAPS ("audio/x-raw-int, "
GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) "rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, MAX ], "
"endianness = (int) BYTE_ORDER, "
"width = (int) { 8, 16 }, "
"depth = (int) { 8, 16 }, " "signed = (boolean) true")
); );
static GstStaticPadTemplate cutter_sink_factory = static GstStaticPadTemplate cutter_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; " GST_STATIC_CAPS ("audio/x-raw-int, "
GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) "rate = (int) [ 1, MAX ], "
"channels = (int) [ 1, MAX ], "
"endianness = (int) BYTE_ORDER, "
"width = (int) { 8, 16 }, "
"depth = (int) { 8, 16 }, " "signed = (boolean) true")
); );
enum enum
@ -75,8 +82,6 @@ static void gst_cutter_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_cutter_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_cutter_chain (GstPad * pad, GstBuffer * buffer);
static double inline gst_cutter_16bit_ms (gint16 * data, guint numsamples);
static double inline gst_cutter_8bit_ms (gint8 * data, guint numsamples);
void gst_cutter_get_caps (GstPad * pad, GstCutter * filter); void gst_cutter_get_caps (GstPad * pad, GstCutter * filter);
@ -171,13 +176,46 @@ gst_cutter_message_new (GstCutter * c, gboolean above, GstClockTime timestamp)
return gst_message_new_element (GST_OBJECT (c), s); return gst_message_new_element (GST_OBJECT (c), s);
} }
/* Calculate the Normalized Cumulative Square over a buffer of the given type
* and over all channels combined */
#define DEFINE_CUTTER_CALCULATOR(TYPE, RESOLUTION) \
static void inline \
gst_cutter_calculate_##TYPE (TYPE * in, guint num, \
double *NCS) \
{ \
register int j; \
double squaresum = 0.0; /* square sum of the integer samples */ \
register double square = 0.0; /* Square */ \
gdouble normalizer; /* divisor to get a [-1.0, 1.0] range */ \
\
*NCS = 0.0; /* Normalized Cumulative Square */ \
\
normalizer = (double) (1 << (RESOLUTION * 2)); \
\
for (j = 0; j < num; j++) \
{ \
square = ((double) in[j]) * in[j]; \
squaresum += square; \
} \
\
\
*NCS = squaresum / normalizer; \
}
DEFINE_CUTTER_CALCULATOR (gint16, 15);
DEFINE_CUTTER_CALCULATOR (gint8, 7);
static GstFlowReturn static GstFlowReturn
gst_cutter_chain (GstPad * pad, GstBuffer * buf) gst_cutter_chain (GstPad * pad, GstBuffer * buf)
{ {
GstCutter *filter; GstCutter *filter;
gint16 *in_data; gint16 *in_data;
double RMS = 0.0; /* RMS of signal in buffer */ guint num_samples;
double ms = 0.0; /* mean square value of buffer */ gdouble NCS = 0.0; /* Normalized Cumulative Square of buffer */
gdouble RMS = 0.0; /* RMS of signal in buffer */
gdouble NMS = 0.0; /* Normalized Mean Square of buffer */
static gboolean silent_prev = FALSE; /* previous value of silent */ static gboolean silent_prev = FALSE; /* previous value of silent */
GstBuffer *prebuf; /* pointer to a prebuffer element */ GstBuffer *prebuf; /* pointer to a prebuffer element */
@ -204,10 +242,14 @@ gst_cutter_chain (GstPad * pad, GstBuffer * buf)
/* calculate mean square value on buffer */ /* calculate mean square value on buffer */
switch (filter->width) { switch (filter->width) {
case 16: case 16:
ms = gst_cutter_16bit_ms (in_data, GST_BUFFER_SIZE (buf) / 2); num_samples = GST_BUFFER_SIZE (buf) / 2;
gst_cutter_calculate_gint16 (in_data, num_samples, &NCS);
NMS = NCS / num_samples;
break; break;
case 8: case 8:
ms = gst_cutter_8bit_ms ((gint8 *) in_data, GST_BUFFER_SIZE (buf)); num_samples = GST_BUFFER_SIZE (buf);
gst_cutter_calculate_gint8 ((gint8 *) in_data, num_samples, &NCS);
NMS = NCS / num_samples;
break; break;
default: default:
/* this shouldn't happen */ /* this shouldn't happen */
@ -217,12 +259,12 @@ gst_cutter_chain (GstPad * pad, GstBuffer * buf)
silent_prev = filter->silent; silent_prev = filter->silent;
RMS = sqrt (ms) / (double) filter->max_sample; RMS = sqrt (NMS);
/* if RMS below threshold, add buffer length to silent run length count /* if RMS below threshold, add buffer length to silent run length count
* if not, reset * if not, reset
*/ */
GST_LOG_OBJECT (filter, "buffer stats: ms %f, RMS %f, audio length %f", GST_LOG_OBJECT (filter, "buffer stats: NMS %f, RMS %f, audio length %f",
ms, RMS, gst_audio_duration_from_pad_buffer (filter->sinkpad, buf)); NMS, RMS, gst_audio_duration_from_pad_buffer (filter->sinkpad, buf));
if (RMS < filter->threshold_level) if (RMS < filter->threshold_level)
filter->silent_run_length += filter->silent_run_length +=
gst_audio_duration_from_pad_buffer (filter->sinkpad, buf); gst_audio_duration_from_pad_buffer (filter->sinkpad, buf);
@ -267,13 +309,6 @@ gst_cutter_chain (GstPad * pad, GstBuffer * buf)
/* now check if we have to send the new buffer to the internal buffer cache /* now check if we have to send the new buffer to the internal buffer cache
* or to the srcpad */ * or to the srcpad */
if (filter->silent) { if (filter->silent) {
/* we ref it before putting it in the pre_buffer */
/* FIXME: we shouldn't probably do this, because the buffer
* arrives reffed already; the plugin should just push it
* or unref it to make it disappear */
/*
gst_buffer_ref (buf);
*/
filter->pre_buffer = g_list_append (filter->pre_buffer, buf); filter->pre_buffer = g_list_append (filter->pre_buffer, buf);
filter->pre_run_length += filter->pre_run_length +=
gst_audio_duration_from_pad_buffer (filter->sinkpad, buf); gst_audio_duration_from_pad_buffer (filter->sinkpad, buf);
@ -293,13 +328,8 @@ gst_cutter_chain (GstPad * pad, GstBuffer * buf)
return GST_FLOW_OK; return GST_FLOW_OK;
} }
static double inline static void
gst_cutter_16bit_ms (gint16 * data, guint num_samples) gst_cutter_set_property (GObject * object, guint prop_id,
#include "filter.func"
static double inline gst_cutter_8bit_ms (gint8 * data, guint num_samples)
#include "filter.func"
static void
gst_cutter_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstCutter *filter; GstCutter *filter;
@ -309,7 +339,6 @@ gst_cutter_16bit_ms (gint16 * data, guint num_samples)
switch (prop_id) { switch (prop_id) {
case PROP_THRESHOLD: case PROP_THRESHOLD:
/* set the level */
filter->threshold_level = g_value_get_double (value); filter->threshold_level = g_value_get_double (value);
GST_DEBUG ("DEBUG: set threshold level to %f", filter->threshold_level); GST_DEBUG ("DEBUG: set threshold level to %f", filter->threshold_level);
break; break;
@ -319,7 +348,8 @@ gst_cutter_16bit_ms (gint16 * data, guint num_samples)
* values in dB < 0 result in values between 0 and 1 * values in dB < 0 result in values between 0 and 1
*/ */
filter->threshold_level = pow (10, g_value_get_double (value) / 20); filter->threshold_level = pow (10, g_value_get_double (value) / 20);
GST_DEBUG ("DEBUG: set threshold level to %f", filter->threshold_level); GST_DEBUG_OBJECT (filter, "set threshold level to %f",
filter->threshold_level);
break; break;
case PROP_RUN_LENGTH: case PROP_RUN_LENGTH:
/* set the minimum length of the silent run required */ /* set the minimum length of the silent run required */
@ -397,6 +427,6 @@ gst_cutter_get_caps (GstPad * pad, GstCutter * filter)
g_assert (caps != NULL); g_assert (caps != NULL);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
gst_structure_get_int (structure, "width", &filter->width); gst_structure_get_int (structure, "width", &filter->width);
filter->max_sample = gst_audio_highest_sample_value (pad); filter->max_sample = 1 << (filter->width - 1); /* signed */
filter->have_caps = TRUE; filter->have_caps = TRUE;
} }