completely rewrite interpolation so that it is more stable, faster, easier to maintain and it now sounds damned smoooth

Original commit message from CVS:
completely rewrite interpolation so that it is more stable, faster, easier to maintain and it now sounds damned smoooth
This commit is contained in:
Steve Baker 2002-05-29 18:47:06 +00:00
parent e1fe257bc9
commit fc7a6ad8c9
2 changed files with 85 additions and 54 deletions

View file

@ -31,6 +31,7 @@ static void gst_dpsmooth_init (GstDParamSmooth *dparam);
static void gst_dpsmooth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info);
static void gst_dpsmooth_value_changed_float (GstDParam *dparam);
enum {
ARG_0,
@ -124,6 +125,7 @@ gst_dpsmooth_new (GType type)
switch (type){
case G_TYPE_FLOAT: {
dparam->do_update_func = gst_dpsmooth_do_update_float;
g_signal_connect (G_OBJECT (dpsmooth), "value_changed", G_CALLBACK (gst_dpsmooth_value_changed_float), NULL);
break;
}
default:
@ -197,23 +199,55 @@ gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParam
}
}
static void
gst_dpsmooth_value_changed_float (GstDParam *dparam)
{
GstDParamSmooth *dpsmooth;
gfloat time_ratio;
g_return_if_fail(GST_IS_DPSMOOTH(dparam));
dpsmooth = GST_DPSMOOTH(dparam);
if (GST_DPARAM_IS_LOG(dparam)){
dparam->value_float = log(dparam->value_float);
}
dpsmooth->start_float = dpsmooth->current_float;
dpsmooth->diff_float = dparam->value_float - dpsmooth->start_float;
time_ratio = ABS(dpsmooth->diff_float) / dpsmooth->slope_delta_float;
dpsmooth->duration_interp = (gint64)(time_ratio * (gfloat)dpsmooth->slope_time);
dpsmooth->need_interp_times = TRUE;
GST_DEBUG(GST_CAT_PARAMS, "%f to %f ratio:%f duration:%lld\n",
dpsmooth->start_float, dparam->value_float, time_ratio, dpsmooth->duration_interp);
}
static void
gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info)
{
gint64 time_diff;
gfloat time_ratio;
gfloat current, target, max_change, final_val;
gfloat current_diff = 0;
GstDParamSmooth *dpsmooth = GST_DPSMOOTH(dparam);
GST_DPARAM_LOCK(dparam);
if (update_info == GST_DPARAM_UPDATE_FIRST){
/*this is the first update since the pipeline started.
* the value won't be smoothed, it will be updated immediately
*/
g_value_set_float(value, dparam->value_float);
if (dpsmooth->need_interp_times){
dpsmooth->start_interp = timestamp;
dpsmooth->end_interp = timestamp + dpsmooth->duration_interp;
dpsmooth->need_interp_times = FALSE;
}
if ((update_info == GST_DPARAM_UPDATE_FIRST) || (timestamp >= dpsmooth->end_interp)){
if (GST_DPARAM_IS_LOG(dparam)){
g_value_set_float(value, exp(dparam->value_float));
}
else {
g_value_set_float(value, dparam->value_float);
}
dpsmooth->current_float = dparam->value_float;
GST_DEBUG(GST_CAT_PARAMS, "interp finished at %lld", timestamp);
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp;
@ -221,59 +255,46 @@ gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value
GST_DPARAM_UNLOCK(dparam);
return;
}
time_diff = timestamp - GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam);
target = dparam->value_float;
current = g_value_get_float(value);
time_ratio = (gfloat)time_diff / (gfloat)dpsmooth->slope_time;
if (timestamp <= dpsmooth->start_interp){
if (GST_DPARAM_IS_LOG(dparam)){
g_value_set_float(value, exp(dpsmooth->start_float));
}
else {
g_value_set_float(value, dpsmooth->start_float);
}
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = dpsmooth->start_interp + dpsmooth->update_period;
GST_DEBUG(GST_CAT_PARAMS, "interp started at %lld", timestamp);
max_change = time_ratio * dpsmooth->slope_delta_float;
GST_DPARAM_UNLOCK(dparam);
return;
}
GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f max_change:%f ",
target, current, max_change);
time_ratio = (gfloat)(timestamp - dpsmooth->start_interp) / (gfloat)dpsmooth->duration_interp;
GST_DEBUG(GST_CAT_PARAMS, "start:%lld current:%lld end:%lld ratio%f", dpsmooth->start_interp, timestamp, dpsmooth->end_interp, time_ratio);
GST_DEBUG(GST_CAT_PARAMS, "pre start:%f current:%f target:%f", dpsmooth->start_float, dpsmooth->current_float, dparam->value_float);
if (GST_DPARAM_IS_LOG(dparam)){
if (current == 0.0F){
/* this shouldn't happen, so forget about smoothing and just set the value */
final_val = target;
}
else {
gfloat current_log;
current_log = log(current);
current_diff = ABS(current_log - log(target));
GST_DEBUG(GST_CAT_PARAMS, "current_log:%f",current_log);
GST_DEBUG(GST_CAT_PARAMS, "current_diff:%f",current_diff);
if (current_diff > max_change){
final_val = (target < current) ? exp(current_log-max_change) : exp(current_log+max_change);
}
else {
final_val = target;
}
}
}
else {
current_diff = ABS (current - target);
if (current_diff > max_change){
final_val = (target < current) ? current-max_change : current+max_change;
}
else {
final_val = target;
}
dpsmooth->current_float = dpsmooth->start_float + (dpsmooth->diff_float * time_ratio);
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp + dpsmooth->update_period;
if (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) > dpsmooth->end_interp){
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = dpsmooth->end_interp;
}
GST_DPARAM_READY_FOR_UPDATE(dparam) = (final_val != target);
if (GST_DPARAM_READY_FOR_UPDATE(dparam)){
GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp + dpsmooth->update_period;
}
GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
g_value_set_float(value, final_val);
GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f final:%f actual:%f", target, current, final_val, g_value_get_float(value));
if (GST_DPARAM_IS_LOG(dparam)){
g_value_set_float(value, exp(dpsmooth->current_float));
}
else {
g_value_set_float(value, dpsmooth->current_float);
}
GST_DEBUG(GST_CAT_PARAMS, "post start:%f current:%f target:%f", dpsmooth->start_float, dpsmooth->current_float, dparam->value_float);
GST_DPARAM_UNLOCK(dparam);
}

View file

@ -40,9 +40,19 @@ typedef struct _GstDParamSmooth GstDParamSmooth;
struct _GstDParamSmooth {
GstDParam dparam;
gint64 start_interp;
gint64 end_interp;
gint64 duration_interp;
gfloat start_float;
gfloat diff_float;
gfloat current_float;
gint64 update_period;
gint64 slope_time;
gfloat slope_delta_float;
gboolean need_interp_times;
};
struct _GstDParamSmoothClass {