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 ****************************************************************************/
32 #include "replaygain.h"
33 #include "fixedpoint.h"
36 #define FP_ONE (1 << FP_BITS)
39 static long fp_atof(const char* s
, int precision
)
42 long int_one
= BIT_N(precision
);
45 long frac_max
= ((precision
* 4) + 12) / 13;
46 long frac_max_int
= 1;
50 while ((*s
!= '\0') && isspace(*s
))
80 if (frac_count
< frac_max
)
82 frac_part
= frac_part
* 10 + (*s
- '0');
89 int_part
= int_part
* 10 + (*s
- '0');
100 while (frac_count
< frac_max
)
107 return sign
* ((int_part
* int_one
)
108 + (((int64_t) frac_part
* int_one
) / frac_max_int
));
111 static long convert_gain(long gain
)
113 /* Don't allow unreasonably low or high gain changes.
114 * Our math code can't handle it properly anyway. :)
116 if (gain
< (-48 * FP_ONE
))
121 if (gain
> (17 * FP_ONE
))
126 gain
= fp_factor(gain
, FP_BITS
) << (24 - FP_BITS
);
131 /* Get the sample scale factor in Q7.24 format from a gain value. Returns 0
134 * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored.
136 static long get_replaygain(const char* str
)
142 gain
= fp_atof(str
, FP_BITS
);
143 gain
= convert_gain(gain
);
149 /* Get the peak volume in Q7.24 format.
151 * str Peak volume. Full scale is specified as "1.0". Returns 0 for no peak.
153 static long get_replaypeak(const char* str
)
159 peak
= fp_atof(str
, 24);
165 /* Get a sample scale factor in Q7.24 format from a gain value.
167 * int_gain Gain in dB, multiplied by 100.
169 long get_replaygain_int(long int_gain
)
171 return convert_gain(int_gain
* FP_ONE
/ 100);
174 /* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
175 * valid tag is found, update mp3entry struct accordingly. Existing values
176 * are not overwritten. Returns number of bytes written to buffer.
178 * key Name of the tag.
179 * value Value of the tag.
180 * entry mp3entry struct to update.
181 * buffer Where to store the text for gain values (for later display).
182 * length Bytes left in buffer.
184 long parse_replaygain(const char* key
, const char* value
,
185 struct mp3entry
* entry
, char* buffer
, int length
)
189 if (((strcasecmp(key
, "replaygain_track_gain") == 0)
190 || (strcasecmp(key
, "rg_radio") == 0)) && !entry
->track_gain
)
192 entry
->track_gain
= get_replaygain(value
);
193 p
= &(entry
->track_gain_string
);
195 else if (((strcasecmp(key
, "replaygain_album_gain") == 0)
196 || (strcasecmp(key
, "rg_audiophile") == 0)) && !entry
->album_gain
)
198 entry
->album_gain
= get_replaygain(value
);
199 p
= &(entry
->album_gain_string
);
201 else if (((strcasecmp(key
, "replaygain_track_peak") == 0)
202 || (strcasecmp(key
, "rg_peak") == 0)) && !entry
->track_peak
)
204 entry
->track_peak
= get_replaypeak(value
);
206 else if ((strcasecmp(key
, "replaygain_album_peak") == 0)
207 && !entry
->album_peak
)
209 entry
->album_peak
= get_replaypeak(value
);
214 int len
= strlen(value
);
216 len
= MIN(len
, length
- 1);
218 /* A few characters just isn't interesting... */
221 strlcpy(buffer
, value
, len
+ 1);
230 /* Set ReplayGain values from integers. Existing values are not overwritten.
231 * Returns number of bytes written to buffer.
233 * album If true, set album values, otherwise set track values.
234 * gain Gain value in dB, multiplied by 512. 0 for no gain.
235 * peak Peak volume in Q7.24 format, where 1.0 is full scale. 0 for no
237 * buffer Where to store the text for gain values (for later display).
238 * length Bytes left in buffer.
240 long parse_replaygain_int(bool album
, long gain
, long peak
,
241 struct mp3entry
* entry
, char* buffer
, int length
)
247 len
= snprintf(buffer
, length
, "%d.%02d dB", gain
/ 512,
248 ((abs(gain
) & 0x01ff) * 100 + 256) / 512);
254 gain
= convert_gain(gain
* FP_ONE
/ 512);
259 entry
->album_gain
= gain
;
260 entry
->album_gain_string
= buffer
;
264 entry
->album_peak
= peak
;
269 entry
->track_gain
= gain
;
270 entry
->track_gain_string
= buffer
;
274 entry
->track_peak
= peak
;