mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-16 19:25:18 +00:00
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:
parent
e1fe257bc9
commit
fc7a6ad8c9
2 changed files with 85 additions and 54 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue