Refactored AudioProperties classes in some ways

This commit is contained in:
Tsuda Kageyu
2013-07-13 10:38:52 +09:00
parent 6d89689c0e
commit 6d40cbc04f
44 changed files with 498 additions and 477 deletions

View File

@ -29,7 +29,7 @@
#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include "id3v2tag.h"
#include "apeproperties.h"
#include "apefile.h"
@ -39,16 +39,14 @@ using namespace TagLib;
class APE::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *file, offset_t streamLength) :
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
version(0),
bitsPerSample(0),
sampleFrames(0),
file(file),
streamLength(streamLength) {}
sampleFrames(0) {}
int length;
int bitrate;
@ -57,19 +55,16 @@ public:
int version;
int bitsPerSample;
uint sampleFrames;
File *file;
offset_t streamLength;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
APE::AudioProperties::AudioProperties(File *file, ReadStyle style)
: TagLib::AudioProperties(style)
APE::AudioProperties::AudioProperties(File *file, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, file->length());
read();
read(file);
}
APE::AudioProperties::~AudioProperties()
@ -117,35 +112,35 @@ TagLib::uint APE::AudioProperties::sampleFrames() const
////////////////////////////////////////////////////////////////////////////////
void APE::AudioProperties::read()
void APE::AudioProperties::read(File *file)
{
// First we are searching the descriptor
offset_t offset = findDescriptor();
offset_t offset = findDescriptor(file);
if(offset < 0)
return;
// Then we read the header common for all versions of APE
d->file->seek(offset);
ByteVector commonHeader = d->file->readBlock(6);
file->seek(offset);
ByteVector commonHeader = file->readBlock(6);
if(!commonHeader.startsWith("MAC "))
return;
d->version = commonHeader.toUInt16LE(4);
if(d->version >= 3980) {
analyzeCurrent();
analyzeCurrent(file);
}
else {
analyzeOld();
analyzeOld(file);
}
}
offset_t APE::AudioProperties::findDescriptor()
offset_t APE::AudioProperties::findDescriptor(File *file)
{
offset_t ID3v2Location = findID3v2();
offset_t ID3v2Location = findID3v2(file);
long ID3v2OriginalSize = 0;
bool hasID3v2 = false;
if(ID3v2Location >= 0) {
ID3v2::Tag tag(d->file, ID3v2Location);
ID3v2::Tag tag(file, ID3v2Location);
ID3v2OriginalSize = tag.header()->completeTagSize();
if(tag.header()->tagSize() > 0)
hasID3v2 = true;
@ -153,9 +148,9 @@ offset_t APE::AudioProperties::findDescriptor()
offset_t offset = 0;
if(hasID3v2)
offset = d->file->find("MAC ", ID3v2Location + ID3v2OriginalSize);
offset = file->find("MAC ", ID3v2Location + ID3v2OriginalSize);
else
offset = d->file->find("MAC ");
offset = file->find("MAC ");
if(offset < 0) {
debug("APE::Properties::findDescriptor() -- APE descriptor not found");
@ -165,31 +160,31 @@ offset_t APE::AudioProperties::findDescriptor()
return offset;
}
offset_t APE::AudioProperties::findID3v2()
offset_t APE::AudioProperties::findID3v2(File *file)
{
if(!d->file->isValid())
if(!file->isValid())
return -1;
d->file->seek(0);
file->seek(0);
if(d->file->readBlock(3) == ID3v2::Header::fileIdentifier())
if(file->readBlock(3) == ID3v2::Header::fileIdentifier())
return 0;
return -1;
}
void APE::AudioProperties::analyzeCurrent()
void APE::AudioProperties::analyzeCurrent(File *file)
{
// Read the descriptor
d->file->seek(2, File::Current);
ByteVector descriptor = d->file->readBlock(44);
file->seek(2, File::Current);
ByteVector descriptor = file->readBlock(44);
const uint descriptorBytes = descriptor.toUInt32LE(0);
if ((descriptorBytes - 52) > 0)
d->file->seek(descriptorBytes - 52, File::Current);
file->seek(descriptorBytes - 52, File::Current);
// Read the header
ByteVector header = d->file->readBlock(24);
ByteVector header = file->readBlock(24);
// Get the APE info
d->channels = header.toInt16LE(18);
@ -203,12 +198,12 @@ void APE::AudioProperties::analyzeCurrent()
d->sampleFrames = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(file->length() * 8L / d->length / 1000) : 0;
}
void APE::AudioProperties::analyzeOld()
void APE::AudioProperties::analyzeOld(File *file)
{
ByteVector header = d->file->readBlock(26);
ByteVector header = file->readBlock(26);
const uint totalFrames = header.toUInt32LE(18);
// Fail on 0 length APE files (catches non-finalized APE files)
@ -229,6 +224,6 @@ void APE::AudioProperties::analyzeOld()
const uint finalFrameBlocks = header.toUInt32LE(22);
const uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
d->length = totalBlocks / d->sampleRate;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(file->length() * 8L / d->length / 1000) : 0;
}

View File

@ -50,10 +50,10 @@ namespace TagLib {
{
public:
/*!
* Create an instance of APE::AudioProperties with the data read from
* Creates an instance of APE::AudioProperties with the data read from
* the ByteVector \a data.
*/
AudioProperties(File *f, ReadStyle style = Average);
AudioProperties(File *file, ReadStyle style = Average);
/*!
* Destroys this APE::AudioProperties instance.
@ -79,16 +79,13 @@ namespace TagLib {
int version() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read(File *file);
void read();
offset_t findDescriptor(File *file);
offset_t findID3v2(File *file);
offset_t findDescriptor();
offset_t findID3v2();
void analyzeCurrent();
void analyzeOld();
void analyzeCurrent(File *file);
void analyzeOld(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -32,7 +32,13 @@ using namespace TagLib;
class ASF::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0), encrypted(false) {}
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
encrypted(false) {}
int length;
int bitrate;
int sampleRate;
@ -44,16 +50,14 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::AudioProperties::AudioProperties()
: TagLib::AudioProperties(AudioProperties::Average)
ASF::AudioProperties::AudioProperties() :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate;
}
ASF::AudioProperties::~AudioProperties()
{
if(d)
delete d;
delete d;
}
int ASF::AudioProperties::length() const

View File

@ -34,13 +34,16 @@ namespace TagLib {
namespace ASF {
class File;
//! An implementation of ASF audio properties
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
public:
friend class File;
public:
/*!
* Create an instance of ASF::AudioProperties.
* Creates an instance of ASF::AudioProperties.
*/
AudioProperties();
@ -50,21 +53,20 @@ namespace TagLib {
virtual ~AudioProperties();
// Reimplementations.
virtual int length() const;
virtual int bitrate() const;
virtual int sampleRate() const;
virtual int channels() const;
bool isEncrypted() const;
#ifndef DO_NOT_DOCUMENT
private:
void setLength(int value);
void setBitrate(int value);
void setSampleRate(int value);
void setChannels(int value);
void setEncrypted(bool value);
#endif
private:
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@ -28,31 +28,15 @@
using namespace TagLib;
class AudioProperties::AudioPropertiesPrivate
{
};
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::~AudioProperties()
{
}
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::AudioProperties(ReadStyle)
{
}
String
AudioProperties::toString() const
String AudioProperties::toString() const
{
StringList desc;
desc.append("Audio");
@ -60,3 +44,11 @@ AudioProperties::toString() const
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::AudioProperties()
{
}

View File

@ -95,21 +95,16 @@ namespace TagLib {
protected:
/*!
* Construct an audio properties instance. This is protected as this class
* Constructs an audio properties instance. This is protected as this class
* should not be instantiated directly, but should be instantiated via its
* subclasses and can be fetched from the FileRef or File APIs.
*
* \see ReadStyle
*/
AudioProperties(ReadStyle style);
AudioProperties();
private:
// Noncopyable. Derived classes as well.
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
}

View File

@ -32,8 +32,7 @@ class EBML::Matroska::AudioProperties::AudioPropertiesPrivate
{
public:
// Constructor
AudioPropertiesPrivate(File *p_document) :
document(p_document),
AudioPropertiesPrivate(File *document) :
length(0),
bitrate(0),
channels(1),
@ -46,7 +45,7 @@ public:
if(info && (value = info->getChild(Constants::Duration))) {
length = static_cast<int>(value->getAsFloat() / 1000000000.L);
if((value = info->getChild(Constants::TimecodeScale)))
length *= value->getAsUnsigned();
length *= static_cast<int>(value->getAsUnsigned());
else
length *= 1000000;
}
@ -69,9 +68,6 @@ public:
samplerate = static_cast<int>(value->getAsFloat());
}
// The corresponding file
File *document;
// The length of the file
int length;
@ -90,7 +86,6 @@ public:
////////////////////////////////////////////////////////////////////////////////
EBML::Matroska::AudioProperties::AudioProperties(File *document) :
TagLib::AudioProperties(TagLib::AudioProperties::Fast),
d(new AudioPropertiesPrivate(document))
{
}

View File

@ -122,7 +122,7 @@ namespace
file.reset(new MP4::File(fileName, readAudioProperties, audioPropertiesStyle));
else if(ext == "WMA" || ext == "ASF")
file.reset(new ASF::File(fileName, readAudioProperties, audioPropertiesStyle));
else if(ext == "AIF" || ext == "AIFF")
else if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
file.reset(new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle));
else if(ext == "WAV")
file.reset(new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle));

View File

@ -34,10 +34,7 @@ using namespace TagLib;
class FLAC::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(const ByteVector &d, offset_t st, ReadStyle s) :
data(d),
streamLength(st),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
@ -45,9 +42,6 @@ public:
channels(0),
sampleFrames(0) {}
ByteVector data;
offset_t streamLength;
ReadStyle style;
int length;
int bitrate;
int sampleRate;
@ -61,11 +55,11 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::AudioProperties::AudioProperties(const ByteVector &data, offset_t streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
FLAC::AudioProperties::AudioProperties(const ByteVector &data, offset_t streamLength,
ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(data, streamLength, style);
read();
read(data, streamLength);
}
FLAC::AudioProperties::~AudioProperties()
@ -112,14 +106,14 @@ ByteVector FLAC::AudioProperties::signature() const
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::AudioProperties::read()
void FLAC::AudioProperties::read(const ByteVector &data, offset_t streamLength)
{
if(d->data.size() < 18) {
if(data.size() < 18) {
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
return;
}
uint pos = 0;
size_t pos = 0;
// Minimum block size (in samples)
pos += 2;
@ -133,7 +127,7 @@ void FLAC::AudioProperties::read()
// Maximum frame size (in bytes)
pos += 3;
const uint flags = d->data.toUInt32BE(pos);
const uint flags = data.toUInt32BE(pos);
pos += 4;
d->sampleRate = flags >> 12;
@ -144,7 +138,7 @@ void FLAC::AudioProperties::read()
// stream length in samples. (Audio files measured in days)
const ulonglong hi = flags & 0xf;
const ulonglong lo = d->data.toUInt32BE(pos);
const ulonglong lo = data.toUInt32BE(pos);
pos += 4;
d->sampleFrames = (hi << 32) | lo;
@ -158,7 +152,7 @@ void FLAC::AudioProperties::read()
// Real bitrate:
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(streamLength * 8L / d->length / 1000) : 0;
d->signature = d->data.mid(pos, 32);
d->signature = data.mid(pos, 32);
}

View File

@ -46,7 +46,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of FLAC::AudioProperties with the data read from
* Creates an instance of FLAC::AudioProperties with the data read from
* the ByteVector \a data.
*/
AudioProperties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
@ -81,10 +81,7 @@ namespace TagLib {
ByteVector signature() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(const ByteVector &data, offset_t streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -42,9 +42,7 @@ public:
tempo(0),
bpmSpeed(0),
panningSeparation(0),
pitchWheelDepth(0)
{
}
pitchWheelDepth(0) {}
int channels;
ushort lengthInPatterns;
@ -63,9 +61,12 @@ public:
uchar pitchWheelDepth;
};
IT::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle)
: TagLib::AudioProperties(propertiesStyle)
, d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
IT::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle) :
d(new PropertiesPrivate())
{
}
@ -169,6 +170,10 @@ uchar IT::AudioProperties::pitchWheelDepth() const
return d->pitchWheelDepth;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void IT::AudioProperties::setChannels(int channels)
{
d->channels = channels;

View File

@ -26,9 +26,15 @@
#include "audioproperties.h"
namespace TagLib {
namespace IT {
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties {
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*! Flag bits. */
enum {
@ -72,6 +78,7 @@ namespace TagLib {
uchar panningSeparation() const;
uchar pitchWheelDepth() const;
private:
void setChannels(int channels);
void setLengthInPatterns(ushort lengthInPatterns);
void setInstrumentCount(ushort instrumentCount);
@ -88,10 +95,6 @@ namespace TagLib {
void setPanningSeparation(uchar panningSeparation);
void setPitchWheelDepth (uchar pitchWheelDepth);
private:
AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@ -30,18 +30,19 @@ public:
PropertiesPrivate() :
channels(0),
instrumentCount(0),
lengthInPatterns(0)
{
}
lengthInPatterns(0) {}
int channels;
uint instrumentCount;
uchar lengthInPatterns;
};
Mod::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle)
: TagLib::AudioProperties(propertiesStyle)
, d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Mod::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle) :
d(new PropertiesPrivate)
{
}
@ -80,6 +81,10 @@ uchar Mod::AudioProperties::lengthInPatterns() const
return d->lengthInPatterns;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void Mod::AudioProperties::setChannels(int channels)
{
d->channels = channels;

View File

@ -29,8 +29,12 @@ namespace TagLib {
namespace Mod {
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
AudioProperties(AudioProperties::ReadStyle propertiesStyle);
virtual ~AudioProperties();
@ -43,17 +47,12 @@ namespace TagLib {
uint instrumentCount() const;
uchar lengthInPatterns() const;
private:
void setChannels(int channels);
void setInstrumentCount(uint sampleCount);
void setLengthInPatterns(uchar lengthInPatterns);
private:
friend class File;
AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@ -34,7 +34,14 @@ using namespace TagLib;
class MP4::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false), format(Unknown) {}
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
encrypted(false),
format(Unknown) {}
enum Format {
Unknown = 0,
@ -51,11 +58,76 @@ public:
Format format;
};
MP4::AudioProperties::AudioProperties(File *file, MP4::Atoms *atoms, ReadStyle style)
: TagLib::AudioProperties(style)
MP4::AudioProperties::AudioProperties(File *file, MP4::Atoms *atoms, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate;
read(file, atoms);
}
MP4::AudioProperties::~AudioProperties()
{
delete d;
}
int
MP4::AudioProperties::channels() const
{
return d->channels;
}
int
MP4::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int
MP4::AudioProperties::length() const
{
return d->length;
}
int
MP4::AudioProperties::bitrate() const
{
return d->bitrate;
}
int
MP4::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
bool
MP4::AudioProperties::isEncrypted() const
{
return d->encrypted;
}
String
MP4::AudioProperties::toString() const
{
String format;
if(d->format == PropertiesPrivate::AAC) {
format = "AAC";
}
else if(d->format == PropertiesPrivate::ALAC) {
format = "ALAC";
}
else {
format = "Unknown";
}
StringList desc;
desc.append("MPEG-4 audio (" + format + ")");
desc.append(String::number(length()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}
void
MP4::AudioProperties::read(File *file, Atoms *atoms)
{
MP4::Atom *moov = atoms->find("moov");
if(!moov) {
debug("MP4: Atom 'moov' not found");
@ -156,65 +228,3 @@ MP4::AudioProperties::AudioProperties(File *file, MP4::Atoms *atoms, ReadStyle s
d->encrypted = true;
}
}
MP4::AudioProperties::~AudioProperties()
{
delete d;
}
int
MP4::AudioProperties::channels() const
{
return d->channels;
}
int
MP4::AudioProperties::sampleRate() const
{
return d->sampleRate;
}
int
MP4::AudioProperties::length() const
{
return d->length;
}
int
MP4::AudioProperties::bitrate() const
{
return d->bitrate;
}
int
MP4::AudioProperties::bitsPerSample() const
{
return d->bitsPerSample;
}
bool
MP4::AudioProperties::isEncrypted() const
{
return d->encrypted;
}
String
MP4::AudioProperties::toString() const
{
String format;
if(d->format == PropertiesPrivate::AAC) {
format = "AAC";
}
else if(d->format == PropertiesPrivate::ALAC) {
format = "ALAC";
}
else {
format = "Unknown";
}
StringList desc;
desc.append("MPEG-4 audio (" + format + ")");
desc.append(String::number(length()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}

View File

@ -53,6 +53,8 @@ namespace TagLib {
String toString() const;
private:
void read(File *file, Atoms *atoms);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@ -36,9 +36,7 @@ using namespace TagLib;
class MPC::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(offset_t length, ReadStyle s) :
streamLength(length),
style(s),
PropertiesPrivate() :
version(0),
length(0),
bitrate(0),
@ -51,8 +49,6 @@ public:
albumGain(0),
albumPeak(0) {}
offset_t streamLength;
ReadStyle style;
int version;
int length;
int bitrate;
@ -71,25 +67,17 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::AudioProperties::AudioProperties(const ByteVector &data, offset_t streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
MPC::AudioProperties::AudioProperties(File *file, offset_t streamLength, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(streamLength, style);
readSV7(data);
}
MPC::AudioProperties::AudioProperties(File *file, offset_t streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
{
d = new PropertiesPrivate(streamLength, style);
ByteVector magic = file->readBlock(4);
const ByteVector magic = file->readBlock(4);
if(magic == "MPCK") {
// Musepack version 8
readSV8(file);
readSV8(file, streamLength);
}
else {
// Musepack version 7 or older, fixed size header
readSV7(magic + file->readBlock(MPC::HeaderSize - 4));
readSV7(magic + file->readBlock(52), streamLength);
}
}
@ -190,7 +178,7 @@ namespace
static const unsigned short sftable [4] = { 44100, 48000, 37800, 32000 };
}
void MPC::AudioProperties::readSV8(File *file)
void MPC::AudioProperties::readSV8(File *file, offset_t streamLength)
{
bool readSH = false, readRG = false;
@ -219,7 +207,7 @@ void MPC::AudioProperties::readSV8(File *file)
d->channels = flags[7] * 8 + flags[6] * 4 + flags[5] * 2 + flags[4] + 1;
if((d->sampleFrames - begSilence) != 0)
d->bitrate = static_cast<int>(d->streamLength * 8.0 * d->sampleRate / (d->sampleFrames - begSilence));
d->bitrate = static_cast<int>(streamLength * 8.0 * d->sampleRate / (d->sampleFrames - begSilence));
d->bitrate = d->bitrate / 1000;
d->length = (d->sampleFrames - begSilence) / d->sampleRate;
@ -250,7 +238,7 @@ void MPC::AudioProperties::readSV8(File *file)
}
}
void MPC::AudioProperties::readSV7(const ByteVector &data)
void MPC::AudioProperties::readSV7(const ByteVector &data, offset_t streamLength)
{
if(data.startsWith("MP+")) {
d->version = data[3] & 15;
@ -316,6 +304,6 @@ void MPC::AudioProperties::readSV7(const ByteVector &data)
d->length = d->sampleRate > 0 ? (d->sampleFrames + (d->sampleRate / 2)) / d->sampleRate : 0;
if(!d->bitrate)
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(streamLength * 8L / d->length / 1000) : 0;
}

View File

@ -35,8 +35,6 @@ namespace TagLib {
class File;
static const uint HeaderSize = 8*7;
//! An implementation of audio property reading for MPC
/*!
@ -48,15 +46,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of MPC::AudioProperties with the data read from
* the ByteVector \a data.
*
* This constructor is deprecated. It only works for MPC version up to 7.
*/
AudioProperties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
/*!
* Create an instance of MPC::AudioProperties with the data read directly
* Creates an instance of MPC::AudioProperties with the data read directly
* from a MPC::File.
*/
AudioProperties(File *file, offset_t streamLength, ReadStyle style = Average);
@ -107,11 +97,8 @@ namespace TagLib {
int albumPeak() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void readSV7(const ByteVector &data);
void readSV8(File *file);
void readSV7(const ByteVector &data, offset_t streamLength);
void readSV8(File *file, offset_t streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -25,6 +25,7 @@
#include <tdebug.h>
#include <tstring.h>
#include <tsmartptr.h>
#include "mpegproperties.h"
#include "mpegfile.h"
@ -35,10 +36,7 @@ using namespace TagLib;
class MPEG::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *f, ReadStyle s) :
file(f),
xingHeader(0),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
@ -50,14 +48,7 @@ public:
isCopyrighted(false),
isOriginal(false) {}
~PropertiesPrivate()
{
delete xingHeader;
}
File *file;
XingHeader *xingHeader;
ReadStyle style;
SCOPED_PTR<XingHeader> xingHeader;
int length;
int bitrate;
int sampleRate;
@ -74,13 +65,10 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPEG::AudioProperties::AudioProperties(File *file, ReadStyle style)
: TagLib::AudioProperties(style)
MPEG::AudioProperties::AudioProperties(File *file, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, style);
if(file && file->isOpen())
read();
read(file);
}
MPEG::AudioProperties::~AudioProperties()
@ -110,7 +98,7 @@ int MPEG::AudioProperties::channels() const
const MPEG::XingHeader *MPEG::AudioProperties::xingHeader() const
{
return d->xingHeader;
return d->xingHeader.get();
}
MPEG::Header::Version MPEG::AudioProperties::version() const
@ -147,22 +135,22 @@ bool MPEG::AudioProperties::isOriginal() const
// private members
////////////////////////////////////////////////////////////////////////////////
void MPEG::AudioProperties::read()
void MPEG::AudioProperties::read(File *file)
{
// Since we've likely just looked for the ID3v1 tag, start at the end of the
// file where we're least likely to have to have to move the disk head.
offset_t last = d->file->lastFrameOffset();
offset_t last = file->lastFrameOffset();
if(last < 0) {
debug("MPEG::Properties::read() -- Could not find a valid last MPEG frame in the stream.");
return;
}
d->file->seek(last);
Header lastHeader(d->file->readBlock(4));
file->seek(last);
Header lastHeader(file->readBlock(4));
offset_t first = d->file->firstFrameOffset();
offset_t first = file->firstFrameOffset();
if(first < 0) {
debug("MPEG::Properties::read() -- Could not find a valid first MPEG frame in the stream.");
@ -175,13 +163,13 @@ void MPEG::AudioProperties::read()
while(pos > first) {
pos = d->file->previousFrameOffset(pos);
pos = file->previousFrameOffset(pos);
if(pos < 0)
break;
d->file->seek(pos);
Header header(d->file->readBlock(4));
file->seek(pos);
Header header(file->readBlock(4));
if(header.isValid()) {
lastHeader = header;
@ -193,8 +181,8 @@ void MPEG::AudioProperties::read()
// Now jump back to the front of the file and read what we need from there.
d->file->seek(first);
Header firstHeader(d->file->readBlock(4));
file->seek(first);
Header firstHeader(file->readBlock(4));
if(!firstHeader.isValid() || !lastHeader.isValid()) {
debug("MPEG::Properties::read() -- Page headers were invalid.");
@ -207,8 +195,8 @@ void MPEG::AudioProperties::read()
int xingHeaderOffset = MPEG::XingHeader::offset(firstHeader.version(),
firstHeader.channelMode());
d->file->seek(first + xingHeaderOffset);
d->xingHeader = new XingHeader(d->file->readBlock(16));
file->seek(first + xingHeaderOffset);
d->xingHeader.reset(new XingHeader(file->readBlock(16)));
// Read the length and the bitrate from the Xing header.
@ -228,8 +216,7 @@ void MPEG::AudioProperties::read()
// Since there was no valid Xing header found, we hope that we're in a constant
// bitrate file.
delete d->xingHeader;
d->xingHeader = 0;
d->xingHeader.reset();
// TODO: Make this more robust with audio property detection for VBR without a
// Xing header.
@ -243,7 +230,6 @@ void MPEG::AudioProperties::read()
}
}
d->sampleRate = firstHeader.sampleRate();
d->channels = firstHeader.channelMode() == Header::SingleChannel ? 1 : 2;
d->version = firstHeader.version();

View File

@ -49,7 +49,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of MPEG::AudioProperties with the data read from
* Creates an instance of MPEG::AudioProperties with the data read from
* the MPEG::File \a file.
*/
AudioProperties(File *file, ReadStyle style = Average);
@ -104,10 +104,7 @@ namespace TagLib {
bool isOriginal() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -29,7 +29,6 @@
#include <tstring.h>
#include <tdebug.h>
#include <oggpageheader.h>
#include "opusproperties.h"
@ -41,16 +40,12 @@ using namespace TagLib::Ogg;
class Opus::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *f, ReadStyle s) :
file(f),
style(s),
PropertiesPrivate() :
length(0),
inputSampleRate(0),
channels(0),
opusVersion(0) {}
File *file;
ReadStyle style;
int length;
int inputSampleRate;
int channels;
@ -61,11 +56,10 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
Opus::AudioProperties::AudioProperties(File *file, ReadStyle style)
: TagLib::AudioProperties(style)
Opus::AudioProperties::AudioProperties(File *file, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, style);
read();
read(file);
}
Opus::AudioProperties::~AudioProperties()
@ -110,16 +104,16 @@ int Opus::AudioProperties::opusVersion() const
// private members
////////////////////////////////////////////////////////////////////////////////
void Opus::AudioProperties::read()
void Opus::AudioProperties::read(File *file)
{
// Get the identification header from the Ogg implementation.
// http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1
ByteVector data = d->file->packet(0);
const ByteVector data = file->packet(0);
// *Magic Signature*
uint pos = 8;
size_t pos = 8;
// *Version* (8 bits, unsigned)
d->opusVersion = uchar(data.at(pos));
@ -143,12 +137,12 @@ void Opus::AudioProperties::read()
// *Channel Mapping Family* (8 bits, unsigned)
pos += 1;
const Ogg::PageHeader *first = d->file->firstPageHeader();
const Ogg::PageHeader *last = d->file->lastPageHeader();
const Ogg::PageHeader *first = file->firstPageHeader();
const Ogg::PageHeader *last = file->lastPageHeader();
if(first && last) {
long long start = first->absoluteGranularPosition();
long long end = last->absoluteGranularPosition();
const long long start = first->absoluteGranularPosition();
const long long end = last->absoluteGranularPosition();
if(start >= 0 && end >= 0)
d->length = (int) ((end - start - preSkip) / 48000);

View File

@ -51,7 +51,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of Opus::AudioProperties with the data read from
* Creates an instance of Opus::AudioProperties with the data read from
* the Opus::File \a file.
*/
AudioProperties(File *file, ReadStyle style = Average);
@ -81,10 +81,7 @@ namespace TagLib {
int opusVersion() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -29,7 +29,6 @@
#include <tstring.h>
#include <tdebug.h>
#include <oggpageheader.h>
#include "speexproperties.h"
@ -41,9 +40,7 @@ using namespace TagLib::Ogg;
class Speex::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *f, ReadStyle s) :
file(f),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
@ -52,8 +49,6 @@ public:
vbr(false),
mode(0) {}
File *file;
ReadStyle style;
int length;
int bitrate;
int sampleRate;
@ -67,11 +62,10 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
Speex::AudioProperties::AudioProperties(File *file, ReadStyle style)
: TagLib::AudioProperties(style)
Speex::AudioProperties::AudioProperties(File *file, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, style);
read();
read(file);
}
Speex::AudioProperties::~AudioProperties()
@ -108,11 +102,11 @@ int Speex::AudioProperties::speexVersion() const
// private members
////////////////////////////////////////////////////////////////////////////////
void Speex::AudioProperties::read()
void Speex::AudioProperties::read(File *file)
{
// Get the identification header from the Ogg implementation.
ByteVector data = d->file->packet(0);
const ByteVector data = file->packet(0);
size_t pos = 28;
@ -153,12 +147,12 @@ void Speex::AudioProperties::read()
// frames_per_packet; /**< Number of frames stored per Ogg packet */
// unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false);
const Ogg::PageHeader *first = d->file->firstPageHeader();
const Ogg::PageHeader *last = d->file->lastPageHeader();
const Ogg::PageHeader *first = file->firstPageHeader();
const Ogg::PageHeader *last = file->lastPageHeader();
if(first && last) {
long long start = first->absoluteGranularPosition();
long long end = last->absoluteGranularPosition();
const long long start = first->absoluteGranularPosition();
const long long end = last->absoluteGranularPosition();
if(start >= 0 && end >= 0 && d->sampleRate > 0)
d->length = (int) ((end - start) / (long long) d->sampleRate);

View File

@ -51,7 +51,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of Speex::AudioProperties with the data read from
* Creates an instance of Speex::AudioProperties with the data read from
* the Speex::File \a file.
*/
AudioProperties(File *file, ReadStyle style = Average);
@ -74,10 +74,7 @@ namespace TagLib {
int speexVersion() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -36,9 +36,7 @@ using namespace TagLib;
class Ogg::Vorbis::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(File *f, ReadStyle s) :
file(f),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
@ -48,8 +46,6 @@ public:
bitrateNominal(0),
bitrateMinimum(0) {}
File *file;
ReadStyle style;
int length;
int bitrate;
int sampleRate;
@ -65,18 +61,17 @@ namespace TagLib {
* Vorbis headers can be found with one type ID byte and the string "vorbis" in
* an Ogg stream. 0x01 indicates the setup header.
*/
static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 };
const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 };
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle style)
: TagLib::AudioProperties(style)
Ogg::Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(file, style);
read();
read(file);
}
Ogg::Vorbis::AudioProperties::~AudioProperties()
@ -137,13 +132,13 @@ String Ogg::Vorbis::AudioProperties::toString() const
// private members
////////////////////////////////////////////////////////////////////////////////
void Ogg::Vorbis::AudioProperties::read()
void Ogg::Vorbis::AudioProperties::read(File *file)
{
// Get the identification header from the Ogg implementation.
ByteVector data = d->file->packet(0);
const ByteVector data = file->packet(0);
uint pos = 0;
size_t pos = 0;
if(data.mid(pos, 7) != vorbisSetupHeaderID) {
debug("Ogg::Vorbis::Properties::read() -- invalid Ogg::Vorbis identification header");
@ -175,12 +170,12 @@ void Ogg::Vorbis::AudioProperties::read()
// Find the length of the file. See http://wiki.xiph.org/Ogg::VorbisStreamLength/
// for my notes on the topic.
const Ogg::PageHeader *first = d->file->firstPageHeader();
const Ogg::PageHeader *last = d->file->lastPageHeader();
const Ogg::PageHeader *first = file->firstPageHeader();
const Ogg::PageHeader *last = file->lastPageHeader();
if(first && last) {
long long start = first->absoluteGranularPosition();
long long end = last->absoluteGranularPosition();
const long long start = first->absoluteGranularPosition();
const long long end = last->absoluteGranularPosition();
if(start >= 0 && end >= 0 && d->sampleRate > 0)
d->length = (int)((end - start) / (long long) d->sampleRate);

View File

@ -48,7 +48,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of Vorbis::Properties with the data read from the
* Creates an instance of Vorbis::Properties with the data read from the
* Vorbis::File \a file.
*/
AudioProperties(File *file, ReadStyle style = Average);
@ -74,26 +74,29 @@ namespace TagLib {
/*!
* Returns the maximum bitrate as read from the Vorbis identification
* header.
*
* \note The value is in bits per second unlike bitrate().
*/
int bitrateMaximum() const;
/*!
* Returns the nominal bitrate as read from the Vorbis identification
* header.
*
* \note The value is in bits per second unlike bitrate().
*/
int bitrateNominal() const;
/*!
* Returns the minimum bitrate as read from the Vorbis identification
* header.
*
* \note The value is in bits per second unlike bitrate().
*/
int bitrateMinimum() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(File *file);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -38,15 +38,17 @@ public:
sampleRate(0),
channels(0),
sampleWidth(0),
sampleFrames(0)
{
}
sampleFrames(0) {}
int length;
int bitrate;
int sampleRate;
int channels;
int sampleWidth;
ByteVector compressionType;
String compressionName;
uint sampleFrames;
};
@ -54,9 +56,8 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::AIFF::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle style)
: TagLib::AudioProperties(style)
, d(new PropertiesPrivate())
RIFF::AIFF::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle style) :
d(new PropertiesPrivate())
{
read(data);
}
@ -101,12 +102,32 @@ TagLib::uint RIFF::AIFF::AudioProperties::sampleFrames() const
return d->sampleFrames;
}
bool RIFF::AIFF::AudioProperties::isAiffC() const
{
return (!d->compressionType.isEmpty());
}
ByteVector RIFF::AIFF::AudioProperties::compressionType() const
{
return d->compressionType;
}
String RIFF::AIFF::AudioProperties::compressionName() const
{
return d->compressionName;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void RIFF::AIFF::AudioProperties::read(const ByteVector &data)
{
if(data.size() < 18) {
debug("RIFF::AIFF::AudioProperties::read() - \"COMM\" chunk is too short for AIFF.");
return;
}
d->channels = data.toInt16BE(0);
d->sampleFrames = data.toUInt32BE(2);
d->sampleWidth = data.toInt16BE(6);
@ -114,4 +135,12 @@ void RIFF::AIFF::AudioProperties::read(const ByteVector &data)
d->sampleRate = static_cast<int>(sampleRate);
d->bitrate = static_cast<int>((sampleRate * d->sampleWidth * d->channels) / 1000.0);
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
if(data.size() < 23) {
debug("RIFF::AIFF::AudioProperties::read() - \"COMM\" chunk is too short for AIFF-C.");
return;
}
d->compressionType = data.mid(18, 4);
d->compressionName = String(data.mid(23, static_cast<uchar>(data[22])));
}

View File

@ -36,7 +36,7 @@ namespace TagLib {
class File;
//! An implementation of audio property reading for AIFF
//! An implementation of audio property reading for AIFF or AIFF-C
/*!
* This reads the data from an AIFF stream found in the AudioProperties
@ -47,7 +47,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of AIFF::AudioProperties with the data read from
* Creates an instance of AIFF::AudioProperties with the data read from
* the ByteVector \a data.
*/
AudioProperties(const ByteVector &data, ReadStyle style);
@ -69,6 +69,30 @@ namespace TagLib {
int sampleWidth() const;
uint sampleFrames() const;
/*!
* Returns true if the file is in AIFF-C format, false if AIFF format.
*/
bool isAiffC() const;
/*!
* Returns the compression type of the AIFF-C file. For example, "NONE" for
* not compressed, "ACE2" for ACE 2-to-1.
*
* If the file is in AIFF format, always returns an empty vector.
*
* \see isAiffC()
*/
ByteVector compressionType() const;
/*!
* Returns the concrete compression name of the AIFF-C file.
*
* If the file is in AIFF format, always returns an empty string.
*
* \see isAiffC()
*/
String compressionName() const;
private:
void read(const ByteVector &data);

View File

@ -23,30 +23,23 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "wavproperties.h"
#include <tstring.h>
#include <tdebug.h>
#include <cmath>
#include <math.h>
#include "wavproperties.h"
using namespace TagLib;
class RIFF::WAV::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(uint streamLength = 0) :
PropertiesPrivate() :
format(0),
length(0),
bitrate(0),
sampleRate(0),
channels(0),
sampleWidth(0),
sampleFrames(0),
streamLength(streamLength)
{
}
sampleFrames(0) {}
short format;
int length;
@ -55,25 +48,17 @@ public:
int channels;
int sampleWidth;
uint sampleFrames;
uint streamLength;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::WAV::AudioProperties::AudioProperties(const ByteVector &data, ReadStyle style)
: TagLib::AudioProperties(style)
RIFF::WAV::AudioProperties::AudioProperties(const ByteVector &data, uint streamLength,
ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate();
read(data);
}
RIFF::WAV::AudioProperties::AudioProperties(const ByteVector &data, uint streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
{
d = new PropertiesPrivate(streamLength);
read(data);
read(data, streamLength);
}
RIFF::WAV::AudioProperties::~AudioProperties()
@ -111,12 +96,22 @@ TagLib::uint RIFF::WAV::AudioProperties::sampleFrames() const
return d->sampleFrames;
}
TagLib::uint RIFF::WAV::AudioProperties::format() const
{
return d->format;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void RIFF::WAV::AudioProperties::read(const ByteVector &data)
void RIFF::WAV::AudioProperties::read(const ByteVector &data, uint streamLength)
{
if(data.size() < 16) {
debug("RIFF::WAV::AudioProperties::read() - \"fmt \" chunk is too short.");
return;
}
d->format = data.toInt16LE(0);
d->channels = data.toInt16LE(2);
d->sampleRate = data.toUInt32LE(4);
@ -125,7 +120,9 @@ void RIFF::WAV::AudioProperties::read(const ByteVector &data)
const uint byteRate = data.toUInt32LE(8);
d->bitrate = byteRate * 8 / 1000;
d->length = byteRate > 0 ? d->streamLength / byteRate : 0;
if(d->channels > 0 && d->sampleWidth > 0)
d->sampleFrames = d->streamLength / (d->channels * ((d->sampleWidth + 7) / 8));
d->length = byteRate > 0 ? streamLength / byteRate : 0;
// format ID 1 means uncompressed PCM.
if(d->format == 1 && d->channels > 0 && d->sampleWidth > 0)
d->sampleFrames = streamLength / (d->channels * ((d->sampleWidth + 7) / 8));
}

View File

@ -50,13 +50,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of WAV::AudioProperties with the data read from
* the ByteVector \a data.
*/
AudioProperties(const ByteVector &data, ReadStyle style);
/*!
* Create an instance of WAV::Properties with the data read from the
* Creates an instance of WAV::Properties with the data read from the
* ByteVector \a data and the length calculated using \a streamLength.
*/
AudioProperties(const ByteVector &data, uint streamLength, ReadStyle style);
@ -73,14 +67,28 @@ namespace TagLib {
virtual int sampleRate() const;
virtual int channels() const;
/*!
* Returns the count of bits per sample.
*/
int sampleWidth() const;
/*!
* Returns the total number of the samples.
*
* If the format ID is not 1, always returns 0.
*
* \see format()
*/
uint sampleFrames() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
/*!
* Returns the format ID of the WAVE file. For example, 0 for Unknown,
* 1 for PCM and so forth.
*/
uint format() const;
void read(const ByteVector &data);
private:
void read(const ByteVector &data, uint streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -39,9 +39,7 @@ public:
globalVolume(0),
masterVolume(0),
tempo(0),
bpmSpeed(0)
{
}
bpmSpeed(0) {}
ushort lengthInPatterns;
int channels;
@ -57,9 +55,12 @@ public:
uchar bpmSpeed;
};
S3M::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle)
: TagLib::AudioProperties(propertiesStyle)
, d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
S3M::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle) :
d(new PropertiesPrivate())
{
}
@ -143,6 +144,10 @@ uchar S3M::AudioProperties::bpmSpeed() const
return d->bpmSpeed;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void S3M::AudioProperties::setLengthInPatterns(ushort lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;

View File

@ -26,9 +26,15 @@
#include "audioproperties.h"
namespace TagLib {
namespace S3M {
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties {
class File;
class TAGLIB_EXPORT AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*! Flag bits. */
enum {
@ -61,6 +67,7 @@ namespace TagLib {
uchar tempo() const;
uchar bpmSpeed() const;
private:
void setChannels(int channels);
void setLengthInPatterns (ushort lengthInPatterns);
@ -75,10 +82,6 @@ namespace TagLib {
void setTempo (uchar tempo);
void setBpmSpeed (uchar bpmSpeed);
private:
AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};

View File

@ -269,13 +269,11 @@ void TrueAudio::File::read(bool readProperties, AudioProperties::ReadStyle /* pr
if(readProperties) {
if(d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2OriginalSize);
d->properties = new AudioProperties(readBlock(TrueAudio::HeaderSize),
length() - d->ID3v2OriginalSize);
d->properties = new AudioProperties(this, length() - d->ID3v2OriginalSize);
}
else {
seek(0);
d->properties = new AudioProperties(readBlock(TrueAudio::HeaderSize),
length());
d->properties = new AudioProperties(this, length());
}
}
}

View File

@ -29,7 +29,6 @@
#include <tstring.h>
#include <tdebug.h>
#include <bitset>
#include "trueaudioproperties.h"
#include "trueaudiofile.h"
@ -39,10 +38,7 @@ using namespace TagLib;
class TrueAudio::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(const ByteVector &d, offset_t length, ReadStyle s) :
data(d),
streamLength(length),
style(s),
PropertiesPrivate() :
version(0),
length(0),
bitrate(0),
@ -51,9 +47,6 @@ public:
bitsPerSample(0),
sampleFrames(0) {}
ByteVector data;
offset_t streamLength;
ReadStyle style;
int version;
int length;
int bitrate;
@ -67,12 +60,10 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
TrueAudio::AudioProperties::AudioProperties(
const ByteVector &data, offset_t streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
TrueAudio::AudioProperties::AudioProperties(File *file, offset_t streamLength, ReadStyle style) :
d(new PropertiesPrivate())
{
d = new PropertiesPrivate(data, streamLength, style);
read();
read(file, streamLength);
}
TrueAudio::AudioProperties::~AudioProperties()
@ -119,14 +110,15 @@ int TrueAudio::AudioProperties::ttaVersion() const
// private members
////////////////////////////////////////////////////////////////////////////////
void TrueAudio::AudioProperties::read()
void TrueAudio::AudioProperties::read(File *file, offset_t streamLength)
{
if(!d->data.startsWith("TTA"))
const ByteVector data = file->readBlock(18);
if(!data.startsWith("TTA"))
return;
int pos = 3;
size_t pos = 3;
d->version = d->data[pos] - '0';
d->version = data[pos] - '0';
pos += 1;
// According to http://en.true-audio.com/TTA_Lossless_Audio_Codec_-_Format_Description
@ -135,18 +127,18 @@ void TrueAudio::AudioProperties::read()
// Skip the audio format
pos += 2;
d->channels = d->data.toInt16LE(pos);
d->channels = data.toInt16LE(pos);
pos += 2;
d->bitsPerSample = d->data.toInt16LE(pos);
d->bitsPerSample = data.toInt16LE(pos);
pos += 2;
d->sampleRate = d->data.toUInt32LE(pos);
d->sampleRate = data.toUInt32LE(pos);
pos += 4;
d->sampleFrames = d->data.toUInt32LE(pos);
d->sampleFrames = data.toUInt32LE(pos);
d->length = d->sampleRate > 0 ? d->sampleFrames / d->sampleRate : 0;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(streamLength * 8L / d->length / 1000) : 0;
}
}

View File

@ -38,8 +38,6 @@ namespace TagLib {
class File;
static const uint HeaderSize = 18;
//! An implementation of audio property reading for TrueAudio
/*!
@ -51,10 +49,10 @@ namespace TagLib {
{
public:
/*!
* Create an instance of TrueAudio::AudioProperties with the data read from
* Creates an instance of TrueAudio::AudioProperties with the data read from
* the ByteVector \a data.
*/
AudioProperties(const ByteVector &data, offset_t streamLength, ReadStyle style = Average);
AudioProperties(File *file, offset_t streamLength, ReadStyle style = Average);
/*!
* Destroys this TrueAudio::AudioProperties instance.
@ -84,10 +82,7 @@ namespace TagLib {
int ttaVersion() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
void read(File *file, offset_t streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -38,22 +38,15 @@ using namespace TagLib;
class WavPack::AudioProperties::PropertiesPrivate
{
public:
PropertiesPrivate(const ByteVector &d, offset_t length, ReadStyle s, File *f) :
data(d),
streamLength(length),
style(s),
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
version(0),
bitsPerSample(0),
sampleFrames(0),
file(f) {}
sampleFrames(0) {}
ByteVector data;
offset_t streamLength;
ReadStyle style;
int length;
int bitrate;
int sampleRate;
@ -61,19 +54,16 @@ public:
int version;
int bitsPerSample;
uint sampleFrames;
File *file;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
WavPack::AudioProperties::AudioProperties(File *file, offset_t streamLength, ReadStyle style)
: TagLib::AudioProperties(style)
WavPack::AudioProperties::AudioProperties(File *file, offset_t streamLength, ReadStyle style) :
d(new PropertiesPrivate())
{
ByteVector data = file->readBlock(32);
d = new PropertiesPrivate(data, streamLength, style, file);
read();
read(file, streamLength, style);
}
WavPack::AudioProperties::~AudioProperties()
@ -140,25 +130,26 @@ namespace
#define FINAL_BLOCK 0x1000
void WavPack::AudioProperties::read()
void WavPack::AudioProperties::read(File *file, offset_t streamLength, ReadStyle style)
{
if(!d->data.startsWith("wvpk"))
const ByteVector data = file->readBlock(32);
if(!data.startsWith("wvpk"))
return;
d->version = d->data.toInt16LE(8);
d->version = data.toInt16LE(8);
if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS)
return;
const uint flags = d->data.toUInt32LE(24);
const uint flags = data.toUInt32LE(24);
d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 -
((flags & SHIFT_MASK) >> SHIFT_LSB);
d->sampleRate = sample_rates[(flags & SRATE_MASK) >> SRATE_LSB];
d->channels = (flags & MONO_FLAG) ? 1 : 2;
uint samples = d->data.toUInt32LE(12);
uint samples = data.toUInt32LE(12);
if(samples == ~0u) {
if(d->style != Fast) {
samples = seekFinalIndex();
if(style != Fast) {
samples = seekFinalIndex(file, streamLength);
}
else {
samples = 0;
@ -167,20 +158,20 @@ void WavPack::AudioProperties::read()
d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
d->sampleFrames = samples;
d->bitrate = d->length > 0 ? static_cast<int>(d->streamLength * 8L / d->length / 1000) : 0;
d->bitrate = d->length > 0 ? static_cast<int>(streamLength * 8L / d->length / 1000) : 0;
}
unsigned int WavPack::AudioProperties::seekFinalIndex()
unsigned int WavPack::AudioProperties::seekFinalIndex(File *file, offset_t streamLength)
{
ByteVector blockID("wvpk", 4);
offset_t offset = d->streamLength;
offset_t offset = streamLength;
while(offset > 0) {
offset = d->file->rfind(blockID, offset);
offset = file->rfind(blockID, offset);
if(offset == -1)
return 0;
d->file->seek(offset);
ByteVector data = d->file->readBlock(32);
file->seek(offset);
ByteVector data = file->readBlock(32);
if(data.size() != 32)
return 0;
const int version = data.toInt16LE(8);

View File

@ -52,7 +52,7 @@ namespace TagLib {
{
public:
/*!
* Create an instance of WavPack::AudioProperties.
* Creates an instance of WavPack::AudioProperties.
*/
AudioProperties(File *file, offset_t streamLength, ReadStyle style = Average);
@ -80,11 +80,8 @@ namespace TagLib {
int version() const;
private:
AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read();
unsigned int seekFinalIndex();
void read(File *file, offset_t streamLength, ReadStyle style);
unsigned int seekFinalIndex(File *file, offset_t streamLength);
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -37,9 +37,7 @@ public:
sampleCount(0),
flags(0),
tempo(0),
bpmSpeed(0)
{
}
bpmSpeed(0) {}
ushort lengthInPatterns;
int channels;
@ -53,9 +51,12 @@ public:
ushort bpmSpeed;
};
XM::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle)
: TagLib::AudioProperties(propertiesStyle)
, d(new PropertiesPrivate)
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
XM::AudioProperties::AudioProperties(AudioProperties::ReadStyle propertiesStyle) :
d(new PropertiesPrivate())
{
}
@ -129,6 +130,10 @@ TagLib::ushort XM::AudioProperties::bpmSpeed() const
return d->bpmSpeed;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void XM::AudioProperties::setLengthInPatterns(ushort lengthInPatterns)
{
d->lengthInPatterns = lengthInPatterns;

View File

@ -27,9 +27,15 @@
#include "audioproperties.h"
namespace TagLib {
namespace XM {
class AudioProperties : public TagLib::AudioProperties {
class File;
class AudioProperties : public TagLib::AudioProperties
{
friend class File;
public:
/*! Flag bits. */
enum {
@ -54,6 +60,7 @@ namespace TagLib {
ushort tempo() const;
ushort bpmSpeed() const;
private:
void setChannels(int channels);
void setLengthInPatterns(ushort lengthInPatterns);
@ -66,10 +73,6 @@ namespace TagLib {
void setTempo(ushort tempo);
void setBpmSpeed(ushort bpmSpeed);
private:
AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
class PropertiesPrivate;
PropertiesPrivate *d;
};