ref: 2bb99f3cf0119a43884cb7c04fb5dc8c3aec61fc
parent: 661459b4aad3511e28976d8dfd84e02b36cc3d63
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Tue Dec 29 09:36:25 EST 2015
Add support for R128_ALBUM_GAIN tag. This includes convenience routines specifying the album gain should be applied and for parsing the tag.
--- a/include/opusfile.h
+++ b/include/opusfile.h
@@ -531,6 +531,24 @@
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.
@@ -1763,6 +1781,10 @@
#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 @@
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.*/
--- a/src/info.c
+++ b/src/info.c
@@ -332,19 +332,20 @@
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 @@
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;
@@ -365,6 +366,14 @@
}
}
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){
--- a/src/opusfile.c
+++ b/src/opusfile.c
@@ -1307,13 +1307,20 @@
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 @@
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;