MP3 Player. You can change fwd/rev speed and skip. see: http://mbed.org/users/okini3939/notebook/lpc4088_madplayer/

Dependencies:   I2SSlave SDFileSystem TLV320 mbed

Committer:
okini3939
Date:
Tue Feb 18 00:22:50 2014 +0000
Revision:
0:8ba6230eefbd
1st build

Who changed what in which revision?

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