mirror of
https://github.com/taglib/taglib.git
synced 2026-04-05 21:52:43 -04:00
Refactored AudioProperties classes in some ways
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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(", ");
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,8 @@ namespace TagLib {
|
||||
String toString() const;
|
||||
|
||||
private:
|
||||
void read(File *file, Atoms *atoms);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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])));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user