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 }

Generated on Tue Dec 13 14:47:49 2005 for guliverkli by  doxygen 1.4.5