annotate src/libmad-0.15.1b/timer.c @ 83:ae30d91d2ffe

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