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