mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
metadata: read R128 gain tags in Opus files
RFC 7845 specifies R128_TRACK_GAIN and R128_ALBUM_GAIN for loudness normalization in Opus files, but Rockbox only understood the REPLAYGAIN_* tags. Parse the R128 tags as Q7.8 dB values relative to -23 LUFS and add 5 dB to match the ReplayGain reference level. If a file has both kinds of tags, the R128 tags take priority. Fixes FS#13624 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: I0ef08a7897ec5ee8d1e5d99e7d9ea3901847fa52
This commit is contained in:
parent
27a8ca3f55
commit
5880b6111c
1 changed files with 44 additions and 2 deletions
|
|
@ -138,6 +138,26 @@ static long get_replaygain(const char* str)
|
||||||
return fp_atof(str, FP_BITS);
|
return fp_atof(str, FP_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the gain in Q19.12 format from an Opus R128 gain tag (RFC 7845).
|
||||||
|
* Returns false if the tag is not a valid integer.
|
||||||
|
*
|
||||||
|
* str Gain in dB as a Q7.8 integer, relative to -23 LUFS.
|
||||||
|
*/
|
||||||
|
static bool get_r128_gain(const char* str, long* gain)
|
||||||
|
{
|
||||||
|
char* end;
|
||||||
|
long q8 = strtol(str, &end, 10);
|
||||||
|
|
||||||
|
if (end == str || q8 < -32768 || q8 > 32767)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ReplayGain targets -18 LUFS, so add 5 dB to match its loudness */
|
||||||
|
*gain = q8 * (FP_ONE / 256) + 5 * FP_ONE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the peak volume in Q7.24 format.
|
/* Get the peak volume in Q7.24 format.
|
||||||
*
|
*
|
||||||
* str Peak volume. Full scale is specified as "1.0". Returns 0 for no peak.
|
* str Peak volume. Full scale is specified as "1.0". Returns 0 for no peak.
|
||||||
|
|
@ -158,7 +178,8 @@ long get_replaygain_int(long int_gain)
|
||||||
|
|
||||||
/* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
|
/* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
|
||||||
* valid tag is found, update mp3entry struct accordingly. Existing values
|
* valid tag is found, update mp3entry struct accordingly. Existing values
|
||||||
* are not overwritten.
|
* are not overwritten, except by the R128 gain tags in Opus files, which
|
||||||
|
* take priority over REPLAYGAIN tags.
|
||||||
*
|
*
|
||||||
* key Name of the tag.
|
* key Name of the tag.
|
||||||
* value Value of the tag.
|
* value Value of the tag.
|
||||||
|
|
@ -170,9 +191,30 @@ void parse_replaygain(const char* key, const char* value,
|
||||||
static const char *rg_options[] = {"replaygain_track_gain", "rg_radio",
|
static const char *rg_options[] = {"replaygain_track_gain", "rg_radio",
|
||||||
"replaygain_album_gain", "rg_audiophile",
|
"replaygain_album_gain", "rg_audiophile",
|
||||||
"replaygain_track_peak", "rg_peak",
|
"replaygain_track_peak", "rg_peak",
|
||||||
"replaygain_album_peak", NULL};
|
"replaygain_album_peak",
|
||||||
|
"r128_track_gain", "r128_album_gain",
|
||||||
|
NULL};
|
||||||
|
|
||||||
int rg_op = string_option(key, rg_options, true);
|
int rg_op = string_option(key, rg_options, true);
|
||||||
|
long gain;
|
||||||
|
|
||||||
|
if (rg_op == 7 || rg_op == 8)
|
||||||
|
{ /*r128_track_gain||r128_album_gain, only defined for Opus*/
|
||||||
|
if (entry->codectype == AFMT_OPUS && get_r128_gain(value, &gain))
|
||||||
|
{
|
||||||
|
if (rg_op == 7)
|
||||||
|
{
|
||||||
|
entry->track_level = gain;
|
||||||
|
entry->track_gain = convert_gain(gain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry->album_level = gain;
|
||||||
|
entry->album_gain = convert_gain(gain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((rg_op == 0 || rg_op == 1) && !entry->track_gain)
|
if ((rg_op == 0 || rg_op == 1) && !entry->track_gain)
|
||||||
{ /*replaygain_track_gain||rg_radio*/
|
{ /*replaygain_track_gain||rg_radio*/
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue