Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / replaygain.c
blobb7cde7f005e78d64b14ea308c1bf14fa1bcc9cbe
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 /* Type of channel for RVA2 frame. There are more than this defined in the spec
32 but we don't use them. */
33 #define MASTER_CHANNEL 1
35 /* The fixed point math routines (with the exception of fp_atof) are based
36 * on oMathFP by Dan Carter (http://orbisstudios.com).
39 /* 12 bits of precision gives fairly accurate result, but still allows a
40 * compact implementation. The math code supports up to 13...
43 #define FP_BITS (12)
44 #define FP_MASK ((1 << FP_BITS) - 1)
45 #define FP_ONE (1 << FP_BITS)
46 #define FP_TWO (2 << FP_BITS)
47 #define FP_HALF (1 << (FP_BITS - 1))
48 #define FP_LN2 ( 45426 >> (16 - FP_BITS))
49 #define FP_LN2_INV ( 94548 >> (16 - FP_BITS))
50 #define FP_EXP_ZERO ( 10922 >> (16 - FP_BITS))
51 #define FP_EXP_ONE ( -182 >> (16 - FP_BITS))
52 #define FP_EXP_TWO ( 4 >> (16 - FP_BITS))
53 #define FP_INF (0x7fffffff)
54 #define FP_LN10 (150902 >> (16 - FP_BITS))
56 #define FP_MAX_DIGITS (4)
57 #define FP_MAX_DIGITS_INT (10000)
59 #define FP_FAST_MUL_DIV
61 #ifdef FP_FAST_MUL_DIV
63 /* These macros can easily overflow, but they are good enough for our uses,
64 * and saves some code.
66 #define fp_mul(x, y) (((x) * (y)) >> FP_BITS)
67 #define fp_div(x, y) (((x) << FP_BITS) / (y))
69 #else
71 static long fp_mul(long x, long y)
73 long x_neg = 0;
74 long y_neg = 0;
75 long rc;
77 if ((x == 0) || (y == 0))
79 return 0;
82 if (x < 0)
84 x_neg = 1;
85 x = -x;
88 if (y < 0)
90 y_neg = 1;
91 y = -y;
94 rc = (((x >> FP_BITS) * (y >> FP_BITS)) << FP_BITS)
95 + (((x & FP_MASK) * (y & FP_MASK)) >> FP_BITS)
96 + ((x & FP_MASK) * (y >> FP_BITS))
97 + ((x >> FP_BITS) * (y & FP_MASK));
99 if ((x_neg ^ y_neg) == 1)
101 rc = -rc;
104 return rc;
107 static long fp_div(long x, long y)
109 long x_neg = 0;
110 long y_neg = 0;
111 long shifty;
112 long rc;
113 int msb = 0;
114 int lsb = 0;
116 if (x == 0)
118 return 0;
121 if (y == 0)
123 return (x < 0) ? -FP_INF : FP_INF;
126 if (x < 0)
128 x_neg = 1;
129 x = -x;
132 if (y < 0)
134 y_neg = 1;
135 y = -y;
138 while ((x & (1 << (30 - msb))) == 0)
140 msb++;
143 while ((y & (1 << lsb)) == 0)
145 lsb++;
148 shifty = FP_BITS - (msb + lsb);
149 rc = ((x << msb) / (y >> lsb));
151 if (shifty > 0)
153 rc <<= shifty;
155 else
157 rc >>= -shifty;
160 if ((x_neg ^ y_neg) == 1)
162 rc = -rc;
165 return rc;
168 #endif /* FP_FAST_MUL_DIV */
170 static long fp_exp(long x)
172 long k;
173 long z;
174 long R;
175 long xp;
177 if (x == 0)
179 return FP_ONE;
182 k = (fp_mul(abs(x), FP_LN2_INV) + FP_HALF) & ~FP_MASK;
184 if (x < 0)
186 k = -k;
189 x -= fp_mul(k, FP_LN2);
190 z = fp_mul(x, x);
191 R = FP_TWO + fp_mul(z, FP_EXP_ZERO + fp_mul(z, FP_EXP_ONE
192 + fp_mul(z, FP_EXP_TWO)));
193 xp = FP_ONE + fp_div(fp_mul(FP_TWO, x), R - x);
195 if (k < 0)
197 k = FP_ONE >> (-k >> FP_BITS);
199 else
201 k = FP_ONE << (k >> FP_BITS);
204 return fp_mul(k, xp);
207 static long fp_exp10(long x)
209 if (x == 0)
211 return FP_ONE;
214 return fp_exp(fp_mul(FP_LN10, x));
217 static long fp_atof(const char* s, int precision)
219 long int_part = 0;
220 long int_one = 1 << precision;
221 long frac_part = 0;
222 long frac_count = 0;
223 long frac_max = ((precision * 4) + 12) / 13;
224 long frac_max_int = 1;
225 long sign = 1;
226 bool point = false;
228 while ((*s != '\0') && isspace(*s))
230 s++;
233 if (*s == '-')
235 sign = -1;
236 s++;
238 else if (*s == '+')
240 s++;
243 while (*s != '\0')
245 if (*s == '.')
247 if (point)
249 break;
252 point = true;
254 else if (isdigit(*s))
256 if (point)
258 if (frac_count < frac_max)
260 frac_part = frac_part * 10 + (*s - '0');
261 frac_count++;
262 frac_max_int *= 10;
265 else
267 int_part = int_part * 10 + (*s - '0');
270 else
272 break;
275 s++;
278 while (frac_count < frac_max)
280 frac_part *= 10;
281 frac_count++;
282 frac_max_int *= 10;
285 return sign * ((int_part * int_one)
286 + (((int64_t) frac_part * int_one) / frac_max_int));
289 static long convert_gain(long gain)
291 if (gain != 0)
293 /* Don't allow unreasonably low or high gain changes.
294 * Our math code can't handle it properly anyway. :)
296 if (gain < (-48 * FP_ONE))
298 gain = -48 * FP_ONE;
301 if (gain > (17 * FP_ONE))
303 gain = 17 * FP_ONE;
306 gain = fp_exp10(gain / 20) << (24 - FP_BITS);
309 return gain;
312 long get_replaygain_int(long int_gain)
314 long gain = 0;
316 if (int_gain)
318 gain = convert_gain(int_gain * FP_ONE / 100);
321 return gain;
324 long get_replaygain(const char* str)
326 long gain = 0;
328 if (str)
330 gain = fp_atof(str, FP_BITS);
331 gain = convert_gain(gain);
334 return gain;
337 long get_replaypeak(const char* str)
339 long peak = 0;
341 if (str)
343 peak = fp_atof(str, 24);
346 return peak;
349 /* Check for a ReplayGain tag conforming to the "VorbisGain standard". If
350 * found, set the mp3entry accordingly. buffer is where to store the text
351 * contents of the gain tags; up to length bytes (including end nil) can be
352 * written. Returns number of bytes written to the tag text buffer, or zero
353 * if no ReplayGain tag was found (or nothing was copied to the buffer for
354 * other reasons).
356 long parse_replaygain(const char* key, const char* value,
357 struct mp3entry* entry, char* buffer, int length)
359 char **p = NULL;
361 if (((strcasecmp(key, "replaygain_track_gain") == 0)
362 || (strcasecmp(key, "rg_radio") == 0)) && !entry->track_gain)
364 entry->track_gain = get_replaygain(value);
365 p = &(entry->track_gain_string);
367 else if (((strcasecmp(key, "replaygain_album_gain") == 0)
368 || (strcasecmp(key, "rg_audiophile") == 0)) && !entry->album_gain)
370 entry->album_gain = get_replaygain(value);
371 p = &(entry->album_gain_string);
373 else if (((strcasecmp(key, "replaygain_track_peak") == 0)
374 || (strcasecmp(key, "rg_peak") == 0)) && !entry->track_peak)
376 entry->track_peak = get_replaypeak(value);
378 else if ((strcasecmp(key, "replaygain_album_peak") == 0)
379 && !entry->album_peak)
381 entry->album_peak = get_replaypeak(value);
384 if (p)
386 int len = strlen(value);
388 len = MIN(len, length - 1);
390 /* A few characters just isn't interesting... */
391 if (len > 1)
393 strncpy(buffer, value, len);
394 buffer[len] = 0;
395 *p = buffer;
396 return len + 1;
400 return 0;
403 static long get_rva_values(const char *frame, long *gain, long *peak,
404 char **string, char *buffer, int length)
406 long value, len;
407 int negative = 0;
408 char tmpbuf[10];
409 int peakbits, peakbytes, shift;
410 unsigned long peakvalue = 0;
412 value = 256 * ((unsigned char)*frame) + ((unsigned char)*(frame + 1));
413 if (value & 0x8000)
415 value = -(value | ~0xFFFF);
416 negative = 1;
419 len = snprintf(tmpbuf, sizeof(tmpbuf), "%s%d.%02d dB", negative ? "-" : "",
420 value / 512, (value & 0x1FF) * 195 / 1000);
422 *gain = get_replaygain(tmpbuf);
424 len = MIN(len, length - 1);
425 if (len > 1)
427 strncpy(buffer, tmpbuf, len);
428 buffer[len] = 0;
429 *string = buffer;
432 frame += 2;
433 peakbits = *(unsigned char *)frame++;
434 peakbytes = MIN(4, (peakbits + 7) >> 3);
435 shift = ((8 - (peakbits & 7)) & 7) + (4 - peakbytes) * 8;
437 for (; peakbytes; peakbytes--)
439 peakvalue <<= 8;
440 peakvalue += (unsigned long)*frame++;
443 peakvalue <<= shift;
445 if (peakbits > 32)
446 peakvalue += (unsigned long)*frame >> (8 - shift);
448 snprintf(tmpbuf, sizeof(tmpbuf), "%d.%06d", peakvalue >> 31,
449 (peakvalue & ~(1 << 31)) / 2147);
451 *peak = get_replaypeak(tmpbuf);
453 return len + 1;
456 long parse_replaygain_rva(const char* key, const char* value,
457 struct mp3entry* entry, char* buffer, int length)
459 /* Values will be overwritten if they already exist. This gives priority to
460 replaygain in RVA2 fields over TXXX fields for ID3v2.4. */
461 if ((strcasecmp(key, "track") == 0) && *value == MASTER_CHANNEL)
463 return get_rva_values(value + 1, &(entry->track_gain), &(entry->track_peak),
464 &(entry->track_gain_string), buffer, length);
466 else if ((strcasecmp(key, "album") == 0) && *value == MASTER_CHANNEL)
468 return get_rva_values(value + 1, &(entry->album_gain), &(entry->album_peak),
469 &(entry->album_gain_string), buffer, length);
472 return 0;