summaryrefslogtreecommitdiff
path: root/apps/replaygain.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/replaygain.c')
-rw-r--r--apps/replaygain.c130
1 files changed, 33 insertions, 97 deletions
diff --git a/apps/replaygain.c b/apps/replaygain.c
index 81f1a45ad7..9f0dda7a0b 100644
--- a/apps/replaygain.c
+++ b/apps/replaygain.c
@@ -36,6 +36,13 @@
36#define FP_BITS (12) 36#define FP_BITS (12)
37#define FP_ONE (1 << FP_BITS) 37#define FP_ONE (1 << FP_BITS)
38 38
39void replaygain_itoa(char* buffer, int length, long int_gain)
40{
41 /* int_gain uses Q19.12 format. */
42 int one = abs(int_gain) >> FP_BITS;
43 int cent = ((abs(int_gain) & 0x0fff) * 100 + (FP_ONE/2)) >> FP_BITS;
44 snprintf(buffer, length, "%d.%02d dB", (int_gain<0) ? -one : one, cent);
45}
39 46
40static long fp_atof(const char* s, int precision) 47static long fp_atof(const char* s, int precision)
41{ 48{
@@ -109,42 +116,25 @@ static long fp_atof(const char* s, int precision)
109 + (((int64_t) frac_part * int_one) / frac_max_int)); 116 + (((int64_t) frac_part * int_one) / frac_max_int));
110} 117}
111 118
112static long convert_gain(long gain) 119long convert_gain(long gain)
113{ 120{
114 /* Don't allow unreasonably low or high gain changes. 121 /* Don't allow unreasonably low or high gain changes.
115 * Our math code can't handle it properly anyway. :) 122 * Our math code can't handle it properly anyway. :)
116 */ 123 */
117 if (gain < (-48 * FP_ONE)) 124 gain = MAX(gain,-48 * FP_ONE);
118 { 125 gain = MIN(gain, 17 * FP_ONE);
119 gain = -48 * FP_ONE;
120 }
121
122 if (gain > (17 * FP_ONE))
123 {
124 gain = 17 * FP_ONE;
125 }
126
127 gain = fp_factor(gain, FP_BITS) << (24 - FP_BITS);
128 126
129 return gain; 127 return fp_factor(gain, FP_BITS) << (24 - FP_BITS);
130} 128}
131 129
132/* Get the sample scale factor in Q7.24 format from a gain value. Returns 0 130/* Get the sample scale factor in Q19.12 format from a gain value. Returns 0
133 * for no gain. 131 * for no gain.
134 * 132 *
135 * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored. 133 * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored.
136 */ 134 */
137static long get_replaygain(const char* str) 135static long get_replaygain(const char* str)
138{ 136{
139 long gain = 0; 137 return fp_atof(str, FP_BITS);
140
141 if (str)
142 {
143 gain = fp_atof(str, FP_BITS);
144 gain = convert_gain(gain);
145 }
146
147 return gain;
148} 138}
149 139
150/* Get the peak volume in Q7.24 format. 140/* Get the peak volume in Q7.24 format.
@@ -153,14 +143,7 @@ static long get_replaygain(const char* str)
153 */ 143 */
154static long get_replaypeak(const char* str) 144static long get_replaypeak(const char* str)
155{ 145{
156 long peak = 0; 146 return fp_atof(str, 24);
157
158 if (str)
159 {
160 peak = fp_atof(str, 24);
161 }
162
163 return peak;
164} 147}
165 148
166/* Get a sample scale factor in Q7.24 format from a gain value. 149/* Get a sample scale factor in Q7.24 format from a gain value.
@@ -174,107 +157,60 @@ long get_replaygain_int(long int_gain)
174 157
175/* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a 158/* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
176 * valid tag is found, update mp3entry struct accordingly. Existing values 159 * valid tag is found, update mp3entry struct accordingly. Existing values
177 * are not overwritten. Returns number of bytes written to buffer. 160 * are not overwritten.
178 * 161 *
179 * key Name of the tag. 162 * key Name of the tag.
180 * value Value of the tag. 163 * value Value of the tag.
181 * entry mp3entry struct to update. 164 * entry mp3entry struct to update.
182 * buffer Where to store the text for gain values (for later display).
183 * length Bytes left in buffer.
184 */ 165 */
185long parse_replaygain(const char* key, const char* value, 166void parse_replaygain(const char* key, const char* value,
186 struct mp3entry* entry, char* buffer, int length) 167 struct mp3entry* entry)
187{ 168{
188 char **p = NULL; 169 if (((strcasecmp(key, "replaygain_track_gain") == 0) ||
189 170 (strcasecmp(key, "rg_radio") == 0)) &&
190 if (((strcasecmp(key, "replaygain_track_gain") == 0) 171 !entry->track_gain)
191 || (strcasecmp(key, "rg_radio") == 0)) && !entry->track_gain)
192 { 172 {
193 entry->track_gain = get_replaygain(value); 173 entry->track_gain = get_replaygain(value);
194 p = &(entry->track_gain_string);
195 } 174 }
196 else if (((strcasecmp(key, "replaygain_album_gain") == 0) 175 else if (((strcasecmp(key, "replaygain_album_gain") == 0) ||
197 || (strcasecmp(key, "rg_audiophile") == 0)) && !entry->album_gain) 176 (strcasecmp(key, "rg_audiophile") == 0)) &&
177 !entry->album_gain)
198 { 178 {
199 entry->album_gain = get_replaygain(value); 179 entry->album_gain = get_replaygain(value);
200 p = &(entry->album_gain_string);
201 } 180 }
202 else if (((strcasecmp(key, "replaygain_track_peak") == 0) 181 else if (((strcasecmp(key, "replaygain_track_peak") == 0) ||
203 || (strcasecmp(key, "rg_peak") == 0)) && !entry->track_peak) 182 (strcasecmp(key, "rg_peak") == 0)) &&
183 !entry->track_peak)
204 { 184 {
205 entry->track_peak = get_replaypeak(value); 185 entry->track_peak = get_replaypeak(value);
206 } 186 }
207 else if ((strcasecmp(key, "replaygain_album_peak") == 0) 187 else if ((strcasecmp(key, "replaygain_album_peak") == 0) &&
208 && !entry->album_peak) 188 !entry->album_peak)
209 { 189 {
210 entry->album_peak = get_replaypeak(value); 190 entry->album_peak = get_replaypeak(value);
211 } 191 }
212
213 if (p)
214 {
215 int len = strlen(value);
216
217 len = MIN(len, length - 1);
218
219 /* A few characters just isn't interesting... */
220 if (len > 1)
221 {
222 strlcpy(buffer, value, len + 1);
223 *p = buffer;
224 return len + 1;
225 }
226 }
227
228 return 0;
229} 192}
230 193
231/* Set ReplayGain values from integers. Existing values are not overwritten. 194/* Set ReplayGain values from integers. Existing values are not overwritten.
232 * Returns number of bytes written to buffer.
233 * 195 *
234 * album If true, set album values, otherwise set track values. 196 * album If true, set album values, otherwise set track values.
235 * gain Gain value in dB, multiplied by 512. 0 for no gain. 197 * 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 198 * peak Peak volume in Q7.24 format, where 1.0 is full scale. 0 for no
237 * peak volume. 199 * peak volume.
238 * buffer Where to store the text for gain values (for later display).
239 * length Bytes left in buffer.
240 */ 200 */
241long parse_replaygain_int(bool album, long gain, long peak, 201void parse_replaygain_int(bool album, long gain, long peak,
242 struct mp3entry* entry, char* buffer, int length) 202 struct mp3entry* entry)
243{ 203{
244 long len = 0; 204 gain = gain * FP_ONE / 512;
245
246 if (buffer != NULL)
247 {
248 len = snprintf(buffer, length, "%ld.%02d dB", gain / 512,
249 ((abs(gain) & 0x01ff) * 100 + 256) / 512);
250 len++;
251 }
252
253 if (gain != 0)
254 {
255 gain = convert_gain(gain * FP_ONE / 512);
256 }
257 205
258 if (album) 206 if (album)
259 { 207 {
260 entry->album_gain = gain; 208 entry->album_gain = gain;
261 entry->album_gain_string = buffer; 209 entry->album_peak = peak;
262
263 if (peak)
264 {
265 entry->album_peak = peak;
266 }
267 } 210 }
268 else 211 else
269 { 212 {
270 entry->track_gain = gain; 213 entry->track_gain = gain;
271 entry->track_gain_string = buffer; 214 entry->track_peak = peak;
272
273 if (peak)
274 {
275 entry->track_peak = peak;
276 }
277 } 215 }
278
279 return len;
280} 216}