diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp index e257f988f..3e3f4a2e1 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp @@ -216,6 +216,11 @@ float APE::Tag::rgTrackPeak() const return d->itemListMap["REPLAYGAIN_TRACK_PEAK"].toString().toFloat(); } +String APE::Tag::soundcheck() const +{ + return String(); +} + void APE::Tag::setTitle(const String &s) { addValue("TITLE", s, true); diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.h b/Frameworks/TagLib/taglib/taglib/ape/apetag.h index 872716098..bf892b0c6 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.h +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.h @@ -101,6 +101,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp index a9df89eeb..fdf7e56cc 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp @@ -154,6 +154,11 @@ float ASF::Tag::rgTrackPeak() const return 0; } +String ASF::Tag::soundcheck() const +{ + return String(); +} + void ASF::Tag::setTitle(const String &value) { d->title = value; diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.h b/Frameworks/TagLib/taglib/taglib/asf/asftag.h index 68f1b4b03..b11c130dc 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.h +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.h @@ -110,6 +110,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; /*! * Sets the title to \a s. diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp index 265757dbe..68bed9228 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp @@ -124,6 +124,11 @@ float Mod::Tag::rgTrackPeak() const return 0; } +String Mod::Tag::soundcheck() const +{ + return String(); +} + String Mod::Tag::trackerName() const { return d->trackerName; diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.h b/Frameworks/TagLib/taglib/taglib/mod/modtag.h index 16b62e11d..d65713e60 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.h +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.h @@ -124,6 +124,11 @@ namespace TagLib { */ virtual float rgTrackPeak() const; + /*! + * Not supported by module files. Therefore always returns empty. + */ + virtual String soundcheck() const; + /*! * Returns the name of the tracker used to create/edit the module file. * Only XM files store this tag to the file as such, for other formats diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp index 63f762c51..13efe7ff8 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp @@ -834,6 +834,14 @@ MP4::Tag::rgTrackPeak() const return 0; } +String +MP4::Tag::soundcheck() const +{ + if (d->items.contains("----:com.apple.iTunes:iTunNORM")) + return d->items["----:com.apple.iTunes:iTunNORM"].toStringList()[0]; + return String(); +} + void MP4::Tag::setTitle(const String &value) { diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h index 60ce51d7d..7384a8ce9 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h @@ -67,6 +67,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &value); virtual void setAlbumArtist(const String &value); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp index 847911ab3..87f816b28 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp @@ -197,6 +197,11 @@ float ID3v1::Tag::rgTrackPeak() const return 0; } +String ID3v1::Tag::soundcheck() const +{ + return String(); +} + void ID3v1::Tag::setTitle(const String &s) { d->title = s; diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h index 8ad94d9f4..c57314fa8 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h @@ -149,6 +149,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp index dfff41d4a..5eaa2d0dd 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp @@ -312,6 +312,24 @@ float ID3v2::Tag::rgTrackPeak() const return rg("replaygain_track_peak"); } +String ID3v2::Tag::soundcheck() const +{ + const FrameList &comments = d->frameListMap["COMM"]; + + if(comments.isEmpty()) + return String(); + + for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it) + { + CommentsFrame *frame = dynamic_cast(*it); + + if(frame && frame->description() == "iTunNORM") + return (*it)->toString(); + } + + return String(); +} + void ID3v2::Tag::setTitle(const String &s) { setTextFrame("TIT2", s); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h index 0e356df32..4cdccccf8 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h @@ -173,6 +173,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp index b1d37a2a0..e371be314 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp @@ -196,6 +196,11 @@ float Ogg::XiphComment::rgTrackPeak() const return d->fieldListMap["REPLAYGAIN_TRACK_PEAK"].front().toFloat(); } +String Ogg::XiphComment::soundcheck() const +{ + return String(); +} + void Ogg::XiphComment::setTitle(const String &s) { addField("TITLE", s); diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h index a29ce5648..335c68198 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h @@ -94,6 +94,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp index 60e0e2a5f..47009c9ab 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp @@ -158,6 +158,11 @@ float RIFF::Info::Tag::rgTrackPeak() const return 0; } +String RIFF::Info::Tag::soundcheck() const +{ + return String(); +} + void RIFF::Info::Tag::setTitle(const String &s) { setFieldText("INAM", s); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h index 4844ba010..b5e913377 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h @@ -116,6 +116,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/tag.h b/Frameworks/TagLib/taglib/taglib/tag.h index e2c9ac2d2..3304e17d6 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.h +++ b/Frameworks/TagLib/taglib/taglib/tag.h @@ -161,6 +161,12 @@ namespace TagLib { */ virtual float rgTrackPeak() const = 0; + /*! + * Returns the Apple SoundCheck tag; if there is tag set, this will + * return empty. + */ + virtual String soundcheck() const = 0; + /*! * Sets the title to \a s. If \a s is String::null then this value will be * cleared. diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.cpp b/Frameworks/TagLib/taglib/taglib/tagunion.cpp index f892c25a2..2abc55fcd 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.cpp +++ b/Frameworks/TagLib/taglib/taglib/tagunion.cpp @@ -243,6 +243,11 @@ float TagUnion::rgTrackPeak() const floatUnion(rgTrackPeak); } +String TagUnion::soundcheck() const +{ + stringUnion(soundcheck); +} + void TagUnion::setTitle(const String &s) { setUnion(Title, s); diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.h b/Frameworks/TagLib/taglib/taglib/tagunion.h index 1ceb05f3f..a6a03f44f 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.h +++ b/Frameworks/TagLib/taglib/taglib/tagunion.h @@ -73,6 +73,7 @@ namespace TagLib { virtual float rgAlbumPeak() const; virtual float rgTrackGain() const; virtual float rgTrackPeak() const; + virtual String soundcheck() const; virtual void setTitle(const String &s); virtual void setAlbumArtist(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp index bf28feb18..96c107500 100644 --- a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp +++ b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.cpp @@ -494,17 +494,17 @@ ByteVector String::data(Type t) const } } -int String::toInt() const +int String::toInt(unsigned int base) const { - return toInt(0); + return toInt(0, base); } -int String::toInt(bool *ok) const +int String::toInt(bool *ok, unsigned int base) const { const wchar_t *begin = d->data.c_str(); wchar_t *end; errno = 0; - const long value = ::wcstol(begin, &end, 10); + const long value = ::wcstol(begin, &end, base); // Has wcstol() consumed the entire string and not overflowed? if(ok) { diff --git a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h index 27c81eabc..5e6caf35e 100644 --- a/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h +++ b/Frameworks/TagLib/taglib/taglib/toolkit/tstring.h @@ -361,7 +361,7 @@ namespace TagLib { * string does not represent a number. */ // BIC: merge with the method below - int toInt() const; + int toInt(unsigned int base = 10) const; /*! * Convert the string to an integer. @@ -370,7 +370,7 @@ namespace TagLib { * true and returns the integer. Otherwise it sets \a *ok to false * and the result is undefined. */ - int toInt(bool *ok) const; + int toInt(bool *ok, unsigned int base = 10) const; /*! * Convert the string to a float. diff --git a/Plugins/TagLib/TagLibMetadataReader.m b/Plugins/TagLib/TagLibMetadataReader.m index 8c9776902..f14fa901d 100644 --- a/Plugins/TagLib/TagLibMetadataReader.m +++ b/Plugins/TagLib/TagLibMetadataReader.m @@ -75,6 +75,7 @@ int year, track, disc; float rgAlbumGain, rgAlbumPeak, rgTrackGain, rgTrackPeak; TagLib::String cuesheet; + TagLib::String soundcheck; artist = tag->artist(); albumartist = tag->albumartist(); @@ -101,6 +102,25 @@ [dict setObject:[NSNumber numberWithFloat:rgAlbumPeak] forKey:@"replayGainAlbumPeak"]; [dict setObject:[NSNumber numberWithFloat:rgTrackGain] forKey:@"replayGainTrackGain"]; [dict setObject:[NSNumber numberWithFloat:rgTrackPeak] forKey:@"replayGainTrackPeak"]; + + soundcheck = tag->soundcheck(); + if (!soundcheck.isEmpty()) { + TagLib::StringList tag = soundcheck.split(" "); + TagLib::StringList wantedTag; + for (int i = 0, count = tag.size(); i < count; i++) + { + if (tag[i].length() == 8) + wantedTag.append(tag[i]); + } + + if (wantedTag.size() >= 10) { + float volume1 = - log10( (double)((uint32_t)wantedTag[0].toInt(16)) / 1000 ) * 10; + float volume2 = - log10( (double)((uint32_t)wantedTag[1].toInt(16)) / 1000 ) * 10; + float volumeToUse = MIN(volume1, volume2); + float volumeScale = pow( 10, volumeToUse / 20 ); + [dict setObject:[NSNumber numberWithFloat:volumeScale] forKey:@"volume"]; + } + } if (!artist.isEmpty()) [dict setObject:[NSString stringWithUTF8String:artist.toCString(true)] forKey:@"artist"];