1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Magnus Holmgren
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 #include "strcasecmp.h"
33 #include "replaygain.h"
34 #include "fixedpoint.h"
37 #define FP_ONE (1 << FP_BITS)
40 static long fp_atof(const char* s
, int precision
)
43 long int_one
= BIT_N(precision
);
46 long frac_max
= ((precision
* 4) + 12) / 13;
47 long frac_max_int
= 1;
51 while ((*s
!= '\0') && isspace(*s
))
81 if (frac_count
< frac_max
)
83 frac_part
= frac_part
* 10 + (*s
- '0');
90 int_part
= int_part
* 10 + (*s
- '0');
101 while (frac_count
< frac_max
)
108 return sign
* ((int_part
* int_one
)
109 + (((int64_t) frac_part
* int_one
) / frac_max_int
));
112 static long convert_gain(long gain
)
114 /* Don't allow unreasonably low or high gain changes.
115 * Our math code can't handle it properly anyway. :)
117 if (gain
< (-48 * FP_ONE
))
122 if (gain
> (17 * FP_ONE
))
127 gain
= fp_factor(gain
, FP_BITS
) << (24 - FP_BITS
);
132 /* Get the sample scale factor in Q7.24 format from a gain value. Returns 0
135 * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored.
137 static long get_replaygain(const char* str
)
143 gain
= fp_atof(str
, FP_BITS
);
144 gain
= convert_gain(gain
);
150 /* Get the peak volume in Q7.24 format.
152 * str Peak volume. Full scale is specified as "1.0". Returns 0 for no peak.
154 static long get_replaypeak(const char* str
)
160 peak
= fp_atof(str
, 24);
166 /* Get a sample scale factor in Q7.24 format from a gain value.
168 * int_gain Gain in dB, multiplied by 100.
170 long get_replaygain_int(long int_gain
)
172 return convert_gain(int_gain
* FP_ONE
/ 100);
175 /* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
176 * valid tag is found, update mp3entry struct accordingly. Existing values
177 * are not overwritten. Returns number of bytes written to buffer.
179 * key Name of the tag.
180 * value Value of the tag.
181 * entry mp3entry struct to update.
182 * buffer Where to store the text for gain values (for later display).
183 * length Bytes left in buffer.
185 long parse_replaygain(const char* key
, const char* value
,
186 struct mp3entry
* entry
, char* buffer
, int length
)
190 if (((strcasecmp(key
, "replaygain_track_gain") == 0)
191 || (strcasecmp(key
, "rg_radio") == 0)) && !entry
->track_gain
)
193 entry
->track_gain
= get_replaygain(value
);
194 p
= &(entry
->track_gain_string
);
196 else if (((strcasecmp(key
, "replaygain_album_gain") == 0)
197 || (strcasecmp(key
, "rg_audiophile") == 0)) && !entry
->album_gain
)
199 entry
->album_gain
= get_replaygain(value
);
200 p
= &(entry
->album_gain_string
);
202 else if (((strcasecmp(key
, "replaygain_track_peak") == 0)
203 || (strcasecmp(key
, "rg_peak") == 0)) && !entry
->track_peak
)
205 entry
->track_peak
= get_replaypeak(value
);
207 else if ((strcasecmp(key
, "replaygain_album_peak") == 0)
208 && !entry
->album_peak
)
210 entry
->album_peak
= get_replaypeak(value
);
215 int len
= strlen(value
);
217 len
= MIN(len
, length
- 1);
219 /* A few characters just isn't interesting... */
222 strlcpy(buffer
, value
, len
+ 1);
231 /* Set ReplayGain values from integers. Existing values are not overwritten.
232 * Returns number of bytes written to buffer.
234 * album If true, set album values, otherwise set track values.
235 * gain Gain value in dB, multiplied by 512. 0 for no gain.
236 * peak Peak volume in Q7.24 format, where 1.0 is full scale. 0 for no
238 * buffer Where to store the text for gain values (for later display).
239 * length Bytes left in buffer.
241 long parse_replaygain_int(bool album
, long gain
, long peak
,
242 struct mp3entry
* entry
, char* buffer
, int length
)
248 len
= snprintf(buffer
, length
, "%ld.%02d dB", gain
/ 512,
249 ((abs(gain
) & 0x01ff) * 100 + 256) / 512);
255 gain
= convert_gain(gain
* FP_ONE
/ 512);
260 entry
->album_gain
= gain
;
261 entry
->album_gain_string
= buffer
;
265 entry
->album_peak
= peak
;
270 entry
->track_gain
= gain
;
271 entry
->track_gain_string
= buffer
;
275 entry
->track_peak
= peak
;