annotate src/libmad-0.15.1b/timer.c @ 23:619f715526df sv_v2.1

Update Vamp plugin SDK to 2.5
author Chris Cannam
date Thu, 09 May 2013 10:52:46 +0100
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 }