- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# timer.c

    00001 /*
    00002  * libmad - MPEG audio decoder library
    00003  * Copyright (C) 2000-2003 Underbit Technologies, Inc.
    00004  *
    00005  * This program is free software; you can redistribute it and/or modify
    00006  * it under the terms of the GNU General Public License as published by
    00007  * the Free Software Foundation; either version 2 of the License, or
    00008  * (at your option) any later version.
    00009  *
    00010  * This program is distributed in the hope that it will be useful,
    00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013  * GNU General Public License for more details.
    00014  *
    00015  * You should have received a copy of the GNU General Public License
    00016  * along with this program; if not, write to the Free Software
    00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00018  *
    00019  * $Id: timer.c,v 1.1 2003/08/31 19:00:17 gabest Exp $
    00020  */
    00021
    00022 # ifdef HAVE_CONFIG_H
    00023 #  include "config.h"
    00024 # endif
    00025
    00026 # include "global.h"
    00027
    00028 # include <stdio.h>
    00029
    00030 # ifdef HAVE_ASSERT_H
    00031 #  include <assert.h>
    00032 # endif
    00033
    00034 # include "timer.h"
    00035
    00036 mad_timer_t const mad_timer_zero = { 0, 0 };
    00037
    00038 /*
    00039  * NAME:        timer->compare()
    00040  * DESCRIPTION: indicate relative order of two timers
    00041  */
    00042 int mad_timer_compare(mad_timer_t timer1, mad_timer_t timer2)
    00043 {
    00044   signed long diff;
    00045
    00046   diff = timer1.seconds - timer2.seconds;
    00047   if (diff < 0)
    00048     return -1;
    00049   else if (diff > 0)
    00050     return +1;
    00051
    00052   diff = timer1.fraction - timer2.fraction;
    00053   if (diff < 0)
    00054     return -1;
    00055   else if (diff > 0)
    00056     return +1;
    00057
    00058   return 0;
    00059 }
    00060
    00061 /*
    00062  * NAME:        timer->negate()
    00063  * DESCRIPTION: invert the sign of a timer
    00064  */
    00065 void mad_timer_negate(mad_timer_t *timer)
    00066 {
    00067   timer->seconds = -timer->seconds;
    00068
    00069   if (timer->fraction) {
    00070     timer->seconds -= 1;
    00071     timer->fraction = MAD_TIMER_RESOLUTION - timer->fraction;
    00072   }
    00073 }
    00074
    00075 /*
    00076  * NAME:        timer->abs()
    00077  * DESCRIPTION: return the absolute value of a timer
    00078  */
    00079 mad_timer_t mad_timer_abs(mad_timer_t timer)
    00080 {
    00081   if (timer.seconds < 0)
    00082     mad_timer_negate(&timer);
    00083
    00084   return timer;
    00085 }
    00086
    00087 /*
    00088  * NAME:        reduce_timer()
    00089  * DESCRIPTION: carry timer fraction into seconds
    00090  */
    00091 static
    00092 void reduce_timer(mad_timer_t *timer)
    00093 {
    00094   timer->seconds  += timer->fraction / MAD_TIMER_RESOLUTION;
    00095   timer->fraction %= MAD_TIMER_RESOLUTION;
    00096 }
    00097
    00098 /*
    00099  * NAME:        gcd()
    00100  * DESCRIPTION: compute greatest common denominator
    00101  */
    00102 static
    00103 unsigned long gcd(unsigned long num1, unsigned long num2)
    00104 {
    00105   unsigned long tmp;
    00106
    00107   while (num2) {
    00108     tmp  = num2;
    00109     num2 = num1 % num2;
    00110     num1 = tmp;
    00111   }
    00112
    00113   return num1;
    00114 }
    00115
    00116 /*
    00117  * NAME:        reduce_rational()
    00118  * DESCRIPTION: convert rational expression to lowest terms
    00119  */
    00120 static
    00121 void reduce_rational(unsigned long *numer, unsigned long *denom)
    00122 {
    00123   unsigned long factor;
    00124
    00125   factor = gcd(*numer, *denom);
    00126
    00127   assert(factor != 0);
    00128
    00129   *numer /= factor;
    00130   *denom /= factor;
    00131 }
    00132
    00133 /*
    00134  * NAME:        scale_rational()
    00135  * DESCRIPTION: solve numer/denom == ?/scale avoiding overflowing
    00136  */
    00137 static
    00138 unsigned long scale_rational(unsigned long numer, unsigned long denom,
    00139                              unsigned long scale)
    00140 {
    00141   reduce_rational(&numer, &denom);
    00142   reduce_rational(&scale, &denom);
    00143
    00144   assert(denom != 0);
    00145
    00146   if (denom < scale)
    00147     return numer * (scale / denom) + numer * (scale % denom) / denom;
    00148   if (denom < numer)
    00149     return scale * (numer / denom) + scale * (numer % denom) / denom;
    00150
    00151   return numer * scale / denom;
    00152 }
    00153
    00154 /*
    00155  * NAME:        timer->set()
    00156  * DESCRIPTION: set timer to specific (positive) value
    00157  */
    00158 void mad_timer_set(mad_timer_t *timer, unsigned long seconds,
    00159                    unsigned long numer, unsigned long denom)
    00160 {
    00161   timer->seconds = seconds;
    00162   if (numer >= denom && denom > 0) {
    00163     timer->seconds += numer / denom;
    00164     numer %= denom;
    00165   }
    00166
    00167   switch (denom) {
    00168   case 0:
    00169   case 1:
    00170     timer->fraction = 0;
    00171     break;
    00172
    00173   case MAD_TIMER_RESOLUTION:
    00174     timer->fraction = numer;
    00175     break;
    00176
    00177   case 1000:
    00178     timer->fraction = numer * (MAD_TIMER_RESOLUTION /  1000);
    00179     break;
    00180
    00181   case 8000:
    00182     timer->fraction = numer * (MAD_TIMER_RESOLUTION /  8000);
    00183     break;
    00184
    00185   case 11025:
    00186     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 11025);
    00187     break;
    00188
    00189   case 12000:
    00190     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 12000);
    00191     break;
    00192
    00193   case 16000:
    00194     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 16000);
    00195     break;
    00196
    00197   case 22050:
    00198     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 22050);
    00199     break;
    00200
    00201   case 24000:
    00202     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 24000);
    00203     break;
    00204
    00205   case 32000:
    00206     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 32000);
    00207     break;
    00208
    00209   case 44100:
    00210     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 44100);
    00211     break;
    00212
    00213   case 48000:
    00214     timer->fraction = numer * (MAD_TIMER_RESOLUTION / 48000);
    00215     break;
    00216
    00217   default:
    00218     timer->fraction = scale_rational(numer, denom, MAD_TIMER_RESOLUTION);
    00219     break;
    00220   }
    00221
    00222   if (timer->fraction >= MAD_TIMER_RESOLUTION)
    00223     reduce_timer(timer);
    00224 }
    00225
    00226 /*
    00227  * NAME:        timer->add()
    00228  * DESCRIPTION: add one timer to another
    00229  */
    00230 void mad_timer_add(mad_timer_t *timer, mad_timer_t incr)
    00231 {
    00232   timer->seconds  += incr.seconds;
    00233   timer->fraction += incr.fraction;
    00234
    00235   if (timer->fraction >= MAD_TIMER_RESOLUTION)
    00236     reduce_timer(timer);
    00237 }
    00238
    00239 /*
    00240  * NAME:        timer->multiply()
    00241  * DESCRIPTION: multiply a timer by a scalar value
    00242  */
    00243 void mad_timer_multiply(mad_timer_t *timer, signed long scalar)
    00244 {
    00245   mad_timer_t addend;
    00246   unsigned long factor;
    00247
    00248   factor = scalar;
    00249   if (scalar < 0) {
    00250     factor = -scalar;
    00251     mad_timer_negate(timer);
    00252   }
    00253
    00254   addend = *timer;
    00255   *timer = mad_timer_zero;
    00256
    00257   while (factor) {
    00258     if (factor & 1)
    00259       mad_timer_add(timer, addend);
    00260
    00261     mad_timer_add(&addend, addend);
    00262     factor >>= 1;
    00263   }
    00264 }
    00265
    00266 /*
    00267  * NAME:        timer->count()
    00268  * DESCRIPTION: return timer value in selected units
    00269  */
    00270 signed long mad_timer_count(mad_timer_t timer, enum mad_units units)
    00271 {
    00272   switch (units) {
    00273   case MAD_UNITS_HOURS:
    00274     return timer.seconds / 60 / 60;
    00275
    00276   case MAD_UNITS_MINUTES:
    00277     return timer.seconds / 60;
    00278
    00279   case MAD_UNITS_SECONDS:
    00280     return timer.seconds;
    00281
    00282   case MAD_UNITS_DECISECONDS:
    00283   case MAD_UNITS_CENTISECONDS:
    00284   case MAD_UNITS_MILLISECONDS:
    00285
    00286   case MAD_UNITS_8000_HZ:
    00287   case MAD_UNITS_11025_HZ:
    00288   case MAD_UNITS_12000_HZ:
    00289   case MAD_UNITS_16000_HZ:
    00290   case MAD_UNITS_22050_HZ:
    00291   case MAD_UNITS_24000_HZ:
    00292   case MAD_UNITS_32000_HZ:
    00293   case MAD_UNITS_44100_HZ:
    00294   case MAD_UNITS_48000_HZ:
    00295
    00296   case MAD_UNITS_24_FPS:
    00297   case MAD_UNITS_25_FPS:
    00298   case MAD_UNITS_30_FPS:
    00299   case MAD_UNITS_48_FPS:
    00300   case MAD_UNITS_50_FPS:
    00301   case MAD_UNITS_60_FPS:
    00302   case MAD_UNITS_75_FPS:
    00303     return timer.seconds * (signed long) units +
    00304       (signed long) scale_rational(timer.fraction, MAD_TIMER_RESOLUTION,
    00305                                    units);
    00306
    00307   case MAD_UNITS_23_976_FPS:
    00308   case MAD_UNITS_24_975_FPS:
    00309   case MAD_UNITS_29_97_FPS:
    00310   case MAD_UNITS_47_952_FPS:
    00311   case MAD_UNITS_49_95_FPS:
    00312   case MAD_UNITS_59_94_FPS:
    00313     return (mad_timer_count(timer, -units) + 1) * 1000 / 1001;
    00314   }
    00315
    00316   /* unsupported units */
    00317   return 0;
    00318 }
    00319
    00320 /*
    00321  * NAME:        timer->fraction()
    00322  * DESCRIPTION: return fractional part of timer in arbitrary terms
    00323  */
    00324 unsigned long mad_timer_fraction(mad_timer_t timer, unsigned long denom)
    00325 {
    00326   timer = mad_timer_abs(timer);
    00327
    00328   switch (denom) {
    00329   case 0:
    00330     return timer.fraction ?
    00331       MAD_TIMER_RESOLUTION / timer.fraction : MAD_TIMER_RESOLUTION + 1;
    00332
    00333   case MAD_TIMER_RESOLUTION:
    00334     return timer.fraction;
    00335
    00336   default:
    00337     return scale_rational(timer.fraction, MAD_TIMER_RESOLUTION, denom);
    00338   }
    00339 }
    00340
    00341 /*
    00342  * NAME:        timer->string()
    00343  * DESCRIPTION: write a string representation of a timer using a template
    00344  */
    00345 void mad_timer_string(mad_timer_t timer,
    00346                       char *dest, char const *format, enum mad_units units,
    00347                       enum mad_units fracunits, unsigned long subparts)
    00348 {
    00349   unsigned long hours, minutes, seconds, sub;
    00350   unsigned int frac;
    00351
    00352   timer = mad_timer_abs(timer);
    00353
    00354   seconds = timer.seconds;
    00355   frac = sub = 0;
    00356
    00357   switch (fracunits) {
    00358   case MAD_UNITS_HOURS:
    00359   case MAD_UNITS_MINUTES:
    00360   case MAD_UNITS_SECONDS:
    00361     break;
    00362
    00363   case MAD_UNITS_DECISECONDS:
    00364   case MAD_UNITS_CENTISECONDS:
    00365   case MAD_UNITS_MILLISECONDS:
    00366
    00367   case MAD_UNITS_8000_HZ:
    00368   case MAD_UNITS_11025_HZ:
    00369   case MAD_UNITS_12000_HZ:
    00370   case MAD_UNITS_16000_HZ:
    00371   case MAD_UNITS_22050_HZ:
    00372   case MAD_UNITS_24000_HZ:
    00373   case MAD_UNITS_32000_HZ:
    00374   case MAD_UNITS_44100_HZ:
    00375   case MAD_UNITS_48000_HZ:
    00376
    00377   case MAD_UNITS_24_FPS:
    00378   case MAD_UNITS_25_FPS:
    00379   case MAD_UNITS_30_FPS:
    00380   case MAD_UNITS_48_FPS:
    00381   case MAD_UNITS_50_FPS:
    00382   case MAD_UNITS_60_FPS:
    00383   case MAD_UNITS_75_FPS:
    00384     {
    00385       unsigned long denom;
    00386
    00387       denom = MAD_TIMER_RESOLUTION / fracunits;
    00388
    00389       frac = timer.fraction / denom;
    00390       sub  = scale_rational(timer.fraction % denom, denom, subparts);
    00391     }
    00392     break;
    00393
    00394   case MAD_UNITS_23_976_FPS:
    00395   case MAD_UNITS_24_975_FPS:
    00396   case MAD_UNITS_29_97_FPS:
    00397   case MAD_UNITS_47_952_FPS:
    00398   case MAD_UNITS_49_95_FPS:
    00399   case MAD_UNITS_59_94_FPS:
    00400     /* drop-frame encoding */
    00401     /* N.B. this is only well-defined for MAD_UNITS_29_97_FPS */
    00402     {
    00403       unsigned long frame, cycle, d, m;
    00404
    00405       frame = mad_timer_count(timer, fracunits);
    00406
    00407       cycle = -fracunits * 60 * 10 - (10 - 1) * 2;
    00408
    00409       d = frame / cycle;
    00410       m = frame % cycle;
    00411       frame += (10 - 1) * 2 * d;
    00412       if (m > 2)
    00413         frame += 2 * ((m - 2) / (cycle / 10));
    00414
    00415       frac    = frame % -fracunits;
    00416       seconds = frame / -fracunits;
    00417     }
    00418     break;
    00419   }
    00420
    00421   switch (units) {
    00422   case MAD_UNITS_HOURS:
    00423     minutes = seconds / 60;
    00424     hours   = minutes / 60;
    00425
    00426     sprintf(dest, format,
    00427             hours,
    00428             (unsigned int) (minutes % 60),
    00429             (unsigned int) (seconds % 60),
    00430             frac, sub);
    00431     break;
    00432
    00433   case MAD_UNITS_MINUTES:
    00434     minutes = seconds / 60;
    00435
    00436     sprintf(dest, format,
    00437             minutes,
    00438             (unsigned int) (seconds % 60),
    00439             frac, sub);
    00440     break;
    00441
    00442   case MAD_UNITS_SECONDS:
    00443     sprintf(dest, format,
    00444             seconds,
    00445             frac, sub);
    00446     break;
    00447
    00448   case MAD_UNITS_23_976_FPS:
    00449   case MAD_UNITS_24_975_FPS:
    00450   case MAD_UNITS_29_97_FPS:
    00451   case MAD_UNITS_47_952_FPS:
    00452   case MAD_UNITS_49_95_FPS:
    00453   case MAD_UNITS_59_94_FPS:
    00454     if (fracunits < 0) {
    00455       /* not yet implemented */
    00456       sub = 0;
    00457     }
    00458
    00459     /* fall through */
    00460
    00461   case MAD_UNITS_DECISECONDS:
    00462   case MAD_UNITS_CENTISECONDS:
    00463   case MAD_UNITS_MILLISECONDS:
    00464
    00465   case MAD_UNITS_8000_HZ:
    00466   case MAD_UNITS_11025_HZ:
    00467   case MAD_UNITS_12000_HZ:
    00468   case MAD_UNITS_16000_HZ:
    00469   case MAD_UNITS_22050_HZ:
    00470   case MAD_UNITS_24000_HZ:
    00471   case MAD_UNITS_32000_HZ:
    00472   case MAD_UNITS_44100_HZ:
    00473   case MAD_UNITS_48000_HZ:
    00474
    00475   case MAD_UNITS_24_FPS:
    00476   case MAD_UNITS_25_FPS:
    00477   case MAD_UNITS_30_FPS:
    00478   case MAD_UNITS_48_FPS:
    00479   case MAD_UNITS_50_FPS:
    00480   case MAD_UNITS_60_FPS:
    00481   case MAD_UNITS_75_FPS:
    00482     sprintf(dest, format, mad_timer_count(timer, units), sub);
    00483     break;
    00484   }
    00485 }