3 * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
5 * gstinterpolation.c: Interpolation methods for dynamic properties
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #include "gstcontroller.h"
26 #define GST_CAT_DEFAULT gst_controller_debug
27 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
32 * gst_controlled_property_find_timed_value_node:
33 * @prop: the controlled property to search in
34 * @timestamp: the search key
36 * Find last value before given timestamp in timed value list.
38 * Returns: the found #GList node or %NULL
41 gst_controlled_property_find_timed_value_node (GstControlledProperty * prop,
42 GstClockTime timestamp)
44 //GList *prev_node = NULL;
45 GList *prev_node = g_list_last (prop->values);
50 if((prop->last_value) &&
51 (timestamp>((GstTimedValue *)(prop->last_value->data))->timestamp)) {
52 node=prop->last_value;
59 /* iterate over timed value list */
60 for (node = prop->values; node; node = g_list_next (node)) {
62 /* this timestamp is newer that the one we look for */
63 if (timestamp < tv->timestamp) {
64 /* get previous one again */
65 prev_node = g_list_previous (node);
71 prop->last_value=prev_node;
77 // steps-like (no-)interpolation, default
78 // just returns the value for the most recent key-frame
81 interpolate_none_get (GstControlledProperty * prop, GstClockTime timestamp)
85 if ((node = gst_controlled_property_find_timed_value_node (prop, timestamp))) {
86 GstTimedValue *tv = node->data;
90 return (&prop->default_value);
93 #define DEFINE_NONE_GET(type) \
95 interpolate_none_get_##type##_value_array (GstControlledProperty * prop, \
96 GstClockTime timestamp, GstValueArray * value_array) \
99 GstClockTime ts=timestamp; \
100 g##type *values=(g##type *)value_array->values; \
102 for(i=0;i<value_array->nbsamples;i++) { \
103 *values=g_value_get_##type (interpolate_none_get (prop,ts)); \
104 ts+=value_array->sample_interval; \
110 DEFINE_NONE_GET (int)
111 DEFINE_NONE_GET (long)
112 DEFINE_NONE_GET (float)
113 DEFINE_NONE_GET (double)
114 DEFINE_NONE_GET (boolean)
116 static GstInterpolateMethod interpolate_none = {
117 interpolate_none_get,
118 interpolate_none_get_int_value_array,
119 interpolate_none_get,
120 interpolate_none_get_long_value_array,
121 interpolate_none_get,
122 interpolate_none_get_float_value_array,
123 interpolate_none_get,
124 interpolate_none_get_double_value_array,
125 interpolate_none_get,
126 interpolate_none_get_boolean_value_array
129 // returns the default value of the property, except for times with specific values
130 // needed for one-shot events, such as notes and triggers
133 interpolate_trigger_get (GstControlledProperty * prop, GstClockTime timestamp)
138 /* check if there is a value at the registered timestamp */
139 for (node = prop->values; node; node = g_list_next (node)) {
141 if (timestamp == tv->timestamp) {
146 return (&prop->default_value);
150 interpolate_trigger_get_value_array (GstControlledProperty * prop,
151 GstClockTime timestamp, GstValueArray * value_array)
156 static GstInterpolateMethod interpolate_trigger = {
157 interpolate_trigger_get,
158 interpolate_trigger_get_value_array,
159 interpolate_trigger_get,
161 interpolate_trigger_get,
163 interpolate_trigger_get,
165 interpolate_trigger_get,
169 // linear interpolation
170 // smoothes inbetween values
172 #define DEFINE_LINEAR_GET(type) \
174 _interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \
178 if ((node = gst_controlled_property_find_timed_value_node (prop, timestamp))) { \
179 GstTimedValue *tv1, *tv2; \
182 if ((node = g_list_next (node))) { \
183 gdouble timediff,valuediff; \
184 g##type value1,value2; \
188 timediff = (gdouble)(tv2->timestamp - tv1->timestamp); \
189 value1 = g_value_get_##type (&tv1->value); \
190 value2 = g_value_get_##type (&tv2->value); \
191 valuediff = (gdouble)(value2-value1); \
193 return((g##type)(value1+valuediff*((timestamp-tv1->timestamp)/timediff))); \
196 return (g_value_get_##type (&tv1->value)); \
199 return (g_value_get_##type (&prop->default_value)); \
203 interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \
205 g_value_set_##type (&prop->result_value,_interpolate_linear_get_##type (prop,timestamp)); \
206 return (&prop->result_value); \
210 interpolate_linear_get_##type##_value_array (GstControlledProperty * prop, \
211 GstClockTime timestamp, GstValueArray * value_array) \
214 GstClockTime ts=timestamp; \
215 gint *values=(gint *)value_array->values; \
217 for(i=0;i<value_array->nbsamples;i++) { \
218 *values=_interpolate_linear_get_##type (prop,ts); \
219 ts+=value_array->sample_interval; \
225 DEFINE_LINEAR_GET (int)
226 DEFINE_LINEAR_GET (long)
227 DEFINE_LINEAR_GET (float)
228 DEFINE_LINEAR_GET (double)
230 static GstInterpolateMethod interpolate_linear = {
231 interpolate_linear_get_int,
232 interpolate_linear_get_int_value_array,
233 interpolate_linear_get_long,
234 interpolate_linear_get_long_value_array,
235 interpolate_linear_get_float,
236 interpolate_linear_get_float_value_array,
237 interpolate_linear_get_double,
238 interpolate_linear_get_double_value_array,
243 // square interpolation
245 // cubic interpolation
247 // register all interpolation methods
248 GstInterpolateMethod *interpolation_methods[] = {
250 &interpolate_trigger,