Format taglib sources

This commit is contained in:
Jonas Kvinge
2020-06-13 19:02:42 +02:00
parent 72bff7fa35
commit 4ce099294c
224 changed files with 12905 additions and 15623 deletions

View File

@@ -38,25 +38,22 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
enum { MPCAPEIndex = 0, MPCID3v1Index = 1 };
namespace {
enum { MPCAPEIndex = 0,
MPCID3v1Index = 1 };
}
class MPC::File::FilePrivate
{
public:
FilePrivate() :
APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
ID3v2Location(-1),
ID3v2Size(0),
properties(0) {}
class MPC::File::FilePrivate {
public:
FilePrivate() : APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
ID3v2Location(-1),
ID3v2Size(0),
properties(0) {}
~FilePrivate()
{
~FilePrivate() {
delete ID3v2Header;
delete properties;
}
@@ -79,8 +76,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool MPC::File::isSupported(IOStream *stream)
{
bool MPC::File::isSupported(IOStream *stream) {
// A newer MPC file has to start with "MPCK" or "MP+", but older files don't
// have keys to do a quick check.
@@ -92,71 +88,60 @@ bool MPC::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MPC::File::~File()
{
MPC::File::~File() {
delete d;
}
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const
{
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const {
return &d->tag;
}
PropertyMap MPC::File::properties() const
{
PropertyMap MPC::File::properties() const {
return d->tag.properties();
}
void MPC::File::removeUnsupportedProperties(const StringList &properties)
{
void MPC::File::removeUnsupportedProperties(const StringList &properties) {
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap MPC::File::setProperties(const PropertyMap &properties)
{
if(ID3v1Tag())
PropertyMap MPC::File::setProperties(const PropertyMap &properties) {
if (ID3v1Tag())
ID3v1Tag()->setProperties(properties);
return APETag(true)->setProperties(properties);
}
MPC::Properties *MPC::File::audioProperties() const
{
MPC::Properties *MPC::File::audioProperties() const {
return d->properties;
}
bool MPC::File::save()
{
if(readOnly()) {
bool MPC::File::save() {
if (readOnly()) {
debug("MPC::File::save() -- File is read only.");
return false;
}
// Possibly strip ID3v2 tag
if(!d->ID3v2Header && d->ID3v2Location >= 0) {
if (!d->ID3v2Header && d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, d->ID3v2Size);
if(d->APELocation >= 0)
if (d->APELocation >= 0)
d->APELocation -= d->ID3v2Size;
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->ID3v2Size;
d->ID3v2Location = -1;
@@ -165,11 +150,11 @@ bool MPC::File::save()
// Update ID3v1 tag
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
if (ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
}
else {
@@ -183,7 +168,7 @@ bool MPC::File::save()
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
@@ -191,12 +176,12 @@ bool MPC::File::save()
// Update APE tag
if(APETag() && !APETag()->isEmpty()) {
if (APETag() && !APETag()->isEmpty()) {
// APE tag is not empty. Update the old one or create a new one.
if(d->APELocation < 0) {
if(d->ID3v1Location >= 0)
if (d->APELocation < 0) {
if (d->ID3v1Location >= 0)
d->APELocation = d->ID3v1Location;
else
d->APELocation = length();
@@ -205,7 +190,7 @@ bool MPC::File::save()
const ByteVector data = APETag()->render();
insert(data, d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->APESize = data.size();
@@ -214,10 +199,10 @@ bool MPC::File::save()
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
removeBlock(d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
d->APELocation = -1;
@@ -228,45 +213,39 @@ bool MPC::File::save()
return true;
}
ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
{
ID3v1::Tag *MPC::File::ID3v1Tag(bool create) {
return d->tag.access<ID3v1::Tag>(MPCID3v1Index, create);
}
APE::Tag *MPC::File::APETag(bool create)
{
APE::Tag *MPC::File::APETag(bool create) {
return d->tag.access<APE::Tag>(MPCAPEIndex, create);
}
void MPC::File::strip(int tags)
{
if(tags & ID3v1)
void MPC::File::strip(int tags) {
if (tags & ID3v1)
d->tag.set(MPCID3v1Index, 0);
if(tags & APE)
if (tags & APE)
d->tag.set(MPCAPEIndex, 0);
if(!ID3v1Tag())
if (!ID3v1Tag())
APETag(true);
if(tags & ID3v2) {
if (tags & ID3v2) {
delete d->ID3v2Header;
d->ID3v2Header = 0;
}
}
void MPC::File::remove(int tags)
{
void MPC::File::remove(int tags) {
strip(tags);
}
bool MPC::File::hasID3v1Tag() const
{
bool MPC::File::hasID3v1Tag() const {
return (d->ID3v1Location >= 0);
}
bool MPC::File::hasAPETag() const
{
bool MPC::File::hasAPETag() const {
return (d->APELocation >= 0);
}
@@ -274,13 +253,12 @@ bool MPC::File::hasAPETag() const
// private members
////////////////////////////////////////////////////////////////////////////////
void MPC::File::read(bool readProperties)
{
void MPC::File::read(bool readProperties) {
// Look for an ID3v2 tag
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
@@ -290,36 +268,36 @@ void MPC::File::read(bool readProperties)
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
// Look for an APE tag
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
d->tag.set(MPCAPEIndex, new APE::Tag(this, d->APELocation));
d->APESize = APETag()->footer()->completeTagSize();
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
}
if(d->ID3v1Location < 0)
if (d->ID3v1Location < 0)
APETag(true);
// Look for MPC metadata
if(readProperties) {
if (readProperties) {
long streamLength;
if(d->APELocation >= 0)
if (d->APELocation >= 0)
streamLength = d->APELocation;
else if(d->ID3v1Location >= 0)
else if (d->ID3v1Location >= 0)
streamLength = d->ID3v1Location;
else
streamLength = length();
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
}

View File

@@ -37,14 +37,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
class Tag;
class Tag;
namespace ID3v1 { class Tag; }
namespace APE { class Tag; }
namespace ID3v1 {
class Tag;
}
namespace APE {
class Tag;
}
//! An implementation of MPC metadata
//! An implementation of MPC metadata
/*!
/*!
* This is implementation of MPC metadata.
*
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
@@ -52,11 +56,11 @@ namespace TagLib {
* and ignored.
*/
namespace MPC {
namespace MPC {
//! An implementation of TagLib::File with MPC specific methods
//! An implementation of TagLib::File with MPC specific methods
/*!
/*!
* This implements and provides an interface for MPC files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
@@ -64,36 +68,35 @@ namespace TagLib {
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
public:
/*!
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
* being OR-ed together.
*/
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
//! Matches ID3v1 tags.
ID3v1 = 0x0001,
//! Matches ID3v2 tags.
ID3v2 = 0x0002,
//! Matches APE tags.
APE = 0x0004,
//! Matches all tag types.
AllTags = 0xffff
};
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
//! Matches ID3v1 tags.
ID3v1 = 0x0001,
//! Matches ID3v2 tags.
ID3v2 = 0x0002,
//! Matches APE tags.
APE = 0x0004,
//! Matches all tag types.
AllTags = 0xffff
};
/*!
/*!
* Constructs an MPC file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
/*!
* Constructs an MPC file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
@@ -102,50 +105,50 @@ namespace TagLib {
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
/*!
* Destroys this instance of the File.
*/
virtual ~File();
virtual ~File();
/*!
/*!
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
* or a combination of the two.
*/
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
/*!
/*!
* Implements the unified property interface -- export function.
* If the file contains both an APE and an ID3v1 tag, only the APE
* tag will be converted to the PropertyMap.
*/
PropertyMap properties() const;
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
void removeUnsupportedProperties(const StringList &properties);
/*!
/*!
* Implements the unified property interface -- import function.
* Affects only the APEv2 tag which will be created if necessary.
* If an ID3v1 tag exists, it will be updated as well.
*/
PropertyMap setProperties(const PropertyMap &);
PropertyMap setProperties(const PropertyMap &);
/*!
/*!
* Returns the MPC::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
virtual Properties *audioProperties() const;
/*!
/*!
* Saves the file.
*
* This returns true if the save was successful.
*/
virtual bool save();
virtual bool save();
/*!
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this returns a null pointer
@@ -162,9 +165,9 @@ namespace TagLib {
*
* \see hasID3v1Tag()
*/
ID3v1::Tag *ID3v1Tag(bool create = false);
ID3v1::Tag *ID3v1Tag(bool create = false);
/*!
/*!
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this may return a null pointer
@@ -182,9 +185,9 @@ namespace TagLib {
*
* \see hasAPETag()
*/
APE::Tag *APETag(bool create = false);
APE::Tag *APETag(bool create = false);
/*!
/*!
* This will remove the tags that match the OR-ed together TagTypes from the
* file. By default it removes all tags.
*
@@ -193,48 +196,48 @@ namespace TagLib {
*
* \note In order to make the removal permanent save() still needs to be called.
*/
void strip(int tags = AllTags);
void strip(int tags = AllTags);
/*!
/*!
* \deprecated
* \see strip
*/
TAGLIB_DEPRECATED void remove(int tags = AllTags);
TAGLIB_DEPRECATED void remove(int tags = AllTags);
/*!
/*!
* Returns whether or not the file on disk actually has an ID3v1 tag.
*
* \see ID3v1Tag()
*/
bool hasID3v1Tag() const;
bool hasID3v1Tag() const;
/*!
/*!
* Returns whether or not the file on disk actually has an APE tag.
*
* \see APETag()
*/
bool hasAPETag() const;
bool hasAPETag() const;
/*!
/*!
* Returns whether or not the given \a stream can be opened as an MPC
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
static bool isSupported(IOStream *stream);
private:
File(const File &);
File &operator=(const File &);
private:
File(const File &);
File &operator=(const File &);
void read(bool readProperties);
void read(bool readProperties);
class FilePrivate;
FilePrivate *d;
};
}
}
}
class FilePrivate;
FilePrivate *d;
};
} // namespace MPC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -33,21 +33,19 @@
using namespace Strawberry_TagLib::TagLib;
class MPC::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
version(0),
length(0),
bitrate(0),
sampleRate(0),
channels(0),
totalFrames(0),
sampleFrames(0),
trackGain(0),
trackPeak(0),
albumGain(0),
albumPeak(0) {}
class MPC::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : version(0),
length(0),
bitrate(0),
sampleRate(0),
channels(0),
totalFrames(0),
sampleFrames(0),
trackGain(0),
trackPeak(0),
albumGain(0),
albumPeak(0) {}
int version;
int length;
@@ -66,19 +64,15 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
readSV7(data, streamLength);
}
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
ByteVector magic = file->readBlock(4);
if(magic == "MPCK") {
if (magic == "MPCK") {
// Musepack version 8
readSV8(file, streamLength);
}
@@ -88,73 +82,59 @@ MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
}
}
MPC::Properties::~Properties()
{
MPC::Properties::~Properties() {
delete d;
}
int MPC::Properties::length() const
{
int MPC::Properties::length() const {
return lengthInSeconds();
}
int MPC::Properties::lengthInSeconds() const
{
int MPC::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int MPC::Properties::lengthInMilliseconds() const
{
int MPC::Properties::lengthInMilliseconds() const {
return d->length;
}
int MPC::Properties::bitrate() const
{
int MPC::Properties::bitrate() const {
return d->bitrate;
}
int MPC::Properties::sampleRate() const
{
int MPC::Properties::sampleRate() const {
return d->sampleRate;
}
int MPC::Properties::channels() const
{
int MPC::Properties::channels() const {
return d->channels;
}
int MPC::Properties::mpcVersion() const
{
int MPC::Properties::mpcVersion() const {
return d->version;
}
unsigned int MPC::Properties::totalFrames() const
{
unsigned int MPC::Properties::totalFrames() const {
return d->totalFrames;
}
unsigned int MPC::Properties::sampleFrames() const
{
unsigned int MPC::Properties::sampleFrames() const {
return d->sampleFrames;
}
int MPC::Properties::trackGain() const
{
int MPC::Properties::trackGain() const {
return d->trackGain;
}
int MPC::Properties::trackPeak() const
{
int MPC::Properties::trackPeak() const {
return d->trackPeak;
}
int MPC::Properties::albumGain() const
{
int MPC::Properties::albumGain() const {
return d->albumGain;
}
int MPC::Properties::albumPeak() const
{
int MPC::Properties::albumPeak() const {
return d->albumPeak;
}
@@ -162,58 +142,54 @@ int MPC::Properties::albumPeak() const
// private members
////////////////////////////////////////////////////////////////////////////////
namespace
{
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
{
sizeLength = 0;
eof = false;
namespace {
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) {
sizeLength = 0;
eof = false;
unsigned char tmp;
unsigned long size = 0;
unsigned char tmp;
unsigned long size = 0;
do {
const ByteVector b = file->readBlock(1);
if(b.isEmpty()) {
eof = true;
break;
}
do {
const ByteVector b = file->readBlock(1);
if (b.isEmpty()) {
eof = true;
break;
}
tmp = b[0];
size = (size << 7) | (tmp & 0x7F);
sizeLength++;
} while((tmp & 0x80));
return size;
}
unsigned long readSize(const ByteVector &data, unsigned int &pos)
{
unsigned char tmp;
unsigned long size = 0;
do {
tmp = data[pos++];
size = (size << 7) | (tmp & 0x7F);
} while((tmp & 0x80) && (pos < data.size()));
return size;
}
// This array looks weird, but the same as original MusePack code found at:
// https://www.musepack.net/index.php?pg=src
const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
tmp = b[0];
size = (size << 7) | (tmp & 0x7F);
sizeLength++;
} while ((tmp & 0x80));
return size;
}
void MPC::Properties::readSV8(File *file, long streamLength)
{
unsigned long readSize(const ByteVector &data, unsigned int &pos) {
unsigned char tmp;
unsigned long size = 0;
do {
tmp = data[pos++];
size = (size << 7) | (tmp & 0x7F);
} while ((tmp & 0x80) && (pos < data.size()));
return size;
}
// This array looks weird, but the same as original MusePack code found at:
// https://www.musepack.net/index.php?pg=src
const unsigned short sftable[8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
} // namespace
void MPC::Properties::readSV8(File *file, long streamLength) {
bool readSH = false, readRG = false;
while(!readSH && !readRG) {
while (!readSH && !readRG) {
const ByteVector packetType = file->readBlock(2);
unsigned int packetSizeLength;
bool eof;
const unsigned long packetSize = readSize(file, packetSizeLength, eof);
if(eof) {
if (eof) {
debug("MPC::Properties::readSV8() - Reached to EOF.");
break;
}
@@ -221,16 +197,16 @@ void MPC::Properties::readSV8(File *file, long streamLength)
const unsigned long dataSize = packetSize - 2 - packetSizeLength;
const ByteVector data = file->readBlock(dataSize);
if(data.size() != dataSize) {
if (data.size() != dataSize) {
debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
break;
}
if(packetType == "SH") {
if (packetType == "SH") {
// Stream Header
// http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket
if(dataSize <= 5) {
if (dataSize <= 5) {
debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
break;
}
@@ -241,13 +217,13 @@ void MPC::Properties::readSV8(File *file, long streamLength)
d->version = data[pos];
pos += 1;
d->sampleFrames = readSize(data, pos);
if(pos > dataSize - 3) {
if (pos > dataSize - 3) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
break;
}
const unsigned long begSilence = readSize(data, pos);
if(pos > dataSize - 2) {
if (pos > dataSize - 2) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
break;
}
@@ -256,12 +232,12 @@ void MPC::Properties::readSV8(File *file, long streamLength)
pos += 2;
d->sampleRate = sftable[(flags >> 13) & 0x07];
d->channels = ((flags >> 4) & 0x0F) + 1;
d->channels = ((flags >> 4) & 0x0F) + 1;
const unsigned int frameCount = d->sampleFrames - begSilence;
if(frameCount > 0 && d->sampleRate > 0) {
if (frameCount > 0 && d->sampleRate > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
}
@@ -269,7 +245,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
// Replay Gain
// http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket
if(dataSize <= 9) {
if (dataSize <= 9) {
debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
break;
}
@@ -277,7 +253,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
readRG = true;
const int replayGainVersion = data[0];
if(replayGainVersion == 1) {
if (replayGainVersion == 1) {
d->trackGain = data.toShort(1, true);
d->trackPeak = data.toShort(3, true);
d->albumGain = data.toShort(5, true);
@@ -285,7 +261,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
}
}
else if(packetType == "SE") {
else if (packetType == "SE") {
break;
}
@@ -295,18 +271,17 @@ void MPC::Properties::readSV8(File *file, long streamLength)
}
}
void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
{
if(data.startsWith("MP+")) {
void MPC::Properties::readSV7(const ByteVector &data, long streamLength) {
if (data.startsWith("MP+")) {
d->version = data[3] & 15;
if(d->version < 7)
if (d->version < 7)
return;
d->totalFrames = data.toUInt(4, false);
const unsigned int flags = data.toUInt(8, false);
d->sampleRate = sftable[(flags >> 16) & 0x03];
d->channels = 2;
d->channels = 2;
const unsigned int gapless = data.toUInt(5, false);
@@ -316,15 +291,15 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->albumPeak = data.toUShort(16, false);
// convert gain info
if(d->trackGain != 0) {
if (d->trackGain != 0) {
int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->trackGain = tmp;
}
if(d->albumGain != 0) {
if (d->albumGain != 0) {
int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->albumGain = tmp;
}
@@ -335,7 +310,7 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);
bool trueGapless = (gapless >> 31) & 0x0001;
if(trueGapless) {
if (trueGapless) {
unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
}
@@ -345,12 +320,12 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
else {
const unsigned int headerData = data.toUInt(0, false);
d->bitrate = (headerData >> 23) & 0x01ff;
d->version = (headerData >> 11) & 0x03ff;
d->bitrate = (headerData >> 23) & 0x01ff;
d->version = (headerData >> 11) & 0x03ff;
d->sampleRate = 44100;
d->channels = 2;
d->channels = 2;
if(d->version >= 5)
if (d->version >= 5)
d->totalFrames = data.toUInt(4, false);
else
d->totalFrames = data.toUShort(6, false);
@@ -358,11 +333,11 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->sampleFrames = d->totalFrames * 1152 - 576;
}
if(d->sampleFrames > 0 && d->sampleRate > 0) {
if (d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
if(d->bitrate == 0)
if (d->bitrate == 0)
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
}

View File

@@ -32,42 +32,41 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MPC {
namespace MPC {
class File;
class File;
static const unsigned int HeaderSize = 8 * 7;
static const unsigned int HeaderSize = 8 * 7;
//! An implementation of audio property reading for MPC
//! An implementation of audio property reading for MPC
/*!
/*!
* This reads the data from an MPC stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
{
public:
/*!
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of MPC::Properties with the data read from the
* ByteVector \a data.
*
* This constructor is deprecated. It only works for MPC version up to 7.
*/
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
/*!
/*!
* Create an instance of MPC::Properties with the data read directly
* from a MPC::File.
*/
Properties(File *file, long streamLength, ReadStyle style = Average);
Properties(File *file, long streamLength, ReadStyle style = Average);
/*!
/*!
* Destroys this MPC::Properties instance.
*/
virtual ~Properties();
virtual ~Properties();
/*!
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
@@ -75,86 +74,86 @@ namespace TagLib {
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
TAGLIB_DEPRECATED virtual int length() const;
/*!
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
// BIC: make virtual
int lengthInSeconds() const;
/*!
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
virtual int bitrate() const;
/*!
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
virtual int sampleRate() const;
/*!
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
virtual int channels() const;
/*!
/*!
* Returns the version of the bitstream (SV4-SV8)
*/
int mpcVersion() const;
int mpcVersion() const;
unsigned int totalFrames() const;
unsigned int sampleFrames() const;
unsigned int totalFrames() const;
unsigned int sampleFrames() const;
/*!
/*!
* Returns the track gain as an integer value,
* to convert to dB: trackGain in dB = 64.82 - (trackGain / 256)
*/
int trackGain() const;
int trackGain() const;
/*!
/*!
* Returns the track peak as an integer value,
* to convert to dB: trackPeak in dB = trackPeak / 256
* to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768
*/
int trackPeak() const;
int trackPeak() const;
/*!
/*!
* Returns the album gain as an integer value,
* to convert to dB: albumGain in dB = 64.82 - (albumGain / 256)
*/
int albumGain() const;
int albumGain() const;
/*!
/*!
* Returns the album peak as an integer value,
* to convert to dB: albumPeak in dB = albumPeak / 256
* to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768
*/
int albumPeak() const;
int albumPeak() const;
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
private:
Properties(const Properties &);
Properties &operator=(const Properties &);
void readSV7(const ByteVector &data, long streamLength);
void readSV8(File *file, long streamLength);
void readSV7(const ByteVector &data, long streamLength);
void readSV8(File *file, long streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
class PropertiesPrivate;
PropertiesPrivate *d;
};
} // namespace MPC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif