static gboolean gst_freeverb_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { GstFreeverb *filter = GST_FREEVERB (base); GstAudioInfo info; /*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */ if (!gst_audio_info_from_caps (&info, incaps)) goto no_format; GST_DEBUG ("try to process %d input with %d channels", GST_AUDIO_INFO_FORMAT (&info), GST_AUDIO_INFO_CHANNELS (&info)); if (!gst_freeverb_set_process_function (filter, &info)) goto no_format; filter->info = info; gst_freeverb_init_rev_model (filter); filter->drained = FALSE; GST_INFO_OBJECT (base, "model configured"); return TRUE; no_format: { GST_DEBUG ("invalid caps"); return FALSE; } }
static gboolean gst_freeverb_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { GstFreeverb *filter = GST_FREEVERB (base); const GstStructure *structure; gboolean ret; gint width, rate; const gchar *fmt; /*GST_INFO ("incaps are %" GST_PTR_FORMAT, incaps); */ structure = gst_caps_get_structure (incaps, 0); ret = gst_structure_get_int (structure, "channels", &filter->channels); if (!ret) goto no_channels; ret = gst_structure_get_int (structure, "width", &width); if (!ret) goto no_width; filter->width = width / 8; ret = gst_structure_get_int (structure, "rate", &rate); if (!ret) goto no_rate; filter->rate = rate; fmt = gst_structure_get_name (structure); if (!strcmp (fmt, "audio/x-raw-int")) filter->format_float = FALSE; else filter->format_float = TRUE; GST_DEBUG_OBJECT (filter, "try to process %s input_1 with %d channels", fmt, filter->channels); ret = gst_freeverb_set_process_function (filter); if (!ret) GST_WARNING_OBJECT (filter, "can't process input_1 with %d channels", filter->channels); gst_freeverb_init_rev_model (filter); filter->drained = FALSE; GST_INFO_OBJECT (base, "model configured"); return ret; no_channels: GST_DEBUG_OBJECT (filter, "no channels in caps"); return ret; no_width: GST_DEBUG_OBJECT (filter, "no width in caps"); return ret; no_rate: GST_DEBUG_OBJECT (filter, "no rate in caps"); return ret; }
static void gst_freeverb_finalize (GObject * object) { GstFreeverb *filter = GST_FREEVERB (object); freeverb_revmodel_free (filter); G_OBJECT_CLASS (parent_class)->finalize (object); }
/* this function does the actual processing */ static GstFlowReturn gst_freeverb_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf) { GstFreeverb *filter = GST_FREEVERB (base); guint num_samples; GstClockTime timestamp; GstMapInfo inmap, outmap; timestamp = GST_BUFFER_TIMESTAMP (inbuf); timestamp = gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp); gst_buffer_map (inbuf, &inmap, GST_MAP_READ); gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE); num_samples = outmap.size / (2 * GST_AUDIO_INFO_BPS (&filter->info)); GST_DEBUG_OBJECT (filter, "processing %u samples at %" GST_TIME_FORMAT, num_samples, GST_TIME_ARGS (timestamp)); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (GST_OBJECT (filter), timestamp); if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT))) { filter->drained = FALSE; } if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))) { if (filter->drained) { memset (outmap.data, 0, outmap.size); } } else { filter->drained = FALSE; } if (!filter->drained) { filter->drained = filter->process (filter, inmap.data, outmap.data, num_samples); } if (filter->drained) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); } gst_buffer_unmap (inbuf, &inmap); gst_buffer_unmap (outbuf, &outmap); return GST_FLOW_OK; }
static void gst_freeverb_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstFreeverb *filter = GST_FREEVERB (object); GstFreeverbPrivate *priv = filter->priv; gint i; switch (prop_id) { case PROP_ROOM_SIZE: filter->room_size = g_value_get_float (value); priv->roomsize = (filter->room_size * scaleroom) + offsetroom; for (i = 0; i < numcombs; i++) { freeverb_comb_setfeedback (&priv->combL[i], priv->roomsize); freeverb_comb_setfeedback (&priv->combR[i], priv->roomsize); } break; case PROP_DAMPING: filter->damping = g_value_get_float (value); priv->damp = filter->damping * scaledamp; for (i = 0; i < numcombs; i++) { freeverb_comb_setdamp (&priv->combL[i], priv->damp); freeverb_comb_setdamp (&priv->combR[i], priv->damp); } break; case PROP_PAN_WIDTH: filter->pan_width = g_value_get_float (value); priv->width = filter->pan_width; priv->wet1 = priv->wet * (priv->width / 2.0f + 0.5f); priv->wet2 = priv->wet * ((1.0f - priv->width) / 2.0f); break; case PROP_LEVEL: filter->level = g_value_get_float (value); priv->wet = filter->level * scalewet; priv->dry = (1.0 - filter->level) * scaledry; priv->wet1 = priv->wet * (priv->width / 2.0f + 0.5f); priv->wet2 = priv->wet * ((1.0f - priv->width) / 2.0f); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
/* this function does the actual processing */ static GstFlowReturn gst_freeverb_transform (GstBaseTransform * base, GstBuffer * inbuf, GstBuffer * outbuf) { GstFreeverb *filter = GST_FREEVERB (base); guint num_samples = GST_BUFFER_SIZE (outbuf) / (2 * filter->width); GstClockTime timestamp; timestamp = GST_BUFFER_TIMESTAMP (inbuf); timestamp = gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp); GST_DEBUG_OBJECT (filter, "processing %u samples at %" GST_TIME_FORMAT, num_samples, GST_TIME_ARGS (timestamp)); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (G_OBJECT (filter), timestamp); if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT))) { filter->drained = FALSE; } if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))) { if (filter->drained) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf)); return GST_FLOW_OK; } } else { filter->drained = FALSE; } filter->drained = filter->process (filter, GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (outbuf), num_samples); if (filter->drained) { GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); } return GST_FLOW_OK; }
static void gst_freeverb_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstFreeverb *filter = GST_FREEVERB (object); switch (prop_id) { case PROP_ROOM_SIZE: g_value_set_float (value, filter->room_size); break; case PROP_DAMPING: g_value_set_float (value, filter->damping); break; case PROP_PAN_WIDTH: g_value_set_float (value, filter->pan_width); break; case PROP_LEVEL: g_value_set_float (value, filter->level); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }