iPod: Code cleanup - the bootloader now compiles with zero warnings
[Rockbox.git] / firmware / replaygain.c
blob3a2e89757ac4c72086e45a64d01d284a1f193cf6
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Magnus Holmgren
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <ctype.h>
21 #include <inttypes.h>
22 #include <math.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <system.h>
28 #include "id3.h"
29 #include "debug.h"
31 /* The fixed point math routines (with the exception of fp_atof) are based
32 * on oMathFP by Dan Carter (http://orbisstudios.com).
35 /* 12 bits of precision gives fairly accurate result, but still allows a
36 * compact implementation. The math code supports up to 13...
39 #define FP_BITS (12)
40 #define FP_MASK ((1 << FP_BITS) - 1)
41 #define FP_ONE (1 << FP_BITS)
42 #define FP_TWO (2 << FP_BITS)
43 #define FP_HALF (1 << (FP_BITS - 1))
44 #define FP_LN2 ( 45426 >> (16 - FP_BITS))
45 #define FP_LN2_INV ( 94548 >> (16 - FP_BITS))
46 #define FP_EXP_ZERO ( 10922 >> (16 - FP_BITS))
47 #define FP_EXP_ONE ( -182 >> (16 - FP_BITS))
48 #define FP_EXP_TWO ( 4 >> (16 - FP_BITS))
49 #define FP_INF (0x7fffffff)
50 #define FP_LN10 (150902 >> (16 - FP_BITS))
52 #define FP_MAX_DIGITS (4)
53 #define FP_MAX_DIGITS_INT (10000)
55 #define FP_FAST_MUL_DIV
57 #ifdef FP_FAST_MUL_DIV
59 /* These macros can easily overflow, but they are good enough for our uses,
60 * and saves some code.
62 #define fp_mul(x, y) (((x) * (y)) >> FP_BITS)
63 #define fp_div(x, y) (((x) << FP_BITS) / (y))
65 #else
67 static long fp_mul(long x, long y)
69 long x_neg = 0;
70 long y_neg = 0;
71 long rc;
73 if ((x == 0) || (y == 0))
75 return 0;
78 if (x < 0)
80 x_neg = 1;
81 x = -x;
84 if (y < 0)
86 y_neg = 1;
87 y = -y;
90 rc = (((x >> FP_BITS) * (y >> FP_BITS)) << FP_BITS)
91 + (((x & FP_MASK) * (y & FP_MASK)) >> FP_BITS)
92 + ((x & FP_MASK) * (y >> FP_BITS))
93 + ((x >> FP_BITS) * (y & FP_MASK));
95 if ((x_neg ^ y_neg) == 1)
97 rc = -rc;
100 return rc;
103 static long fp_div(long x, long y)
105 long x_neg = 0;
106 long y_neg = 0;
107 long shifty;
108 long rc;
109 int msb = 0;
110 int lsb = 0;
112 if (x == 0)
114 return 0;
117 if (y == 0)
119 return (x < 0) ? -FP_INF : FP_INF;
122 if (x < 0)
124 x_neg = 1;
125 x = -x;
128 if (y < 0)
130 y_neg = 1;
131 y = -y;
134 while ((x & (1 << (30 - msb))) == 0)
136 msb++;
139 while ((y & (1 << lsb)) == 0)
141 lsb++;
144 shifty = FP_BITS - (msb + lsb);
145 rc = ((x << msb) / (y >> lsb));
147 if (shifty > 0)
149 rc <<= shifty;
151 else
153 rc >>= -shifty;
156 if ((x_neg ^ y_neg) == 1)
158 rc = -rc;
161 return rc;
164 #endif /* FP_FAST_MUL_DIV */
166 static long fp_exp(long x)
168 long k;
169 long z;
170 long R;
171 long xp;
173 if (x == 0)
175 return FP_ONE;
178 k = (fp_mul(abs(x), FP_LN2_INV) + FP_HALF) & ~FP_MASK;
180 if (x < 0)
182 k = -k;
185 x -= fp_mul(k, FP_LN2);
186 z = fp_mul(x, x);
187 R = FP_TWO + fp_mul(z, FP_EXP_ZERO + fp_mul(z, FP_EXP_ONE
188 + fp_mul(z, FP_EXP_TWO)));
189 xp = FP_ONE + fp_div(fp_mul(FP_TWO, x), R - x);
191 if (k < 0)
193 k = FP_ONE >> (-k >> FP_BITS);
195 else
197 k = FP_ONE << (k >> FP_BITS);
200 return fp_mul(k, xp);
203 static long fp_exp10(long x)
205 if (x == 0)
207 return FP_ONE;
210 return fp_exp(fp_mul(FP_LN10, x));
213 static long fp_atof(const char* s, int precision)
215 long int_part = 0;
216 long int_one = 1 << precision;
217 long frac_part = 0;
218 long frac_count = 0;
219 long frac_max = ((precision * 4) + 12) / 13;
220 long frac_max_int = 1;
221 long sign = 1;
222 bool point = false;
224 while ((*s != '\0') && isspace(*s))
226 s++;
229 if (*s == '-')
231 sign = -1;
232 s++;
234 else if (*s == '+')
236 s++;
239 while (*s != '\0')
241 if (*s == '.')
243 if (point)
245 break;
248 point = true;
250 else if (isdigit(*s))
252 if (point)
254 if (frac_count < frac_max)
256 frac_part = frac_part * 10 + (*s - '0');
257 frac_count++;
258 frac_max_int *= 10;
261 else
263 int_part = int_part * 10 + (*s - '0');
266 else
268 break;
271 s++;
274 while (frac_count < frac_max)
276 frac_part *= 10;
277 frac_count++;
278 frac_max_int *= 10;
281 return sign * ((int_part * int_one)
282 + (((int64_t) frac_part * int_one) / frac_max_int));
285 static long convert_gain(long gain)
287 if (gain != 0)
289 /* Don't allow unreasonably low or high gain changes.
290 * Our math code can't handle it properly anyway. :)
292 if (gain < (-23 * FP_ONE))
294 gain = -23 * FP_ONE;
297 if (gain > (17 * FP_ONE))
299 gain = 17 * FP_ONE;
302 gain = fp_exp10(gain / 20) << (24 - FP_BITS);
305 return gain;
308 long get_replaygain_int(long int_gain)
310 long gain = 0;
312 if (int_gain)
314 gain = convert_gain(int_gain * FP_ONE / 100);
317 return gain;
320 long get_replaygain(const char* str)
322 long gain = 0;
324 if (str)
326 gain = fp_atof(str, FP_BITS);
327 gain = convert_gain(gain);
330 return gain;
333 long get_replaypeak(const char* str)
335 long peak = 0;
337 if (str)
339 peak = fp_atof(str, 24);
342 return peak;
345 /* Check for a ReplayGain tag conforming to the "VorbisGain standard". If
346 * found, set the mp3entry accordingly. buffer is where to store the text
347 * contents of the gain tags; up to length bytes (including end nil) can be
348 * written. Returns number of bytes written to the tag text buffer, or zero
349 * if no ReplayGain tag was found (or nothing was copied to the buffer for
350 * other reasons).
352 long parse_replaygain(const char* key, const char* value,
353 struct mp3entry* entry, char* buffer, int length)
355 char **p = NULL;
357 if ((strcasecmp(key, "replaygain_track_gain") == 0)
358 || ((strcasecmp(key, "rg_radio") == 0) && !entry->track_gain))
360 entry->track_gain = get_replaygain(value);
361 p = &(entry->track_gain_string);
363 else if ((strcasecmp(key, "replaygain_album_gain") == 0)
364 || ((strcasecmp(key, "rg_audiophile") == 0) && !entry->album_gain))
366 entry->album_gain = get_replaygain(value);
367 p = &(entry->album_gain_string);
369 else if ((strcasecmp(key, "replaygain_track_peak") == 0)
370 || ((strcasecmp(key, "rg_peak") == 0) && !entry->track_peak))
372 entry->track_peak = get_replaypeak(value);
374 else if (strcasecmp(key, "replaygain_album_peak") == 0)
376 entry->album_peak = get_replaypeak(value);
379 if (p)
381 int len = strlen(value);
383 len = MIN(len, length - 1);
385 /* A few characters just isn't interesting... */
386 if (len > 1)
388 strncpy(buffer, value, len);
389 buffer[len] = 0;
390 *p = buffer;
391 return len + 1;
395 return 0;