diff options
Diffstat (limited to 'apps/replaygain.c')
-rw-r--r-- | apps/replaygain.c | 130 |
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 | ||
39 | void 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 | ||
40 | static long fp_atof(const char* s, int precision) | 47 | static 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 | ||
112 | static long convert_gain(long gain) | 119 | long 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 | */ |
137 | static long get_replaygain(const char* str) | 135 | static 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 | */ |
154 | static long get_replaypeak(const char* str) | 144 | static 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 | */ |
185 | long parse_replaygain(const char* key, const char* value, | 166 | void 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 | */ |
241 | long parse_replaygain_int(bool album, long gain, long peak, | 201 | void 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 | } |