summaryrefslogtreecommitdiffstats
path: root/gst/replaygain
diff options
context:
space:
mode:
authorGabriel Bouvigne <bouvigne@mp3-tech.org>2009-05-07 16:25:41 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-05-07 16:25:41 +0200
commit3e0f1b84a4af33ef90da5f0f039f8f2c2cd62e81 (patch)
tree1bdb9e26b3eb2188b0684871b50ecd98284dd819 /gst/replaygain
parente2a483f0f96b2919f214dfcdae924cf0cbd9063b (diff)
rganalysis: Add ability to post level messages
Fixes bug #581568.
Diffstat (limited to 'gst/replaygain')
-rw-r--r--gst/replaygain/gstrganalysis.c48
-rw-r--r--gst/replaygain/gstrganalysis.h1
-rw-r--r--gst/replaygain/rganalysis.c45
-rw-r--r--gst/replaygain/rganalysis.h7
4 files changed, 96 insertions, 5 deletions
diff --git a/gst/replaygain/gstrganalysis.c b/gst/replaygain/gstrganalysis.c
index 982c8a7f..1c6d1e84 100644
--- a/gst/replaygain/gstrganalysis.c
+++ b/gst/replaygain/gstrganalysis.c
@@ -95,13 +95,15 @@ static const GstElementDetails rganalysis_details = {
/* Default property value. */
#define FORCED_DEFAULT TRUE
+#define DEFAULT_MESSAGE FALSE
enum
{
PROP_0,
PROP_NUM_TRACKS,
PROP_FORCED,
- PROP_REFERENCE_LEVEL
+ PROP_REFERENCE_LEVEL,
+ PROP_MESSAGE
};
/* The ReplayGain algorithm is intended for use with mono and stereo
@@ -272,6 +274,11 @@ gst_rg_analysis_class_init (GstRgAnalysisClass * klass)
"Reference level [dB]", 0.0, 150., RG_REFERENCE_LEVEL,
G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE,
+ g_param_spec_boolean ("message", "Message",
+ "Post statics messages",
+ DEFAULT_MESSAGE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
trans_class = (GstBaseTransformClass *) klass;
trans_class->start = GST_DEBUG_FUNCPTR (gst_rg_analysis_start);
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_rg_analysis_set_caps);
@@ -290,6 +297,7 @@ gst_rg_analysis_init (GstRgAnalysis * filter, GstRgAnalysisClass * gclass)
filter->num_tracks = 0;
filter->forced = FORCED_DEFAULT;
+ filter->message = DEFAULT_MESSAGE;
filter->reference_level = RG_REFERENCE_LEVEL;
filter->ctx = NULL;
@@ -302,6 +310,7 @@ gst_rg_analysis_set_property (GObject * object, guint prop_id,
{
GstRgAnalysis *filter = GST_RG_ANALYSIS (object);
+ GST_OBJECT_LOCK (filter);
switch (prop_id) {
case PROP_NUM_TRACKS:
filter->num_tracks = g_value_get_int (value);
@@ -312,10 +321,14 @@ gst_rg_analysis_set_property (GObject * object, guint prop_id,
case PROP_REFERENCE_LEVEL:
filter->reference_level = g_value_get_double (value);
break;
+ case PROP_MESSAGE:
+ filter->message = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+ GST_OBJECT_UNLOCK (filter);
}
static void
@@ -324,6 +337,7 @@ gst_rg_analysis_get_property (GObject * object, guint prop_id,
{
GstRgAnalysis *filter = GST_RG_ANALYSIS (object);
+ GST_OBJECT_LOCK (filter);
switch (prop_id) {
case PROP_NUM_TRACKS:
g_value_set_int (value, filter->num_tracks);
@@ -334,12 +348,35 @@ gst_rg_analysis_get_property (GObject * object, guint prop_id,
case PROP_REFERENCE_LEVEL:
g_value_set_double (value, filter->reference_level);
break;
+ case PROP_MESSAGE:
+ g_value_set_boolean (value, filter->message);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
+ GST_OBJECT_UNLOCK (filter);
}
+static void
+gst_rg_analysis_post_message (gpointer rganalysis, GstClockTime timestamp,
+ GstClockTime duration, gdouble rglevel)
+{
+ GstRgAnalysis *filter = GST_RG_ANALYSIS (rganalysis);
+ if (filter->message) {
+ GstMessage *m;
+
+ m = gst_message_new_element (GST_OBJECT_CAST (rganalysis),
+ gst_structure_new ("rganalysis",
+ "timestamp", G_TYPE_UINT64, timestamp,
+ "duration", G_TYPE_UINT64, duration,
+ "rglevel", G_TYPE_DOUBLE, rglevel, NULL));
+
+ gst_element_post_message (GST_ELEMENT_CAST (rganalysis), m);
+ }
+}
+
+
static gboolean
gst_rg_analysis_start (GstBaseTransform * base)
{
@@ -353,6 +390,10 @@ gst_rg_analysis_start (GstBaseTransform * base)
filter->has_album_peak = FALSE;
filter->ctx = rg_analysis_new ();
+ GST_OBJECT_LOCK (filter);
+ rg_analysis_init_silence_detection (filter->ctx, gst_rg_analysis_post_message,
+ filter);
+ GST_OBJECT_UNLOCK (filter);
filter->analyze = NULL;
GST_LOG_OBJECT (filter, "started");
@@ -452,13 +493,10 @@ gst_rg_analysis_transform_ip (GstBaseTransform * base, GstBuffer * buf)
if (filter->skip)
return GST_FLOW_OK;
- /* Buffers made up of silence have no influence on the analysis: */
- if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP))
- return GST_FLOW_OK;
-
GST_LOG_OBJECT (filter, "processing buffer of size %u",
GST_BUFFER_SIZE (buf));
+ rg_analysis_start_buffer (filter->ctx, GST_BUFFER_TIMESTAMP (buf));
filter->analyze (filter->ctx, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
filter->depth);
diff --git a/gst/replaygain/gstrganalysis.h b/gst/replaygain/gstrganalysis.h
index fbf46830..0d68e630 100644
--- a/gst/replaygain/gstrganalysis.h
+++ b/gst/replaygain/gstrganalysis.h
@@ -63,6 +63,7 @@ struct _GstRgAnalysis
guint num_tracks;
gdouble reference_level;
gboolean forced;
+ gboolean message;
/* State machinery for skipping. */
gboolean ignore_tags;
diff --git a/gst/replaygain/rganalysis.c b/gst/replaygain/rganalysis.c
index 147eef85..9787c688 100644
--- a/gst/replaygain/rganalysis.c
+++ b/gst/replaygain/rganalysis.c
@@ -109,6 +109,14 @@ struct _RgAnalysisCtx
RgAnalysisAcc track;
RgAnalysisAcc album;
+ void (*post_message) (gpointer analysis,
+ GstClockTime timestamp, GstClockTime duration, gdouble rglevel);
+ gpointer analysis;
+ /* The timestamp of the current incoming buffer. */
+ GstClockTime buffer_timestamp;
+ /* Number of samples processed in current buffer, during emit_signal,
+ this will always be on an RMS window boundary. */
+ guint buffer_n_samples_done;
};
/* Filter coefficients for the IIR filters that form the equal
@@ -406,6 +414,13 @@ rg_analysis_new (void)
return ctx;
}
+static void
+reset_silence_detection (RgAnalysisCtx * ctx)
+{
+ ctx->buffer_timestamp = GST_CLOCK_TIME_NONE;
+ ctx->buffer_n_samples_done = 0;
+}
+
/* Adapt to given sample rate. Does nothing if already the current
* rate (returns TRUE then). Returns FALSE only if given sample rate
* is not supported. If the configured rate changes, the last
@@ -458,11 +473,29 @@ rg_analysis_set_sample_rate (RgAnalysisCtx * ctx, gint sample_rate)
/ 1000);
reset_filters (ctx);
+ reset_silence_detection (ctx);
return TRUE;
}
void
+rg_analysis_init_silence_detection (RgAnalysisCtx * ctx,
+ void (*post_message) (gpointer analysis, GstClockTime timestamp,
+ GstClockTime duration, gdouble rglevel), gpointer analysis)
+{
+ ctx->post_message = post_message;
+ ctx->analysis = analysis;
+ reset_silence_detection (ctx);
+}
+
+void
+rg_analysis_start_buffer (RgAnalysisCtx * ctx, GstClockTime buffer_timestamp)
+{
+ ctx->buffer_timestamp = buffer_timestamp;
+ ctx->buffer_n_samples_done = 0;
+}
+
+void
rg_analysis_destroy (RgAnalysisCtx * ctx)
{
g_free (ctx);
@@ -665,6 +698,7 @@ rg_analysis_analyze (RgAnalysisCtx * ctx, const gfloat * samples_l,
* ctx->out_r[ctx->window_n_samples_done + i];
ctx->window_n_samples_done += n_samples_current;
+ ctx->buffer_n_samples_done += n_samples_current;
g_return_if_fail (ctx->window_n_samples_done <= ctx->window_n_samples);
@@ -674,6 +708,15 @@ rg_analysis_analyze (RgAnalysisCtx * ctx, const gfloat * samples_l,
ctx->window_n_samples * 0.5 + 1.e-37);
gint ival = CLAMP ((gint) val, 0,
(gint) G_N_ELEMENTS (ctx->track.histogram) - 1);
+ /* Compute the per-window gain */
+ const gdouble gain = PINK_REF - (gdouble) ival / STEPS_PER_DB;
+ const GstClockTime timestamp = (ctx->buffer_timestamp
+ + ctx->buffer_n_samples_done * GST_SECOND / ctx->sample_rate
+ - RMS_WINDOW_MSECS * GST_MSECOND);
+
+ ctx->post_message (ctx->analysis, timestamp,
+ RMS_WINDOW_MSECS * GST_MSECOND, -gain);
+
ctx->track.histogram[ival]++;
ctx->window_square_sum = 0.;
@@ -736,6 +779,7 @@ rg_analysis_track_result (RgAnalysisCtx * ctx, gdouble * gain, gdouble * peak)
accumulator_clear (&ctx->track);
reset_filters (ctx);
+ reset_silence_detection (ctx);
return result;
}
@@ -774,4 +818,5 @@ rg_analysis_reset (RgAnalysisCtx * ctx)
reset_filters (ctx);
accumulator_clear (&ctx->track);
accumulator_clear (&ctx->album);
+ reset_silence_detection (ctx);
}
diff --git a/gst/replaygain/rganalysis.h b/gst/replaygain/rganalysis.h
index 16247361..f57ad0a3 100644
--- a/gst/replaygain/rganalysis.h
+++ b/gst/replaygain/rganalysis.h
@@ -26,6 +26,7 @@
#define __RG_ANALYSIS_H__
#include <glib.h>
+#include <gst/gst.h>
G_BEGIN_DECLS
@@ -47,6 +48,12 @@ gboolean rg_analysis_track_result (RgAnalysisCtx * ctx, gdouble * gain,
gdouble * peak);
gboolean rg_analysis_album_result (RgAnalysisCtx * ctx, gdouble * gain,
gdouble * peak);
+void rg_analysis_init_silence_detection (
+ RgAnalysisCtx * ctx,
+ void (*post_message) (gpointer analysis, GstClockTime timestamp, GstClockTime duration, gdouble rglevel),
+ gpointer analysis);
+void rg_analysis_start_buffer (RgAnalysisCtx * ctx,
+ GstClockTime buffer_timestamp);
void rg_analysis_reset_album (RgAnalysisCtx * ctx);
void rg_analysis_reset (RgAnalysisCtx * ctx);
void rg_analysis_destroy (RgAnalysisCtx * ctx);