mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 13:15:18 -05:00
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
This commit is contained in:
parent
6510973223
commit
71ceac0b74
12 changed files with 65 additions and 158 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
gain = MAX(gain,-48 * FP_ONE);
|
||||
gain = MIN(gain, 17 * FP_ONE);
|
||||
|
||||
if (gain > (17 * FP_ONE))
|
||||
{
|
||||
gain = 17 * FP_ONE;
|
||||
}
|
||||
|
||||
gain = fp_factor(gain, FP_BITS) << (24 - FP_BITS);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->track_gain = gain;
|
||||
entry->track_gain_string = buffer;
|
||||
|
||||
if (peak)
|
||||
{
|
||||
entry->track_peak = peak;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue