summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmad/timer.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/libmad/timer.c') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/timer.c480
1 files changed, 480 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmad/timer.c b/core/multimedia/opieplayer/libmad/timer.c
new file mode 100644
index 0000000..b30680c
--- a/dev/null
+++ b/core/multimedia/opieplayer/libmad/timer.c
@@ -0,0 +1,480 @@
1/*
2 * mad - MPEG audio decoder
3 * Copyright (C) 2000-2001 Robert Leslie
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * $Id$
20 */
21
22# ifdef HAVE_CONFIG_H
23# include "libmad_config.h"
24# endif
25
26# include "libmad_global.h"
27
28# include <stdio.h>
29# include <assert.h>
30
31# include "timer.h"
32
33mad_timer_t const mad_timer_zero = { 0, 0 };
34
35/*
36 * NAME:timer->compare()
37 * DESCRIPTION:indicate relative order of two timers
38 */
39int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2)
40{
41 signed long diff;
42
43 diff = timer1.seconds - timer2.seconds;
44 if (diff < 0)
45 return -1;
46 else if (diff > 0)
47 return +1;
48
49 diff = timer1.fraction - timer2.fraction;
50 if (diff < 0)
51 return -1;
52 else if (diff > 0)
53 return +1;
54
55 return 0;
56}
57
58/*
59 * NAME:timer->negate()
60 * DESCRIPTION:invert the sign of a timer
61 */
62void mad_timer_negate(mad_timer_t *timer)
63{
64 timer->seconds = -timer->seconds;
65
66 if (timer->fraction) {
67 timer->seconds -= 1;
68 timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction;
69 }
70}
71
72/*
73 * NAME:timer->abs()
74 * DESCRIPTION:return the absolute value of a timer
75 */
76mad_timer_t mad_timer_abs(mad_timer_t timer)
77{
78 if (mad_timer_sign(timer) < 0)
79 mad_timer_negate(&timer);
80
81 return timer;
82}
83
84/*
85 * NAME:reduce_timer()
86 * DESCRIPTION:carry timer fraction into seconds
87 */
88static
89void reduce_timer(mad_timer_t *timer)
90{
91 timer->seconds += timer->fraction / MAD_TIMER_RESOLUTION;
92 timer->fraction %= MAD_TIMER_RESOLUTION;
93}
94
95/*
96 * NAME:gcd()
97 * DESCRIPTION:compute greatest common denominator
98 */
99static
100unsigned long gcd(unsigned long num1, unsigned long num2)
101{
102 unsigned long tmp;
103
104 while (num2) {
105 tmp = num2;
106 num2 = num1 % num2;
107 num1 = tmp;
108 }
109
110 return num1;
111}
112
113/*
114 * NAME:reduce_rational()
115 * DESCRIPTION:convert rational expression to lowest terms
116 */
117static
118void reduce_rational(unsigned long *numer, unsigned long *denom)
119{
120 unsigned long factor;
121
122 factor = gcd(*numer, *denom);
123
124 assert(factor != 0);
125
126 *numer /= factor;
127 *denom /= factor;
128}
129
130/*
131 * NAME:scale_rational()
132 * DESCRIPTION:solve numer/denom == ?/scale avoiding overflowing
133 */
134static
135unsigned long scale_rational(unsigned long numer, unsigned long denom,
136 unsigned long scale)
137{
138 reduce_rational(&numer, &denom);
139 reduce_rational(&scale, &denom);
140
141 assert(denom != 0);
142
143 if (denom < scale)
144 return numer * (scale / denom) + numer * (scale % denom) / denom;
145 if (denom < numer)
146 return scale * (numer / denom) + scale * (numer % denom) / denom;
147
148 return numer * scale / denom;
149}
150
151/*
152 * NAME:timer->set()
153 * DESCRIPTION:set timer to specific value
154 */
155void mad_timer_set(mad_timer_t *timer, unsigned long seconds,
156 unsigned long fraction, unsigned long fracparts)
157{
158 timer->seconds = seconds;
159
160 if (fraction == 0)
161 fracparts = 0;
162 else if (fracparts == 0) {
163 fracparts = fraction;
164 fraction = 1;
165 }
166
167 switch (fracparts) {
168 case 0:
169 timer->fraction = 0;
170 break;
171
172 case MAD_TIMER_RESOLUTION:
173 timer->fraction = fraction;
174 break;
175
176 case 8000:
177 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 8000);
178 break;
179
180 case 11025:
181 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 11025);
182 break;
183
184 case 12000:
185 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 12000);
186 break;
187
188 case 16000:
189 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 16000);
190 break;
191
192 case 22050:
193 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 22050);
194 break;
195
196 case 24000:
197 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 24000);
198 break;
199
200 case 32000:
201 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 32000);
202 break;
203
204 case 44100:
205 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 44100);
206 break;
207
208 case 48000:
209 timer->fraction = fraction * (MAD_TIMER_RESOLUTION / 48000);
210 break;
211
212 default:
213 timer->fraction =
214 scale_rational(fraction, fracparts, MAD_TIMER_RESOLUTION);
215 break;
216 }
217
218 if (timer->fraction >= MAD_TIMER_RESOLUTION)
219 reduce_timer(timer);
220}
221
222/*
223 * NAME:timer->add()
224 * DESCRIPTION:add one timer to another
225 */
226void mad_timer_add(mad_timer_t *timer, mad_timer_t incr)
227{
228 timer->seconds += incr.seconds;
229 timer->fraction += incr.fraction;
230
231 if (timer->fraction >= MAD_TIMER_RESOLUTION)
232 reduce_timer(timer);
233}
234
235/*
236 * NAME:timer->multiply()
237 * DESCRIPTION:multiply a timer by a scalar value
238 */
239void mad_timer_multiply(mad_timer_t *timer, signed long scalar)
240{
241 mad_timer_t addend;
242 unsigned long factor;
243
244 factor = scalar;
245 if (scalar < 0) {
246 mad_timer_negate(timer);
247 factor = -scalar;
248 }
249
250 addend = *timer;
251 *timer = mad_timer_zero;
252
253 while (factor) {
254 if (factor & 1)
255 mad_timer_add(timer, addend);
256
257 mad_timer_add(&addend, addend);
258 factor >>= 1;
259 }
260}
261
262/*
263 * NAME:timer->count()
264 * DESCRIPTION:return timer value in selected units
265 */
266signed long mad_timer_count(mad_timer_t timer, enum mad_units units)
267{
268 switch (units) {
269 case MAD_UNITS_HOURS:
270 return timer.seconds / 60 / 60;
271
272 case MAD_UNITS_MINUTES:
273 return timer.seconds / 60;
274
275 case MAD_UNITS_SECONDS:
276 return timer.seconds;
277
278 case MAD_UNITS_DECISECONDS:
279 case MAD_UNITS_CENTISECONDS:
280 case MAD_UNITS_MILLISECONDS:
281
282 case MAD_UNITS_8000_HZ:
283 case MAD_UNITS_11025_HZ:
284 case MAD_UNITS_12000_HZ:
285 case MAD_UNITS_16000_HZ:
286 case MAD_UNITS_22050_HZ:
287 case MAD_UNITS_24000_HZ:
288 case MAD_UNITS_32000_HZ:
289 case MAD_UNITS_44100_HZ:
290 case MAD_UNITS_48000_HZ:
291
292 case MAD_UNITS_24_FPS:
293 case MAD_UNITS_25_FPS:
294 case MAD_UNITS_30_FPS:
295 case MAD_UNITS_48_FPS:
296 case MAD_UNITS_50_FPS:
297 case MAD_UNITS_60_FPS:
298 case MAD_UNITS_75_FPS:
299 return timer.seconds * (signed long) units +
300 (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION,
301 units);
302
303 case MAD_UNITS_23_976_FPS:
304 case MAD_UNITS_24_975_FPS:
305 case MAD_UNITS_29_97_FPS:
306 case MAD_UNITS_47_952_FPS:
307 case MAD_UNITS_49_95_FPS:
308 case MAD_UNITS_59_94_FPS:
309 return (mad_timer_count(timer, -units) + 1) * 1000 / 1001;
310 }
311
312 /* unsupported units */
313 return 0;
314}
315
316/*
317 * NAME:timer->fraction()
318 * DESCRIPTION:return fractional part of timer in arbitrary terms
319 */
320unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long fracparts)
321{
322 timer = mad_timer_abs(timer);
323
324 switch (fracparts) {
325 case 0:
326 return MAD_TIMER_RESOLUTION / timer.fraction;
327
328 case MAD_TIMER_RESOLUTION:
329 return timer.fraction;
330
331 default:
332 return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, fracparts);
333 }
334}
335
336/*
337 * NAME:timer->string()
338 * DESCRIPTION:write a string representation of a timer using a template
339 */
340void mad_timer_string(mad_timer_t timer,
341 char *dest, char const *format, enum mad_units units,
342 enum mad_units fracunits, unsigned long subparts)
343{
344 unsigned long hours, minutes, seconds, sub;
345 unsigned int frac;
346
347 timer = mad_timer_abs(timer);
348
349 seconds = timer.seconds;
350 frac = sub = 0;
351
352 switch (fracunits) {
353 case MAD_UNITS_HOURS:
354 case MAD_UNITS_MINUTES:
355 case MAD_UNITS_SECONDS:
356 break;
357
358 case MAD_UNITS_DECISECONDS:
359 case MAD_UNITS_CENTISECONDS:
360 case MAD_UNITS_MILLISECONDS:
361
362 case MAD_UNITS_8000_HZ:
363 case MAD_UNITS_11025_HZ:
364 case MAD_UNITS_12000_HZ:
365 case MAD_UNITS_16000_HZ:
366 case MAD_UNITS_22050_HZ:
367 case MAD_UNITS_24000_HZ:
368 case MAD_UNITS_32000_HZ:
369 case MAD_UNITS_44100_HZ:
370 case MAD_UNITS_48000_HZ:
371
372 case MAD_UNITS_24_FPS:
373 case MAD_UNITS_25_FPS:
374 case MAD_UNITS_30_FPS:
375 case MAD_UNITS_48_FPS:
376 case MAD_UNITS_50_FPS:
377 case MAD_UNITS_60_FPS:
378 case MAD_UNITS_75_FPS:
379 {
380 unsigned long fracparts;
381
382 fracparts = MAD_TIMER_RESOLUTION / fracunits;
383
384 frac = timer.fraction / fracparts;
385 sub = scale_rational(timer.fraction % fracparts, fracparts, subparts);
386 }
387 break;
388
389 case MAD_UNITS_23_976_FPS:
390 case MAD_UNITS_24_975_FPS:
391 case MAD_UNITS_29_97_FPS:
392 case MAD_UNITS_47_952_FPS:
393 case MAD_UNITS_49_95_FPS:
394 case MAD_UNITS_59_94_FPS:
395 /* drop-frame encoding */
396 /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */
397 {
398 unsigned long frame, cycle, d, m;
399
400 frame = mad_timer_count(timer, fracunits);
401
402 cycle = -fracunits * 60 * 10 - (10 - 1) * 2;
403
404 d = frame / cycle;
405 m = frame % cycle;
406 frame += (10 - 1) * 2 * d;
407 if (m > 2)
408 frame += 2 * ((m - 2) / (cycle / 10));
409
410 frac = frame % -fracunits;
411 seconds = frame / -fracunits;
412 }
413 break;
414 }
415
416 switch (units) {
417 case MAD_UNITS_HOURS:
418 minutes = seconds / 60;
419 hours = minutes / 60;
420
421 sprintf(dest, format,
422 hours,
423 (unsigned int) (minutes % 60),
424 (unsigned int) (seconds % 60),
425 frac, sub);
426 break;
427
428 case MAD_UNITS_MINUTES:
429 minutes = seconds / 60;
430
431 sprintf(dest, format,
432 minutes,
433 (unsigned int) (seconds % 60),
434 frac, sub);
435 break;
436
437 case MAD_UNITS_SECONDS:
438 sprintf(dest, format,
439 seconds,
440 frac, sub);
441 break;
442
443 case MAD_UNITS_23_976_FPS:
444 case MAD_UNITS_24_975_FPS:
445 case MAD_UNITS_29_97_FPS:
446 case MAD_UNITS_47_952_FPS:
447 case MAD_UNITS_49_95_FPS:
448 case MAD_UNITS_59_94_FPS:
449 if (fracunits < 0) {
450 /* not yet implemented */
451 sub = 0;
452 }
453
454 /* fall through */
455
456 case MAD_UNITS_DECISECONDS:
457 case MAD_UNITS_CENTISECONDS:
458 case MAD_UNITS_MILLISECONDS:
459
460 case MAD_UNITS_8000_HZ:
461 case MAD_UNITS_11025_HZ:
462 case MAD_UNITS_12000_HZ:
463 case MAD_UNITS_16000_HZ:
464 case MAD_UNITS_22050_HZ:
465 case MAD_UNITS_24000_HZ:
466 case MAD_UNITS_32000_HZ:
467 case MAD_UNITS_44100_HZ:
468 case MAD_UNITS_48000_HZ:
469
470 case MAD_UNITS_24_FPS:
471 case MAD_UNITS_25_FPS:
472 case MAD_UNITS_30_FPS:
473 case MAD_UNITS_48_FPS:
474 case MAD_UNITS_50_FPS:
475 case MAD_UNITS_60_FPS:
476 case MAD_UNITS_75_FPS:
477 sprintf(dest, format, mad_timer_count(timer, units), sub);
478 break;
479 }
480}