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:
Tsuda Kageyu
2015-08-10 00:24:20 +09:00
178 changed files with 4703 additions and 2281 deletions

View File

@ -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();

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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 "

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
/*!

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;