mirror of
https://github.com/taglib/taglib.git
synced 2025-07-27 09:24:25 -04:00
Merge branch 'master' into taglib2
Conflicts: CMakeLists.txt ConfigureChecks.cmake config.h.cmake taglib/CMakeLists.txt taglib/ape/apefile.cpp taglib/ape/apefile.h taglib/ape/apeproperties.cpp taglib/ape/apeproperties.h taglib/ape/apetag.cpp taglib/asf/asfattribute.cpp taglib/asf/asffile.cpp taglib/asf/asffile.h taglib/asf/asfpicture.cpp taglib/asf/asfpicture.h taglib/asf/asfproperties.cpp taglib/asf/asfproperties.h taglib/audioproperties.cpp taglib/flac/flacfile.cpp taglib/flac/flacfile.h taglib/flac/flacproperties.cpp taglib/flac/flacproperties.h taglib/it/itproperties.cpp taglib/mod/modproperties.cpp taglib/mp4/mp4atom.cpp taglib/mp4/mp4file.cpp taglib/mp4/mp4file.h taglib/mp4/mp4properties.cpp taglib/mp4/mp4tag.cpp taglib/mp4/mp4tag.h taglib/mpc/mpcfile.cpp taglib/mpc/mpcfile.h taglib/mpc/mpcproperties.cpp taglib/mpc/mpcproperties.h taglib/mpeg/id3v2/frames/chapterframe.cpp taglib/mpeg/id3v2/frames/synchronizedlyricsframe.cpp taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp taglib/mpeg/mpegfile.cpp taglib/mpeg/mpegfile.h taglib/mpeg/mpegheader.cpp taglib/mpeg/mpegproperties.cpp taglib/mpeg/mpegproperties.h taglib/mpeg/xingheader.cpp taglib/mpeg/xingheader.h taglib/ogg/opus/opusfile.cpp taglib/ogg/opus/opusfile.h taglib/ogg/opus/opusproperties.cpp taglib/ogg/opus/opusproperties.h taglib/ogg/speex/speexfile.cpp taglib/ogg/speex/speexfile.h taglib/ogg/speex/speexproperties.cpp taglib/ogg/speex/speexproperties.h taglib/ogg/vorbis/vorbisfile.cpp taglib/ogg/vorbis/vorbisfile.h taglib/ogg/vorbis/vorbisproperties.cpp taglib/ogg/vorbis/vorbisproperties.h taglib/riff/aiff/aifffile.cpp taglib/riff/aiff/aifffile.h taglib/riff/aiff/aiffproperties.cpp taglib/riff/aiff/aiffproperties.h taglib/riff/wav/infotag.h taglib/riff/wav/wavfile.cpp taglib/riff/wav/wavfile.h taglib/riff/wav/wavproperties.cpp taglib/riff/wav/wavproperties.h taglib/s3m/s3mproperties.cpp taglib/taglib_config.h.cmake taglib/toolkit/tbytevector.cpp taglib/toolkit/tfile.cpp taglib/toolkit/tfile.h taglib/toolkit/tfilestream.cpp taglib/toolkit/trefcounter.cpp taglib/toolkit/tstring.cpp taglib/toolkit/tstring.h taglib/toolkit/tutils.h taglib/trueaudio/trueaudiofile.cpp taglib/trueaudio/trueaudiofile.h taglib/trueaudio/trueaudioproperties.cpp taglib/trueaudio/trueaudioproperties.h taglib/wavpack/wavpackfile.cpp taglib/wavpack/wavpackfile.h taglib/wavpack/wavpackproperties.cpp taglib/wavpack/wavpackproperties.h taglib/xm/xmproperties.cpp taglib/xm/xmproperties.h tests/CMakeLists.txt tests/data/alaw.wav tests/test_asf.cpp tests/test_mp4.cpp tests/test_ogg.cpp tests/test_opus.cpp tests/test_string.cpp tests/test_wav.cpp tests/test_wavpack.cpp
This commit is contained in:
@ -42,7 +42,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* This is implementation of FLAC metadata for Ogg FLAC files. For "pure"
|
||||
* FLAC files look under the FLAC hiearchy.
|
||||
* FLAC files look under the FLAC hierarchy.
|
||||
*
|
||||
* Unlike "pure" FLAC-files, Ogg FLAC only supports Xiph-comments,
|
||||
* while the audio-properties are the same.
|
||||
@ -64,7 +64,7 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs an Ogg/FLAC file from \a file. If \a readProperties is true
|
||||
* Constructs an Ogg/FLAC file from \a file. If \a readProperties is true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
@ -73,7 +73,7 @@ namespace TagLib {
|
||||
AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true
|
||||
* Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
@ -92,10 +92,10 @@ namespace TagLib {
|
||||
/*!
|
||||
* Returns the Tag for this file. This will always be a XiphComment.
|
||||
*
|
||||
* \note This always returns a valid pointer regardless of whether or not
|
||||
* the file on disk has a XiphComment. Use hasXiphComment() to check if
|
||||
* \note This always returns a valid pointer regardless of whether or not
|
||||
* the file on disk has a XiphComment. Use hasXiphComment() to check if
|
||||
* the file on disk actually has a XiphComment.
|
||||
*
|
||||
*
|
||||
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
|
||||
* deleted by the user. It will be deleted when the file (object) is
|
||||
* destroyed.
|
||||
@ -111,22 +111,25 @@ namespace TagLib {
|
||||
virtual AudioProperties *audioProperties() const;
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This forwards directly to XiphComment::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified tag dictionary interface -- import function.
|
||||
* Like properties(), this is a forwarder to the file's XiphComment.
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
|
||||
/*!
|
||||
* Save the file. This will primarily save and update the XiphComment.
|
||||
* Returns true if the save is successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace TagLib {
|
||||
/*!
|
||||
* This is an implementation of the pages that make up an Ogg stream.
|
||||
* This handles parsing pages and breaking them down into packets and handles
|
||||
* the details of packets spanning multiple pages and pages that contiain
|
||||
* the details of packets spanning multiple pages and pages that contain
|
||||
* multiple packets.
|
||||
*
|
||||
* In most Xiph.org formats the comments are found in the first few packets,
|
||||
@ -162,7 +162,7 @@ namespace TagLib {
|
||||
|
||||
/*!
|
||||
* Pack \a packets into Ogg pages using the \a strategy for pagination.
|
||||
* The page number indicater inside of the rendered packets will start
|
||||
* The page number indicator inside of the rendered packets will start
|
||||
* with \a firstPage and be incremented for each page rendered.
|
||||
* \a containsLastPacket should be set to true if \a packets contains the
|
||||
* last page in the stream and will set the appropriate flag in the last
|
||||
|
@ -27,8 +27,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
@ -59,20 +57,20 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Opus::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle propertiesStyle) :
|
||||
Opus::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Opus::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle propertiesStyle) :
|
||||
Opus::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Opus::File::~File()
|
||||
@ -114,7 +112,7 @@ bool Opus::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Opus::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
|
||||
void Opus::File::read(bool readProperties)
|
||||
{
|
||||
ByteVector opusHeaderData = packet(0);
|
||||
|
||||
@ -135,5 +133,5 @@ void Opus::File::read(bool readProperties, AudioProperties::ReadStyle properties
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData.mid(8));
|
||||
|
||||
if(readProperties)
|
||||
d->properties = new AudioProperties(this, propertiesStyle);
|
||||
d->properties = new AudioProperties(this);
|
||||
}
|
||||
|
@ -106,13 +106,21 @@ namespace TagLib {
|
||||
*/
|
||||
virtual AudioProperties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
@ -58,7 +58,8 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Opus::AudioProperties::AudioProperties(File *file, ReadStyle style) :
|
||||
Opus::AudioProperties::AudioProperties(File *file, ReadStyle) :
|
||||
TagLib::AudioProperties(),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
read(file);
|
||||
@ -70,6 +71,16 @@ Opus::AudioProperties::~AudioProperties()
|
||||
}
|
||||
|
||||
int Opus::AudioProperties::length() const
|
||||
{
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Opus::AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Opus::AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
@ -147,8 +158,13 @@ void Opus::AudioProperties::read(File *file)
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
|
||||
if(start >= 0 && end >= 0) {
|
||||
d->length = (int)((end - start - preSkip) / 48000);
|
||||
d->bitrate = (int)(file->length() * 8.0 / (1000.0 * d->length) + 0.5);
|
||||
const long long frameCount = (end - start - preSkip);
|
||||
|
||||
if(frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / 48000.0;
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Opus::Properties::read() -- The PCM values for the start or "
|
||||
|
@ -51,7 +51,7 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Creates 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);
|
||||
@ -61,11 +61,49 @@ namespace TagLib {
|
||||
*/
|
||||
virtual ~AudioProperties();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \note This method is just an alias of lengthInSeconds().
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
virtual int length() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*
|
||||
* \note Always returns 48000, because Opus can decode any stream at a
|
||||
* sample rate of 8, 12, 16, 24, or 48 kHz,
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
@ -76,7 +114,7 @@ namespace TagLib {
|
||||
int inputSampleRate() const;
|
||||
|
||||
/*!
|
||||
* Returns the Opus version, currently "0" (as specified by the spec).
|
||||
* Returns the Opus version, in the range 0...255.
|
||||
*/
|
||||
int opusVersion() const;
|
||||
|
||||
|
@ -27,8 +27,6 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
@ -59,20 +57,20 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Speex::File::File(FileName file, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) : Ogg::File(file)
|
||||
Speex::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Speex::File::File(IOStream *stream, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) : Ogg::File(stream)
|
||||
Speex::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Speex::File::~File()
|
||||
@ -114,7 +112,7 @@ bool Speex::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Speex::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
|
||||
void Speex::File::read(bool readProperties)
|
||||
{
|
||||
ByteVector speexHeaderData = packet(0);
|
||||
|
||||
@ -128,5 +126,5 @@ void Speex::File::read(bool readProperties, AudioProperties::ReadStyle propertie
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData);
|
||||
|
||||
if(readProperties)
|
||||
d->properties = new AudioProperties(this, propertiesStyle);
|
||||
d->properties = new AudioProperties(this);
|
||||
}
|
||||
|
@ -106,15 +106,21 @@ namespace TagLib {
|
||||
*/
|
||||
virtual AudioProperties *audioProperties() const;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
PropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
bitrateNominal(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
speexVersion(0),
|
||||
@ -51,6 +52,7 @@ public:
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
int bitrateNominal;
|
||||
int sampleRate;
|
||||
int channels;
|
||||
int speexVersion;
|
||||
@ -62,7 +64,8 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Speex::AudioProperties::AudioProperties(File *file, ReadStyle style) :
|
||||
Speex::AudioProperties::AudioProperties(File *file, ReadStyle) :
|
||||
TagLib::AudioProperties(),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
read(file);
|
||||
@ -74,13 +77,28 @@ Speex::AudioProperties::~AudioProperties()
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::length() const
|
||||
{
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::bitrate() const
|
||||
{
|
||||
return int(float(d->bitrate) / float(1000) + 0.5);
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::bitrateNominal() const
|
||||
{
|
||||
return d->bitrateNominal;
|
||||
}
|
||||
|
||||
int Speex::AudioProperties::sampleRate() const
|
||||
@ -107,6 +125,10 @@ void Speex::AudioProperties::read(File *file)
|
||||
// Get the identification header from the Ogg implementation.
|
||||
|
||||
const ByteVector data = file->packet(0);
|
||||
if(data.size() < 64) {
|
||||
debug("Speex::Properties::read() -- data is too short.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = 28;
|
||||
|
||||
@ -133,7 +155,7 @@ void Speex::AudioProperties::read(File *file)
|
||||
pos += 4;
|
||||
|
||||
// bitrate; /**< Bit-rate used */
|
||||
d->bitrate = data.toUInt32LE(pos);
|
||||
d->bitrateNominal = data.toUInt32LE(pos);
|
||||
pos += 4;
|
||||
|
||||
// frame_size; /**< Size of frames */
|
||||
@ -154,12 +176,25 @@ void Speex::AudioProperties::read(File *file)
|
||||
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);
|
||||
else
|
||||
if(start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
const long long frameCount = end - start;
|
||||
|
||||
if(frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / d->sampleRate;
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Speex::Properties::read() -- Either the PCM values for the start or "
|
||||
"end of this file was incorrect or the sample rate is zero.");
|
||||
}
|
||||
}
|
||||
else
|
||||
debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages.");
|
||||
|
||||
// Alternative to the actual average bitrate.
|
||||
|
||||
if(d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Creates 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);
|
||||
@ -61,11 +61,51 @@ namespace TagLib {
|
||||
*/
|
||||
virtual ~AudioProperties();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \note This method is just an alias of lengthInSeconds().
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
virtual int length() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
* Returns the nominal bit rate as read from the Speex header in kb/s.
|
||||
*/
|
||||
int bitrateNominal() const;
|
||||
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
|
@ -63,20 +63,20 @@ namespace TagLib {
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::Vorbis::File::File(FileName file, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) : Ogg::File(file)
|
||||
Ogg::Vorbis::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Ogg::Vorbis::File::File(IOStream *stream, bool readProperties,
|
||||
AudioProperties::ReadStyle propertiesStyle) : Ogg::File(stream)
|
||||
Ogg::Vorbis::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Ogg::Vorbis::File::~File()
|
||||
@ -121,7 +121,7 @@ bool Ogg::Vorbis::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Ogg::Vorbis::File::read(bool readProperties, AudioProperties::ReadStyle propertiesStyle)
|
||||
void Ogg::Vorbis::File::read(bool readProperties)
|
||||
{
|
||||
ByteVector commentHeaderData = packet(1);
|
||||
|
||||
@ -134,5 +134,5 @@ void Ogg::Vorbis::File::read(bool readProperties, AudioProperties::ReadStyle pro
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData.mid(7));
|
||||
|
||||
if(readProperties)
|
||||
d->properties = new AudioProperties(this, propertiesStyle);
|
||||
d->properties = new AudioProperties(this);
|
||||
}
|
||||
|
@ -105,13 +105,21 @@ namespace TagLib {
|
||||
*/
|
||||
virtual AudioProperties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
|
@ -68,7 +68,8 @@ namespace TagLib {
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle style) :
|
||||
Ogg::Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle) :
|
||||
TagLib::AudioProperties(),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
read(file);
|
||||
@ -80,13 +81,23 @@ Ogg::Vorbis::AudioProperties::~AudioProperties()
|
||||
}
|
||||
|
||||
int Ogg::Vorbis::AudioProperties::length() const
|
||||
{
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Ogg::Vorbis::AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Ogg::Vorbis::AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int Ogg::Vorbis::AudioProperties::bitrate() const
|
||||
{
|
||||
return int(float(d->bitrate) / float(1000) + 0.5);
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int Ogg::Vorbis::AudioProperties::sampleRate() const
|
||||
@ -137,6 +148,10 @@ void Ogg::Vorbis::AudioProperties::read(File *file)
|
||||
// Get the identification header from the Ogg implementation.
|
||||
|
||||
const ByteVector data = file->packet(0);
|
||||
if(data.size() < 28) {
|
||||
debug("Vorbis::Properties::read() -- data is too short.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
@ -163,9 +178,7 @@ void Ogg::Vorbis::AudioProperties::read(File *file)
|
||||
pos += 4;
|
||||
|
||||
d->bitrateMinimum = data.toUInt32LE(pos);
|
||||
|
||||
// TODO: Later this should be only the "fast" mode.
|
||||
d->bitrate = d->bitrateNominal;
|
||||
pos += 4;
|
||||
|
||||
// Find the length of the file. See http://wiki.xiph.org/Ogg::VorbisStreamLength/
|
||||
// for my notes on the topic.
|
||||
@ -177,12 +190,26 @@ void Ogg::Vorbis::AudioProperties::read(File *file)
|
||||
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);
|
||||
else
|
||||
debug("Ogg::Vorbis::Properties::read() -- Either the PCM values for the start or "
|
||||
if(start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
const long long frameCount = end - start;
|
||||
|
||||
if(frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / d->sampleRate;
|
||||
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Vorbis::Properties::read() -- Either the PCM values for the start or "
|
||||
"end of this file was incorrect or the sample rate is zero.");
|
||||
}
|
||||
}
|
||||
else
|
||||
debug("Ogg::Vorbis::Properties::read() -- Could not find valid first and last Ogg pages.");
|
||||
debug("Vorbis::Properties::read() -- Could not find valid first and last Ogg pages.");
|
||||
|
||||
// Alternative to the actual average bitrate.
|
||||
|
||||
if(d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
|
||||
}
|
||||
|
@ -58,11 +58,46 @@ namespace TagLib {
|
||||
*/
|
||||
virtual ~AudioProperties();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \note This method is just an alias of lengthInSeconds().
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
virtual int length() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
virtual String toString() const;
|
||||
|
||||
|
Reference in New Issue
Block a user