From 46555f4e7b44631f27ad9e5a428f418825fb6f34 Mon Sep 17 00:00:00 2001 From: Buschel Date: Thu, 24 Feb 2011 19:10:59 +0000 Subject: [PATCH] FS#11964. Rework replaygain handling to save metadata buffer and binsize. Remove string representation of replaygain and use a dedicated ftoa implementation for WPS/screen info. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29388 a1c6a512-1295-4272-9138-f99709370657 --- apps/dsp.c | 8 +-- apps/gui/skin_engine/skin_tokens.c | 9 +-- apps/metadata.c | 6 -- apps/metadata.h | 7 +- apps/metadata/asf.c | 12 +--- apps/metadata/id3tags.c | 18 ++--- apps/metadata/metadata_common.c | 2 +- apps/metadata/mp4.c | 8 +-- apps/metadata/mpc.c | 6 +- apps/replaygain.c | 130 ++++++++++--------------------------- apps/replaygain.h | 10 +-- apps/screens.c | 7 +- 12 files changed, 65 insertions(+), 158 deletions(-) diff --git a/apps/dsp.c b/apps/dsp.c index 3cff1918d..c462fc37a 100644 --- a/apps/dsp.c +++ b/apps/dsp.c @@ -1475,22 +1475,22 @@ intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value) case DSP_SET_TRACK_GAIN: if (dsp == &AUDIO_DSP) - dsp_set_gain_var(&track_gain, value); + dsp_set_gain_var(&track_gain, convert_gain(value)); break; case DSP_SET_ALBUM_GAIN: if (dsp == &AUDIO_DSP) - dsp_set_gain_var(&album_gain, value); + dsp_set_gain_var(&album_gain, convert_gain(value)); break; case DSP_SET_TRACK_PEAK: if (dsp == &AUDIO_DSP) - dsp_set_gain_var(&track_peak, value); + dsp_set_gain_var(&track_peak, convert_gain(value)); break; case DSP_SET_ALBUM_PEAK: if (dsp == &AUDIO_DSP) - dsp_set_gain_var(&album_peak, value); + dsp_set_gain_var(&album_peak, convert_gain(value)); break; default: diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index f455999b2..1fbe3d714 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -35,6 +35,7 @@ #include "sound.h" #include "debug.h" #include "cuesheet.h" +#include "replaygain.h" #ifdef HAVE_LCD_CHARCELLS #include "hwcompat.h" #endif @@ -1305,8 +1306,8 @@ const char *get_token_value(struct gui_wps *gwps, { int type; if (LIKELY(id3)) - type = get_replaygain_mode(id3->track_gain_string != NULL, - id3->album_gain_string != NULL); + type = get_replaygain_mode(id3->track_gain != 0, + id3->album_gain != 0); else type = -1; @@ -1331,11 +1332,11 @@ const char *get_token_value(struct gui_wps *gwps, /* due to above, coming here with !id3 shouldn't be possible */ case 2: case 4: - strlcpy(buf, id3->track_gain_string, buf_size); + replaygain_itoa(buf, buf_size, id3->track_gain); break; case 3: case 5: - strlcpy(buf, id3->album_gain_string, buf_size); + replaygain_itoa(buf, buf_size, id3->album_gain); break; } return buf; diff --git a/apps/metadata.c b/apps/metadata.c index 12bea286d..4e4ffb6ad 100644 --- a/apps/metadata.c +++ b/apps/metadata.c @@ -411,12 +411,6 @@ void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig) entry->albumartist += offset; if (entry->grouping) entry->grouping += offset; -#if CONFIG_CODEC == SWCODEC - if (entry->track_gain_string) - entry->track_gain_string += offset; - if (entry->album_gain_string) - entry->album_gain_string += offset; -#endif if (entry->mb_track_id) entry->mb_track_id += offset; } diff --git a/apps/metadata.h b/apps/metadata.h index 8d2088283..5662c2e84 100644 --- a/apps/metadata.h +++ b/apps/metadata.h @@ -283,13 +283,10 @@ struct mp3entry { #endif /* replaygain support */ - #if CONFIG_CODEC == SWCODEC - char* track_gain_string; - char* album_gain_string; - long track_gain; /* 7.24 signed fixed point. 0 for no gain. */ + long track_gain; /* s19.12 signed fixed point. 0 for no gain. */ long album_gain; - long track_peak; /* 7.24 signed fixed point. 0 for no peak. */ + long track_peak; /* s19.12 signed fixed point. 0 for no peak. */ long album_peak; #endif diff --git a/apps/metadata/asf.c b/apps/metadata/asf.c index c445e485a..56d5c87f9 100644 --- a/apps/metadata/asf.c +++ b/apps/metadata/asf.c @@ -456,18 +456,8 @@ static int asf_parse_header(int fd, struct mp3entry* id3, lseek(fd, length, SEEK_CUR); } } else if (!strncmp("replaygain_", utf8buf, 11)) { - char* value = id3buf; - int buf_len = id3buf_remaining; - int len; asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); - len = parse_replaygain(utf8buf, value, id3, - value, buf_len); - - if (len == 0) { - /* Don't need to keep the value */ - id3buf = value; - id3buf_remaining = buf_len; - } + parse_replaygain(utf8buf, id3buf, id3); } else if (!strcmp("MusicBrainz/Track Id", utf8buf)) { id3->mb_track_id = id3buf; asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining); diff --git a/apps/metadata/id3tags.c b/apps/metadata/id3tags.c index 3cbebc12e..c1d9cb202 100644 --- a/apps/metadata/id3tags.c +++ b/apps/metadata/id3tags.c @@ -370,14 +370,8 @@ static int parseuser( struct mp3entry* entry, char* tag, int bufferpos ) entry->albumartist = tag; #if CONFIG_CODEC == SWCODEC } else { - /* Calculate residual buffer size in bytes which can be used by - * parse_replaygain() to save the string representation of - * replaygain data.*/ - length = sizeof(entry->id3v2buf) - (tag - entry->id3v2buf); - - /* Call parse_replaygain(), returns length in bytes used by the - * string representation of replaygain data. */ - length = parse_replaygain(tag, value, entry, tag, length); + /* Call parse_replaygain(). */ + parse_replaygain(tag, value, entry); #endif } } @@ -387,12 +381,11 @@ static int parseuser( struct mp3entry* entry, char* tag, int bufferpos ) #if CONFIG_CODEC == SWCODEC /* parse RVA2 binary data and convert to replaygain information. */ -static int parserva2( struct mp3entry* entry, char* tag, int bufferpos ) +static int parserva2( struct mp3entry* entry, char* tag, int bufferpos) { int desc_len = strlen(tag); int start_pos = tag - entry->id3v2buf; int end_pos = start_pos + desc_len + 5; - int value_len = 0; unsigned char* value = tag + desc_len + 1; /* Only parse RVA2 replaygain tags if tag version == 2.4 and channel @@ -447,11 +440,10 @@ static int parserva2( struct mp3entry* entry, char* tag, int bufferpos ) } } - value_len = parse_replaygain_int(album, gain, peak * 2, entry, - tag, sizeof(entry->id3v2buf) - start_pos); + parse_replaygain_int(album, gain, peak * 2, entry); } - return start_pos + value_len; + return start_pos; } #endif diff --git a/apps/metadata/metadata_common.c b/apps/metadata/metadata_common.c index 341d279b5..ae6b24561 100644 --- a/apps/metadata/metadata_common.c +++ b/apps/metadata/metadata_common.c @@ -333,7 +333,7 @@ long parse_tag(const char* name, char* value, struct mp3entry* id3, } else { - len = parse_replaygain(name, value, id3, buf, buf_remaining); + parse_replaygain(name, value, id3); p = NULL; } diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c index 6130135ba..a431231e1 100644 --- a/apps/metadata/mp4.c +++ b/apps/metadata/mp4.c @@ -528,13 +528,7 @@ static bool read_mp4_tags(int fd, struct mp3entry* id3, buffer -= length; buffer_left += length; - if (parse_replaygain(tag_name, buffer, id3, - buffer, buffer_left) > 0) - { - /* Data used, keep it. */ - buffer += length; - buffer_left -= length; - } + parse_replaygain(tag_name, buffer, id3); } } } diff --git a/apps/metadata/mpc.c b/apps/metadata/mpc.c index 0387dc9f7..0b75ed04d 100644 --- a/apps/metadata/mpc.c +++ b/apps/metadata/mpc.c @@ -46,8 +46,7 @@ static int set_replaygain_sv7(struct mp3entry* id3, /* We use a peak value of 0 to indicate a given gain type isn't used. */ if (peak != 0) { /* Save the ReplayGain data to id3-structure for further processing. */ - used += parse_replaygain_int(album, gain * 512 / 100, peak << 9, - id3, id3->toc + used, sizeof(id3->toc) - used); + parse_replaygain_int(album, gain * 512 / 100, peak << 9, id3); } return used; @@ -73,8 +72,7 @@ static int set_replaygain_sv8(struct mp3entry* id3, /* We use a peak value of 0 to indicate a given gain type isn't used. */ if (peak != 0) { /* Save the ReplayGain data to id3-structure for further processing. */ - used += parse_replaygain_int(album, gain * 512 / 100, peak, - id3, id3->toc + used, sizeof(id3->toc) - used); + parse_replaygain_int(album, gain * 512 / 100, peak, id3); } return used; diff --git a/apps/replaygain.c b/apps/replaygain.c index 81f1a45ad..9f0dda7a0 100644 --- a/apps/replaygain.c +++ b/apps/replaygain.c @@ -36,6 +36,13 @@ #define FP_BITS (12) #define FP_ONE (1 << FP_BITS) +void replaygain_itoa(char* buffer, int length, long int_gain) +{ + /* int_gain uses Q19.12 format. */ + int one = abs(int_gain) >> FP_BITS; + int cent = ((abs(int_gain) & 0x0fff) * 100 + (FP_ONE/2)) >> FP_BITS; + snprintf(buffer, length, "%d.%02d dB", (int_gain<0) ? -one : one, cent); +} static long fp_atof(const char* s, int precision) { @@ -109,42 +116,25 @@ static long fp_atof(const char* s, int precision) + (((int64_t) frac_part * int_one) / frac_max_int)); } -static long convert_gain(long gain) +long convert_gain(long gain) { /* Don't allow unreasonably low or high gain changes. * Our math code can't handle it properly anyway. :) */ - if (gain < (-48 * FP_ONE)) - { - gain = -48 * FP_ONE; - } - - if (gain > (17 * FP_ONE)) - { - gain = 17 * FP_ONE; - } - - gain = fp_factor(gain, FP_BITS) << (24 - FP_BITS); + gain = MAX(gain,-48 * FP_ONE); + gain = MIN(gain, 17 * FP_ONE); - return gain; + return fp_factor(gain, FP_BITS) << (24 - FP_BITS); } -/* Get the sample scale factor in Q7.24 format from a gain value. Returns 0 +/* Get the sample scale factor in Q19.12 format from a gain value. Returns 0 * for no gain. * * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored. */ static long get_replaygain(const char* str) { - long gain = 0; - - if (str) - { - gain = fp_atof(str, FP_BITS); - gain = convert_gain(gain); - } - - return gain; + return fp_atof(str, FP_BITS); } /* Get the peak volume in Q7.24 format. @@ -153,14 +143,7 @@ static long get_replaygain(const char* str) */ static long get_replaypeak(const char* str) { - long peak = 0; - - if (str) - { - peak = fp_atof(str, 24); - } - - return peak; + return fp_atof(str, 24); } /* Get a sample scale factor in Q7.24 format from a gain value. @@ -174,107 +157,60 @@ long get_replaygain_int(long int_gain) /* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a * valid tag is found, update mp3entry struct accordingly. Existing values - * are not overwritten. Returns number of bytes written to buffer. + * are not overwritten. * * key Name of the tag. * value Value of the tag. * entry mp3entry struct to update. - * buffer Where to store the text for gain values (for later display). - * length Bytes left in buffer. */ -long parse_replaygain(const char* key, const char* value, - struct mp3entry* entry, char* buffer, int length) +void parse_replaygain(const char* key, const char* value, + struct mp3entry* entry) { - char **p = NULL; - - if (((strcasecmp(key, "replaygain_track_gain") == 0) - || (strcasecmp(key, "rg_radio") == 0)) && !entry->track_gain) + if (((strcasecmp(key, "replaygain_track_gain") == 0) || + (strcasecmp(key, "rg_radio") == 0)) && + !entry->track_gain) { entry->track_gain = get_replaygain(value); - p = &(entry->track_gain_string); } - else if (((strcasecmp(key, "replaygain_album_gain") == 0) - || (strcasecmp(key, "rg_audiophile") == 0)) && !entry->album_gain) + else if (((strcasecmp(key, "replaygain_album_gain") == 0) || + (strcasecmp(key, "rg_audiophile") == 0)) && + !entry->album_gain) { entry->album_gain = get_replaygain(value); - p = &(entry->album_gain_string); } - else if (((strcasecmp(key, "replaygain_track_peak") == 0) - || (strcasecmp(key, "rg_peak") == 0)) && !entry->track_peak) + else if (((strcasecmp(key, "replaygain_track_peak") == 0) || + (strcasecmp(key, "rg_peak") == 0)) && + !entry->track_peak) { entry->track_peak = get_replaypeak(value); } - else if ((strcasecmp(key, "replaygain_album_peak") == 0) - && !entry->album_peak) + else if ((strcasecmp(key, "replaygain_album_peak") == 0) && + !entry->album_peak) { entry->album_peak = get_replaypeak(value); } - - if (p) - { - int len = strlen(value); - - len = MIN(len, length - 1); - - /* A few characters just isn't interesting... */ - if (len > 1) - { - strlcpy(buffer, value, len + 1); - *p = buffer; - return len + 1; - } - } - - return 0; } /* Set ReplayGain values from integers. Existing values are not overwritten. - * Returns number of bytes written to buffer. * * album If true, set album values, otherwise set track values. * gain Gain value in dB, multiplied by 512. 0 for no gain. * peak Peak volume in Q7.24 format, where 1.0 is full scale. 0 for no * peak volume. - * buffer Where to store the text for gain values (for later display). - * length Bytes left in buffer. */ -long parse_replaygain_int(bool album, long gain, long peak, - struct mp3entry* entry, char* buffer, int length) +void parse_replaygain_int(bool album, long gain, long peak, + struct mp3entry* entry) { - long len = 0; - - if (buffer != NULL) - { - len = snprintf(buffer, length, "%ld.%02d dB", gain / 512, - ((abs(gain) & 0x01ff) * 100 + 256) / 512); - len++; - } - - if (gain != 0) - { - gain = convert_gain(gain * FP_ONE / 512); - } + gain = gain * FP_ONE / 512; if (album) { entry->album_gain = gain; - entry->album_gain_string = buffer; - - if (peak) - { - entry->album_peak = peak; - } + entry->album_peak = peak; } else { entry->track_gain = gain; - entry->track_gain_string = buffer; - - if (peak) - { - entry->track_peak = peak; - } + entry->track_peak = peak; } - - return len; } diff --git a/apps/replaygain.h b/apps/replaygain.h index 02ca2e0ba..4fb5476e2 100644 --- a/apps/replaygain.h +++ b/apps/replaygain.h @@ -25,9 +25,11 @@ #include "metadata.h" long get_replaygain_int(long int_gain); -long parse_replaygain(const char* key, const char* value, - struct mp3entry* entry, char* buffer, int length); -long parse_replaygain_int(bool album, long gain, long peak, - struct mp3entry* entry, char* buffer, int length); +void parse_replaygain(const char* key, const char* value, + struct mp3entry* entry); +void parse_replaygain_int(bool album, long gain, long peak, + struct mp3entry* entry); +void replaygain_itoa(char* buffer, int length, long int_gain); +long convert_gain(long gain); #endif diff --git a/apps/screens.c b/apps/screens.c index 81472e6cc..b1a48c5bd 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -53,6 +53,7 @@ #include "backdrop.h" #include "viewport.h" #include "language.h" +#include "replaygain.h" #if CONFIG_CODEC == SWCODEC #include "dsp.h" @@ -728,10 +729,12 @@ static const char* id3_get_info(int selected_item, void* data, break; #if CONFIG_CODEC == SWCODEC case LANG_ID3_TRACK_GAIN: - val=id3->track_gain_string; + replaygain_itoa(buffer, buffer_len, id3->track_gain); + val=(id3->track_gain) ? buffer : NULL; /* only show gains!=0 */ break; case LANG_ID3_ALBUM_GAIN: - val=id3->album_gain_string; + replaygain_itoa(buffer, buffer_len, id3->album_gain); + val=(id3->album_gain) ? buffer : NULL; /* only show gains!=0 */ break; #endif case LANG_ID3_PATH: -- 2.11.4.GIT