MP3 Player without external hardware MP3 Player without external hardware. A software based MP3 player based on a modified version of libmad. Mono output (at the moment) via AnalogOut. Files are read from an USB drive. This is a demo program, it plays only one file at the moment. Documentation is in "main.cpp" and "config.h"

Dependencies:   mbed

Committer:
Gruenfrosch
Date:
Fri Nov 26 12:18:30 2010 +0000
Revision:
0:7627c79db971
Child:
2:f28cf0afd021
First Version

Who changed what in which revision?

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