diff options
| -rw-r--r-- | ChangeLog | 8 | ||||
| -rw-r--r-- | gst/level/gstlevel.c | 191 | ||||
| -rw-r--r-- | gst/level/gstlevel.h | 8 | 
3 files changed, 140 insertions, 67 deletions
@@ -1,3 +1,11 @@ +2007-02-21  Stefan Kost  <ensonic@users.sf.net> + +	* gst/level/gstlevel.c: (gst_level_init), (gst_level_set_caps), +	(gst_level_transform_ip): +	* gst/level/gstlevel.h: +	  Use function pointer for process function and add process functions +	  for float audio. +  2007-02-19  Stefan Kost  <ensonic@users.sf.net>  	* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list), diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c index fcb0907c..bc1c42e1 100644 --- a/gst/level/gstlevel.c +++ b/gst/level/gstlevel.c @@ -78,6 +78,7 @@  #ifdef HAVE_CONFIG_H  #include "config.h"  #endif +#include <string.h>  #include <gst/gst.h>  #include <gst/audio/audio.h>  #include "gstlevel.h" @@ -92,7 +93,7 @@ static const GstElementDetails level_details = GST_ELEMENT_DETAILS ("Level",      "Thomas Vander Stichele <thomas at apestaart dot org>");  static GstStaticPadTemplate sink_template_factory = -GST_STATIC_PAD_TEMPLATE ("sink", +    GST_STATIC_PAD_TEMPLATE ("sink",      GST_PAD_SINK,      GST_PAD_ALWAYS,      GST_STATIC_CAPS ("audio/x-raw-int, " @@ -100,11 +101,16 @@ GST_STATIC_PAD_TEMPLATE ("sink",          "channels = (int) [ 1, MAX ], "          "endianness = (int) BYTE_ORDER, "          "width = (int) { 8, 16 }, " -        "depth = (int) { 8, 16 }, " "signed = (boolean) true") +        "depth = (int) { 8, 16 }, " +        "signed = (boolean) true; " +        "audio/x-raw-float, " +        "rate = (int) [ 1, MAX ], " +        "channels = (int) [ 1, MAX ], " +        "endianness = (int) BYTE_ORDER, " "width = (int) {32, 64} ")      );  static GstStaticPadTemplate src_template_factory = -GST_STATIC_PAD_TEMPLATE ("src", +    GST_STATIC_PAD_TEMPLATE ("src",      GST_PAD_SRC,      GST_PAD_ALWAYS,      GST_STATIC_CAPS ("audio/x-raw-int, " @@ -112,7 +118,12 @@ GST_STATIC_PAD_TEMPLATE ("src",          "channels = (int) [ 1, MAX ], "          "endianness = (int) BYTE_ORDER, "          "width = (int) { 8, 16 }, " -        "depth = (int) { 8, 16 }, " "signed = (boolean) true") +        "depth = (int) { 8, 16 }, " +        "signed = (boolean) true; " +        "audio/x-raw-float, " +        "rate = (int) [ 1, MAX ], " +        "channels = (int) [ 1, MAX ], " +        "endianness = (int) BYTE_ORDER, " "width = (int) {32, 64} ")      );  enum @@ -203,6 +214,8 @@ gst_level_init (GstLevel * filter, GstLevelClass * g_class)    filter->decay_peak_falloff = 10.0;    /* dB falloff (/sec) */    filter->message = TRUE; + +  filter->process = NULL;  }  static void @@ -277,6 +290,82 @@ gst_level_get_property (GObject * object, guint prop_id,    }  } + +/* process one (interleaved) channel of incoming samples + * calculate square sum of samples + * normalize and average over number of samples + * returns a normalized cumulative square value, which can be averaged + * to return the average power as a double between 0 and 1 + * also returns the normalized peak power (square of the highest amplitude) + * + * caller must assure num is a multiple of channels + * samples for multiple channels are interleaved + * input sample data enters in *in_data as 8 or 16 bit data + * this filter only accepts signed audio data, so mid level is always 0 + * + * for 16 bit, this code considers the non-existant 32768 value to be + * full-scale; so 32767 will not map to 1.0 + */ + +#define DEFINE_INT_LEVEL_CALCULATOR(TYPE, RESOLUTION)                         \ +static void inline                                                            \ +gst_level_calculate_##TYPE (gpointer data, guint num, guint channels,         \ +                            gdouble *NCS, gdouble *NPS)                       \ +{                                                                             \ +  TYPE * in = (TYPE *)data;                                                   \ +  register guint j;                                                           \ +  gdouble squaresum = 0.0;           /* square sum of the integer samples */  \ +  register gdouble square = 0.0;     /* Square */                             \ +  register gdouble peaksquare = 0.0; /* Peak Square Sample */                 \ +  gdouble normalizer;               /* divisor to get a [-1.0, 1.0] range */  \ +                                                                              \ +  *NCS = 0.0;                       /* Normalized Cumulative Square */        \ +  *NPS = 0.0;                       /* Normalized Peask Square */             \ +                                                                              \ +  normalizer = (gdouble) (1 << (RESOLUTION * 2));                             \ +                                                                              \ +  for (j = 0; j < num; j += channels)                                         \ +  {                                                                           \ +    square = ((gdouble) in[j]) * in[j];                                       \ +    if (square > peaksquare) peaksquare = square;                             \ +    squaresum += square;                                                      \ +  }                                                                           \ +                                                                              \ +  *NCS = squaresum / normalizer;                                              \ +  *NPS = peaksquare / normalizer;                                             \ +} + +DEFINE_INT_LEVEL_CALCULATOR (gint16, 15); +DEFINE_INT_LEVEL_CALCULATOR (gint8, 7); + +#define DEFINE_FLOAT_LEVEL_CALCULATOR(TYPE)                                   \ +static void inline                                                            \ +gst_level_calculate_##TYPE (gpointer data, guint num, guint channels,         \ +                            gdouble *NCS, gdouble *NPS)                       \ +{                                                                             \ +  TYPE * in = (TYPE *)data;                                                   \ +  register guint j;                                                           \ +  gdouble squaresum = 0.0;           /* square sum of the integer samples */  \ +  register gdouble square = 0.0;     /* Square */                             \ +  register gdouble peaksquare = 0.0; /* Peak Square Sample */                 \ +                                                                              \ +  *NCS = 0.0;                       /* Normalized Cumulative Square */        \ +  *NPS = 0.0;                       /* Normalized Peask Square */             \ +                                                                              \ +  for (j = 0; j < num; j += channels)                                         \ +  {                                                                           \ +    square = ((gdouble) in[j]) * in[j];                                       \ +    if (square > peaksquare) peaksquare = square;                             \ +    squaresum += square;                                                      \ +  }                                                                           \ +                                                                              \ +  *NCS = squaresum;                                                           \ +  *NPS = peaksquare;                                                          \ +} + +DEFINE_FLOAT_LEVEL_CALCULATOR (gfloat); +DEFINE_FLOAT_LEVEL_CALCULATOR (gdouble); +  static gint  structure_get_int (GstStructure * structure, const gchar * field)  { @@ -291,18 +380,42 @@ structure_get_int (GstStructure * structure, const gchar * field)  static gboolean  gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)  { -  GstLevel *filter; +  GstLevel *filter = GST_LEVEL (trans); +  const gchar *mimetype;    GstStructure *structure;    int i; -  filter = GST_LEVEL (trans); -    filter->num_frames = 0;    structure = gst_caps_get_structure (in, 0);    filter->rate = structure_get_int (structure, "rate");    filter->width = structure_get_int (structure, "width");    filter->channels = structure_get_int (structure, "channels"); +  mimetype = gst_structure_get_name (structure); + +  /* FIXME: set calculator func depending on caps */ +  filter->process = NULL; +  if (strcmp (mimetype, "audio/x-raw-int") == 0) { +    GST_DEBUG_OBJECT (filter, "use int: %u", filter->width); +    switch (filter->width) { +      case 8: +        filter->process = gst_level_calculate_gint8; +        break; +      case 16: +        filter->process = gst_level_calculate_gint16; +        break; +    } +  } else if (strcmp (mimetype, "audio/x-raw-float") == 0) { +    GST_DEBUG_OBJECT (filter, "use float, %u", filter->width); +    switch (filter->width) { +      case 32: +        filter->process = gst_level_calculate_gfloat; +        break; +      case 64: +        filter->process = gst_level_calculate_gdouble; +        break; +    } +  }    /* allocate channel variable arrays */    g_free (filter->CS); @@ -328,52 +441,6 @@ gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)    return TRUE;  } -/* process one (interleaved) channel of incoming samples - * calculate square sum of samples - * normalize and average over number of samples - * returns a normalized cumulative square value, which can be averaged - * to return the average power as a double between 0 and 1 - * also returns the normalized peak power (square of the highest amplitude) - * - * caller must assure num is a multiple of channels - * samples for multiple channels are interleaved - * input sample data enters in *in_data as 8 or 16 bit data - * this filter only accepts signed audio data, so mid level is always 0 - * - * for 16 bit, this code considers the non-existant 32768 value to be - * full-scale; so 32767 will not map to 1.0 - */ - -#define DEFINE_LEVEL_CALCULATOR(TYPE, RESOLUTION)                             \ -static void inline                                                            \ -gst_level_calculate_##TYPE (TYPE * in, guint num, gint channels,              \ -                            double *NCS, double *NPS)                         \ -{                                                                             \ -  register int j;                                                             \ -  double squaresum = 0.0;           /* square sum of the integer samples */   \ -  register double square = 0.0;     /* Square */                              \ -  register double peaksquare = 0.0; /* Peak Square Sample */                  \ -  gdouble normalizer;               /* divisor to get a [-1.0, 1.0] range */  \ -                                                                              \ -  *NCS = 0.0;                       /* Normalized Cumulative Square */        \ -  *NPS = 0.0;                       /* Normalized Peask Square */             \ -                                                                              \ -  normalizer = (double) (1 << (RESOLUTION * 2));                              \ -                                                                              \ -  for (j = 0; j < num; j += channels)                                         \ -  {                                                                           \ -    square = ((double) in[j]) * in[j];                                        \ -    if (square > peaksquare) peaksquare = square;                             \ -    squaresum += square;                                                      \ -  }                                                                           \ -                                                                              \ -  *NCS = squaresum / normalizer;                                              \ -  *NPS = peaksquare / normalizer;                                             \ -} - -DEFINE_LEVEL_CALCULATOR (gint16, 15); -DEFINE_LEVEL_CALCULATOR (gint8, 7); -  static GstMessage *  gst_level_message_new (GstLevel * l, GstClockTime endtime)  { @@ -427,10 +494,10 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in)    GstLevel *filter;    gpointer in_data;    double CS = 0.0; -  gint num_frames = 0; -  gint num_int_samples = 0;     /* number of interleaved samples +  guint num_frames = 0; +  guint num_int_samples = 0;    /* number of interleaved samples                                   * ie. total count for all channels combined */ -  gint i; +  guint i;    filter = GST_LEVEL (trans); @@ -447,16 +514,8 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in)    for (i = 0; i < filter->channels; ++i) {      CS = 0.0; -    switch (filter->width) { -      case 16: -        gst_level_calculate_gint16 (((gint16 *) in_data) + i, num_int_samples, -            filter->channels, &CS, &filter->peak[i]); -        break; -      case 8: -        gst_level_calculate_gint8 (((gint8 *) in_data) + i, num_int_samples, -            filter->channels, &CS, &filter->peak[i]); -        break; -    } +    filter->process (in_data + i, num_int_samples, filter->channels, &CS, +        &filter->peak[i]);      GST_LOG_OBJECT (filter,          "channel %d, cumulative sum %f, peak %f, over %d samples/%d channels",          i, CS, filter->peak[i], num_int_samples, filter->channels); diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h index ead53547..3cd5d3a8 100644 --- a/gst/level/gstlevel.h +++ b/gst/level/gstlevel.h @@ -48,7 +48,11 @@ G_BEGIN_DECLS  typedef struct _GstLevel GstLevel;  typedef struct _GstLevelClass GstLevelClass; - +/** + * GstLevel: + * + * Opaque data structure. + */  struct _GstLevel {    GstBaseTransform element; @@ -73,6 +77,8 @@ struct _GstLevel {    gdouble *MS;                  /* normalized Mean Square of buffer */    gdouble *RMS_dB;              /* RMS in dB to emit */    GstClockTime *decay_peak_age; /* age of last peak */ +   +  void (*process)(gpointer, guint, guint, gdouble*, gdouble*);  };  struct _GstLevelClass {  | 
