Commit 2bb99f3c authored by Timothy B. Terriberry's avatar Timothy B. Terriberry
Browse files

Add support for R128_ALBUM_GAIN tag.

This includes convenience routines specifying the album gain should
 be applied and for parsing the tag.
parent 661459b4
......@@ -531,6 +531,24 @@ const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count)
int opus_tags_query_count(const OpusTags *_tags,const char *_tag)
OP_ARG_NONNULL(1) OP_ARG_NONNULL(2);
/**Get the album gain from an R128_ALBUM_GAIN tag, if one was specified.
This searches for the first R128_ALBUM_GAIN tag with a valid signed,
16-bit decimal integer value and returns the value.
This routine is exposed merely for convenience for applications which wish
to do something special with the album gain (i.e., display it).
If you simply wish to apply the album gain instead of the header gain, you
can use op_set_gain_offset() with an #OP_ALBUM_GAIN type and no offset.
\param _tags An initialized #OpusTags structure.
\param[out] _gain_q8 The album gain, in 1/256ths of a dB.
This will lie in the range [-32768,32767], and should
be applied in <em>addition</em> to the header gain.
On error, no value is returned, and the previous
contents remain unchanged.
\return 0 on success, or a negative value on error.
\retval #OP_FALSE There was no album gain available in the given tags.*/
int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8)
OP_ARG_NONNULL(1) OP_ARG_NONNULL(2);
/**Get the track gain from an R128_TRACK_GAIN tag, if one was specified.
This searches for the first R128_TRACK_GAIN tag with a valid signed,
16-bit decimal integer value and returns the value.
......@@ -1762,6 +1780,10 @@ void op_set_decode_callback(OggOpusFile *_of,
This is the default.*/
#define OP_HEADER_GAIN (0)
/**Gain offset type that indicates that the provided offset is relative to the
R128_ALBUM_GAIN value (if any), in addition to the header gain.*/
#define OP_ALBUM_GAIN (3007)
/**Gain offset type that indicates that the provided offset is relative to the
R128_TRACK_GAIN value (if any), in addition to the header gain.*/
#define OP_TRACK_GAIN (3008)
......@@ -1782,8 +1804,8 @@ void op_set_decode_callback(OggOpusFile *_of,
It is meant for setting a target volume level, rather than applying smooth
fades, etc.
\param _of The \c OggOpusFile on which to set the gain offset.
\param _gain_type One of #OP_HEADER_GAIN, #OP_TRACK_GAIN, or
#OP_ABSOLUTE_GAIN.
\param _gain_type One of #OP_HEADER_GAIN, #OP_ALBUM_GAIN,
#OP_TRACK_GAIN, or #OP_ABSOLUTE_GAIN.
\param _gain_offset_q8 The gain offset to apply, in 1/256ths of a dB.
\return 0 on success or a negative value on error.
\retval #OP_EINVAL The \a _gain_type was unrecognized.*/
......
......@@ -332,19 +332,20 @@ int opus_tags_query_count(const OpusTags *_tags,const char *_tag){
return found;
}
int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8,
const char *_tag_name,size_t _tag_len){
char **comments;
int ncomments;
int ci;
comments=_tags->user_comments;
ncomments=_tags->comments;
/*Look for the first valid R128_TRACK_GAIN tag and use that.*/
/*Look for the first valid tag with the name _tag_name and use that.*/
for(ci=0;ci<ncomments;ci++){
if(opus_tagncompare("R128_TRACK_GAIN",15,comments[ci])==0){
if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){
char *p;
opus_int32 gain_q8;
int negative;
p=comments[ci]+16;
p=comments[ci]+_tag_len+1;
negative=0;
if(*p=='-'){
negative=-1;
......@@ -358,7 +359,7 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
p++;
}
/*This didn't look like a signed 16-bit decimal integer.
Not a valid R128_TRACK_GAIN tag.*/
Not a valid gain tag.*/
if(*p!='\0')continue;
*_gain_q8=(int)(gain_q8+negative^negative);
return 0;
......@@ -367,6 +368,14 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
return OP_FALSE;
}
int opus_tags_get_album_gain(const OpusTags *_tags,int *_gain_q8){
return opus_tags_get_gain(_tags,_gain_q8,"R128_ALBUM_GAIN",15);
}
int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
return opus_tags_get_gain(_tags,_gain_q8,"R128_TRACK_GAIN",15);
}
static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){
return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0
&&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0;
......
......@@ -1307,13 +1307,20 @@ static void op_update_gain(OggOpusFile *_of){
track gain must lie in the range [-32768,32767], and the user-supplied
offset has been pre-clamped to [-98302,98303].*/
switch(_of->gain_type){
case OP_ALBUM_GAIN:{
int album_gain_q8;
album_gain_q8=0;
opus_tags_get_album_gain(&_of->links[li].tags,&album_gain_q8);
gain_q8+=album_gain_q8;
gain_q8+=head->output_gain;
}break;
case OP_TRACK_GAIN:{
int track_gain_q8;
track_gain_q8=0;
opus_tags_get_track_gain(&_of->links[li].tags,&track_gain_q8);
gain_q8+=track_gain_q8;
}
/*Fall through.*/
gain_q8+=head->output_gain;
}break;
case OP_HEADER_GAIN:gain_q8+=head->output_gain;break;
case OP_ABSOLUTE_GAIN:break;
default:OP_ASSERT(0);
......@@ -2666,8 +2673,8 @@ void op_set_decode_callback(OggOpusFile *_of,
int op_set_gain_offset(OggOpusFile *_of,
int _gain_type,opus_int32 _gain_offset_q8){
if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_TRACK_GAIN
&&_gain_type!=OP_ABSOLUTE_GAIN){
if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_ALBUM_GAIN
&&_gain_type!=OP_TRACK_GAIN&&_gain_type!=OP_ABSOLUTE_GAIN){
return OP_EINVAL;
}
_of->gain_type=_gain_type;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment